"+b;a.removeChild(a.firstChild);bb(this,a.childNodes);this.remove()}else bb(this,b)}function cb(b){return b.cloneNode(!0)}function sa(b){sb(b);for(var a=0,b=b.childNodes||[];a-1}function vb(b,a){a&&m(a.split(" "),function(a){b.className=
+R((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," "))})}function wb(b,a){a&&m(a.split(" "),function(a){if(!Ca(b,a))b.className=R(b.className+" "+R(a))})}function bb(b,a){if(a)for(var a=!a.nodeName&&v(a.length)&&!oa(a)?a:[a],c=0;c4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"),W.length>20&&c.warn("Cookie '"+a+"' possibly not set or overflowed because too many cookies were already set ("+W.length+
+" > 20 )")}else{if(h.cookie!==y){y=h.cookie;d=y.split("; ");W={};for(f=0;f0&&(W[unescape(e.substring(0,k))]=unescape(e.substring(k+1)))}return W}};f.defer=function(a,b){var c;n++;c=l(function(){delete r[c];e(a)},b||0);r[c]=!0;return c};f.defer.cancel=function(a){return r[a]?(delete r[a],o(a),e(D),!0):!1}}function wc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new vc(b,d,a,c)}]}function xc(){this.$get=function(){function b(b,
+d){function e(a){if(a!=l){if(o){if(o==a)o=a.n}else o=a;g(a.n,a.p);g(a,l);l=a;l.n=null}}function g(a,b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw B("cacheId "+b+" taken");var i=0,f=x({},d,{id:b}),h={},k=d&&d.capacity||Number.MAX_VALUE,j={},l=null,o=null;return a[b]={put:function(a,b){var c=j[a]||(j[a]={key:a});e(c);t(b)||(a in h||i++,h[a]=b,i>k&&this.remove(o.key))},get:function(a){var b=j[a];if(b)return e(b),h[a]},remove:function(a){var b=j[a];if(b){if(b==l)l=b.p;if(b==o)o=b.n;g(b.n,b.p);delete j[a];
+delete h[a];i--}},removeAll:function(){h={};i=0;j={};l=o=null},destroy:function(){j=f=h=null;delete a[b]},info:function(){return x({},f,{size:i})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function yc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Bb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g="Template must have exactly one root element. was: ";
+this.directive=function f(d,e){F(d)?(qa(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];m(a[d],function(a){try{var f=b.invoke(a);if(N(f))f={compile:I(f)};else if(!f.compile&&f.link)f.compile=I(f.link);f.priority=f.priority||0;f.name=f.name||d;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(k){c(k)}});return e}])),a[d].push(e)):m(d,mb(f));return this};this.$get=["$injector","$interpolate","$exceptionHandler",
+"$http","$templateCache","$parse","$controller","$rootScope",function(b,h,k,j,l,o,r,n){function w(a,b,c){a instanceof u||(a=u(a));m(a,function(b,c){b.nodeType==3&&(a[c]=u(b).wrap("").parent()[0])});var d=s(a,b,a,c);return function(b,c){qa(b,"scope");var e=c?ua.clone.call(a):a;e.data("$scope",b);q(e,"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}function q(a,b){try{a.addClass(b)}catch(c){}}function s(a,b,c,d){function e(a,c,d,k){for(var g,h,j,n,o,l=0,r=0,q=f.length;lz.priority)break;if(Y=z.scope)M("isolated scope",C,z,y),L(Y)&&(q(y,"ng-isolate-scope"),C=z),q(y,"ng-scope"),s=s||z;H=z.name;if(Y=z.controller)t=t||{},M("'"+H+"' controller",t[H],z,y),t[H]=z;if(Y=z.transclude)M("transclusion",D,z,y),D=z,n=z.priority,Y=="element"?(X=u(b),y=c.$$element=u("<\!-- "+H+": "+c[H]+" --\>"),b=y[0],Ga(e,u(X[0]),b),v=w(X,d,n)):(X=u(cb(b)).contents(),y.html(""),v=w(X,d));if(Y=z.template)if(M("template",A,z,y),A=z,Y=Ha(Y),z.replace){X=u("
"+R(Y)+"
").contents();
+b=X[0];if(X.length!=1||b.nodeType!==1)throw new B(g+Y);Ga(e,y,b);H={$attr:{}};a=a.concat(O(b,a.splice(E+1,a.length-(E+1)),H));K(c,H);G=a.length}else y.html(Y);if(z.templateUrl)M("template",A,z,y),A=z,j=W(a.splice(E,a.length-E),j,y,c,e,z.replace,v),G=a.length;else if(z.compile)try{x=z.compile(y,c,v),N(x)?f(null,x):x&&f(x.pre,x.post)}catch(I){k(I,pa(y))}if(z.terminal)j.terminal=!0,n=Math.max(n,z.priority)}j.scope=s&&s.scope;j.transclude=D&&v;return j}function A(d,e,g,h){var j=!1;if(a.hasOwnProperty(e))for(var n,
+e=b.get(e+c),o=0,l=e.length;on.priority)&&n.restrict.indexOf(g)!=-1)d.push(n),j=!0}catch(r){k(r)}return j}function K(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){f=="class"?(q(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):f=="style"?e.attr("style",e.attr("style")+";"+b):f.charAt(0)!="$"&&!a.hasOwnProperty(f)&&(a[f]=b,d[f]=c[f])})}function W(a,b,c,d,e,
+f,k){var h=[],n,o,r=c[0],q=a.shift(),w=x({},q,{controller:null,templateUrl:null,transclude:null,scope:null});c.html("");j.get(q.templateUrl,{cache:l}).success(function(j){var l,q,j=Ha(j);if(f){q=u("
"+R(j)+"
").contents();l=q[0];if(q.length!=1||l.nodeType!==1)throw new B(g+j);j={$attr:{}};Ga(e,c,l);O(l,a,j);K(d,j)}else l=r,c.html(j);a.unshift(w);n=C(a,c,d,k);for(o=s(c.contents(),k);h.length;){var ba=h.pop(),j=h.pop();q=h.pop();var y=h.pop(),m=l;q!==r&&(m=cb(l),Ga(j,u(q),m));n(function(){b(o,
+y,m,e,ba)},y,m,e,ba)}h=null}).error(function(a,b,c,d){throw B("Failed to load template: "+d.url);});return function(a,c,d,e,f){h?(h.push(c),h.push(d),h.push(e),h.push(f)):n(function(){b(o,c,d,e,f)},c,d,e,f)}}function y(a,b){return b.priority-a.priority}function M(a,b,c,d){if(b)throw B("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+pa(d));}function H(a,b){var c=h(b,!0);c&&a.push({priority:0,compile:I(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);q(d.data("$binding",
+e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function X(a,b,c,d){var e=h(c,!0);e&&b.push({priority:100,compile:I(function(a,b,c){b=c.$$observers||(c.$$observers={});d==="class"&&(e=h(c[d],!0));c[d]=p;(b[d]||(b[d]=[])).$$inter=!0;(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function Ga(a,b,c){var d=b[0],e=d.parentNode,f,g;if(a){f=0;for(g=a.length;f0){var e=M[0],f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return!1}function f(b,c,d,f){return(b=i(b,c,d,f))?(a&&!b.json&&e("is not valid json",b),M.shift(),b):!1}function h(a){f(a)||e("is unexpected, expecting ["+a+"]",i())}function k(a,b){return function(c,d){return a(c,d,b)}}function j(a,b,c){return function(d,e){return b(d,e,a,c)}}function l(){for(var a=[];;)if(M.length>0&&!i("}",")",";","]")&&a.push(v()),!f(";"))return a.length==1?a[0]:function(b,c){for(var d,
+e=0;e","<=",">="))a=j(a,b.fn,q());return a}function s(){for(var a=m(),b;b=f("*","/","%");)a=j(a,b.fn,m());return a}function m(){var a;return f("+")?C():(a=f("-"))?j(W,a.fn,m()):(a=f("!"))?k(a.fn,m()):C()}function C(){var a;if(f("("))a=v(),h(")");else if(f("["))a=A();else if(f("{"))a=K();else{var b=f();(a=b.fn)||e("not a primary expression",b)}for(var c;b=f("(","[",".");)b.text==="("?(a=u(a,c),c=null):b.text==="["?(c=a,a=ea(a)):b.text==="."?(c=a,a=t(a)):e("IMPOSSIBLE");
+return a}function A(){var a=[];if(g().text!="]"){do a.push(H());while(f(","))}h("]");return function(b,c){for(var d=[],e=0;e1;d++){var e=a.shift(),g=
+b[e];g||(g={},b[e]=g);b=g}return b[a.shift()]=c}function fb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,g=a.length,i=0;i7),hasEvent:function(c){if(c=="input"&&aa==9)return!1;if(t(a[c])){var e=b.document.createElement("div");a[c]="on"+c in e}return a[c]},csp:!1}}]}function Uc(){this.$get=I(U)}function Mb(b){var a={},c,d,e;if(!b)return a;m(b.split("\n"),function(b){e=b.indexOf(":");c=E(R(b.substr(0,
+e)));d=R(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Nb(b){var a=L(b)?b:p;return function(c){a||(a=Mb(b));return c?a[E(c)]||null:a}}function Ob(b,a,c){if(N(c))return c(b,a);m(c,function(c){b=c(b,a)});return b}function Vc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){F(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=nb(d,!0)));return d}],transformRequest:[function(a){return L(a)&&Sa.apply(a)!=="[object File]"?da(a):a}],
+headers:{common:{Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}}},e=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,h,k,j){function l(a){function c(a){var b=x({},a,{data:Ob(a.data,a.headers,f)});return 200<=a.status&&a.status<300?b:k.reject(b)}a.method=la(a.method);var e=a.transformRequest||
+d.transformRequest,f=a.transformResponse||d.transformResponse,h=d.headers,h=x({"X-XSRF-TOKEN":b.cookies()["XSRF-TOKEN"]},h.common,h[E(a.method)],a.headers),e=Ob(a.data,Nb(h),e),g;t(a.data)&&delete h["Content-Type"];g=o(a,e,h);g=g.then(c,c);m(w,function(a){g=a(g)});g.success=function(b){g.then(function(c){b(c.data,c.status,c.headers,a)});return g};g.error=function(b){g.then(null,function(c){b(c.data,c.status,c.headers,a)});return g};return g}function o(b,c,d){function e(a,b,c){m&&(200<=a&&a<300?m.put(w,
+[a,b,Mb(c)]):m.remove(w));f(b,a,c);h.$apply()}function f(a,c,d){c=Math.max(c,0);(200<=c&&c<300?j.resolve:j.reject)({data:a,status:c,headers:Nb(d),config:b})}function i(){var a=za(l.pendingRequests,b);a!==-1&&l.pendingRequests.splice(a,1)}var j=k.defer(),o=j.promise,m,p,w=r(b.url,b.params);l.pendingRequests.push(b);o.then(i,i);b.cache&&b.method=="GET"&&(m=L(b.cache)?b.cache:n);if(m)if(p=m.get(w))if(p.then)return p.then(i,i),p;else J(p)?f(p[1],p[0],V(p[2])):f(p,200,{});else m.put(w,o);p||a(b.method,
+w,c,e,d,b.timeout,b.withCredentials);return o}function r(a,b){if(!b)return a;var c=[];ec(b,function(a,b){a==null||a==p||(L(a)&&(a=da(a)),c.push(encodeURIComponent(b)+"="+encodeURIComponent(a)))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var n=c("$http"),w=[];m(e,function(a){w.push(F(a)?j.get(a):j.invoke(a))});l.pendingRequests=[];(function(a){m(arguments,function(a){l[a]=function(b,c){return l(x(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){l[a]=
+function(b,c,d){return l(x(d||{},{method:a,url:b,data:c}))}})})("post","put");l.defaults=d;return l}]}function Wc(){this.$get=["$browser","$window","$document",function(b,a,c){return Xc(b,Yc,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function Xc(b,a,c,d,e,g){function i(a,b){var c=e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;aa?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=
+d;e.body.appendChild(c)}return function(e,h,k,j,l,o,r){function n(a,c,d,e){c=(h.match(Fb)||["",g])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(D)}b.$$incOutstandingRequestCount();h=h||b.url();if(E(e)=="jsonp"){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a};i(h.replace("JSON_CALLBACK","angular.callbacks."+p),function(){d[p].data?n(j,200,d[p].data):n(j,-2);delete d[p]})}else{var q=new a;q.open(e,h,!0);m(l,function(a,b){a&&q.setRequestHeader(b,a)});
+var s;q.onreadystatechange=function(){q.readyState==4&&n(j,s||q.status,q.responseText,q.getAllResponseHeaders())};if(r)q.withCredentials=!0;q.send(k||"");o>0&&c(function(){s=-1;q.abort()},o)}}}function Zc(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},
+DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",
+shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function $c(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,f,h){var k=c.defer(),j=k.promise,l=v(h)&&!h,f=a.defer(function(){try{k.resolve(e())}catch(a){k.reject(a),d(a)}l||b.$apply()},f),h=function(){delete g[j.$$timeoutId]};j.$$timeoutId=f;g[f]=k;j.then(h,h);return j}var g={};e.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)):
+!1};return e}]}function Pb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Qb);a("date",Rb);a("filter",ad);a("json",bd);a("limitTo",cd);a("lowercase",dd);a("number",Sb);a("orderBy",Tb);a("uppercase",ed)}function ad(){return function(b,a){if(!(b instanceof Array))return b;var c=[];c.check=function(a){for(var b=0;b-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;ce+1?i="0":(f=i,k=!0)}if(!k){i=(i.split(Vb)[1]||"").length;t(e)&&(e=Math.min(Math.max(a.minFrac,i),a.maxFrac));var i=Math.pow(10,e),b=Math.round(b*i)/i,b=(""+b).split(Vb),i=b[0],b=b[1]||"",k=0,j=a.lgSize,l=a.gSize;if(i.length>=j+l)for(var k=i.length-j,o=0;o0||e>-c)e+=c;e===0&&c==-12&&(e=12);return ib(e,a,d)}}function La(b,a){return function(c,d){var e=c["get"+b](),g=la(a?"SHORT"+b:b);return d[g][e]}}function Rb(b){function a(a){var b;
+if(b=a.match(c)){var a=new Date(0),g=0,i=0;b[9]&&(g=G(b[9]+b[10]),i=G(b[9]+b[11]));a.setUTCFullYear(G(b[1]),G(b[2])-1,G(b[3]));a.setUTCHours(G(b[4]||0)-g,G(b[5]||0)-i,G(b[6]||0),G(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g="",i=[],f,h,e=e||"mediumDate",e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=fd.test(c)?G(c):a(c));wa(c)&&(c=new Date(c));if(!na(c))return c;for(;e;)(h=gd.exec(e))?(i=i.concat(ia.call(h,
+1)),e=i.pop()):(i.push(e),e=null);m(i,function(a){f=hd[a];g+=f?f(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function bd(){return function(b){return da(b,!0)}}function cd(){return function(b,a){if(!(b instanceof Array))return b;var a=G(a),c=[],d,e;if(!b||!(b instanceof Array))return c;a>b.length?a=b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;dl?(d.$setValidity("maxlength",
+!1),p):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(c);d.$formatters.push(c)}}function jb(b,a){b="ngClass"+b;return S(function(c,d,e){function g(b,d){if(a===!0||c.$index%2===a)d&&b!==d&&i(d),f(b)}function i(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));d.removeClass(J(a)?a.join(" "):a)}function f(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));a&&d.addClass(J(a)?a.join(" "):a)}c.$watch(e[b],g,!0);e.$observe("class",function(){var a=c.$eval(e[b]);g(a,a)});b!=="ngClass"&&c.$watch("$index",
+function(d,g){var j=d%2;j!==g%2&&(j==a?f(c.$eval(e[b])):i(c.$eval(e[b])))})})}var E=function(b){return F(b)?b.toLowerCase():b},la=function(b){return F(b)?b.toUpperCase():b},B=U.Error,aa=G((/msie (\d+)/.exec(E(navigator.userAgent))||[])[1]),u,ja,ia=[].slice,Ra=[].push,Sa=Object.prototype.toString,Yb=U.angular||(U.angular={}),ta,Cb,Z=["0","0","0"];D.$inject=[];ma.$inject=[];Cb=aa<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?la(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?
+b.nodeName:b[0].nodeName};var kc=/[A-Z]/g,id={full:"1.0.3",major:1,minor:0,dot:3,codeName:"bouncy-thunder"},Ba=Q.cache={},Aa=Q.expando="ng-"+(new Date).getTime(),oc=1,Zb=U.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},db=U.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},mc=/([\:\-\_]+(.))/g,nc=/^moz([A-Z])/,ua=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}
+var c=!1;this.bind("DOMContentLoaded",a);Q(U).bind("load",a)},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?u(this[b]):u(this[this.length+b])},length:0,push:Ra,sort:[].sort,splice:[].splice},Ea={};m("multiple,selected,checked,disabled,readOnly,required".split(","),function(b){Ea[E(b)]=b});var zb={};m("input,select,option,textarea,button,form".split(","),function(b){zb[la(b)]=!0});m({data:ub,inheritedData:Da,scope:function(b){return Da(b,
+"$scope")},controller:xb,injector:function(b){return Da(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Ca,css:function(b,a,c){a=rb(a);if(v(c))b.style[a]=c;else{var d;aa<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];aa<=8&&(d=d===""?p:d);return d}},attr:function(b,a,c){var d=E(a);if(Ea[d])if(v(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||D).specified?d:p;else if(v(c))b.setAttribute(a,
+c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?p:b},prop:function(b,a,c){if(v(c))b[a]=c;else return b[a]},text:x(aa<9?function(b,a){if(b.nodeType==1){if(t(a))return b.innerText;b.innerText=a}else{if(t(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(t(a))return b.textContent;b.textContent=a},{$dv:""}),val:function(b,a){if(t(a))return b.value;b.value=a},html:function(b,a){if(t(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,
+c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Lc={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},hb={},Yc=U.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw new B("This browser does not support XMLHttpRequest.");
+};Pb.$inject=["$provide"];Qb.$inject=["$locale"];Sb.$inject=["$locale"];var Vb=".",hd={yyyy:P("FullYear",4),yy:P("FullYear",2,0,!0),y:P("FullYear",1),MMMM:La("Month"),MMM:La("Month",!0),MM:P("Month",2,1),M:P("Month",1,1),dd:P("Date",2),d:P("Date",1),HH:P("Hours",2),H:P("Hours",1),hh:P("Hours",2,-12),h:P("Hours",1,-12),mm:P("Minutes",2),m:P("Minutes",1),ss:P("Seconds",2),s:P("Seconds",1),EEEE:La("Day"),EEE:La("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=a.getTimezoneOffset();
+return ib(a/60,2)+ib(Math.abs(a%60),2)}},gd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,fd=/^\d+$/;Rb.$inject=["$locale"];var dd=I(E),ed=I(la);Tb.$inject=["$parse"];var jd=I({restrict:"E",compile:function(a,c){c.href||c.$set("href","");return function(a,c){c.bind("click",function(a){if(!c.attr("href"))return a.preventDefault(),!1})}}}),kb={};m(Ea,function(a,c){var d=fa("ng-"+c);kb[d]=function(){return{priority:100,compile:function(){return function(a,g,i){a.$watch(i[d],
+function(a){i.$set(c,!!a)})}}}}});m(["src","href"],function(a){var c=fa("ng-"+a);kb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),aa&&e.prop(a,c))})}}}});var Oa={$addControl:D,$removeControl:D,$setValidity:D,$setDirty:D};Wb.$inject=["$element","$attrs","$scope"];var Ra=function(a){return["$timeout",function(c){var d={name:"form",restrict:"E",controller:Wb,compile:function(){return{pre:function(a,d,i,f){if(!i.action){var h=function(a){a.preventDefault?
+a.preventDefault():a.returnValue=!1};Zb(d[0],"submit",h);d.bind("$destroy",function(){c(function(){db(d[0],"submit",h)},0,!1)})}var k=d.parent().controller("form"),j=i.name||i.ngForm;j&&(a[j]=f);k&&d.bind("$destroy",function(){k.$removeControl(f);j&&(a[j]=p);x(f,Oa)})}}}};return a?x(V(d),{restrict:"EAC"}):d}]},kd=Ra(),ld=Ra(!0),md=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,nd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,od=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,
+ac={text:Qa,number:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);e.$parsers.push(function(a){var c=T(a);return c||od.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),p)});e.$formatters.push(function(a){return T(a)?"":""+a});if(d.min){var f=parseFloat(d.min),a=function(a){return!T(a)&&ah?(e.$setValidity("max",
+!1),p):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return T(a)||wa(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),p)})},url:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||md.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),p)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||nd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email",
+!1),p)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){t(d.name)&&c.attr("name",xa());c.bind("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,i=d.ngFalseValue;F(g)||(g=!0);F(i)||(i=!1);c.bind("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a===
+g});e.$parsers.push(function(a){return a?g:i})},hidden:D,button:D,submit:D,reset:D},bc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,i){i&&(ac[E(g.type)]||ac.text)(d,e,g,i,c,a)}}}],Na="ng-valid",Ma="ng-invalid",Pa="ng-pristine",Xb="ng-dirty",pd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function i(a,c){c=c?"-"+$a(c,"-"):"";e.removeClass((a?Ma:Na)+c).addClass((a?Na:Ma)+c)}this.$modelValue=this.$viewValue=Number.NaN;
+this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var f=g(d.ngModel),h=f.assign;if(!h)throw B(Db+d.ngModel+" ("+pa(e)+")");this.$render=D;var k=e.inheritedData("$formController")||Oa,j=0,l=this.$error={};e.addClass(Pa);i(!0);this.$setValidity=function(a,c){if(l[a]!==!c){if(c){if(l[a]&&j--,!j)i(!0),this.$valid=!0,this.$invalid=!1}else i(!1),this.$invalid=!0,this.$valid=!1,j++;l[a]=!c;i(c,a);k.$setValidity(a,
+c,this)}};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=!0,this.$pristine=!1,e.removeClass(Pa).addClass(Xb),k.$setDirty();m(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,h(a,d),m(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};var o=this;a.$watch(function(){var c=f(a);if(o.$modelValue!==c){var d=o.$formatters,e=d.length;for(o.$modelValue=c;e--;)c=d[e](c);if(o.$viewValue!==c)o.$viewValue=c,o.$render()}})}],qd=function(){return{require:["ngModel",
+"^?form"],controller:pd,link:function(a,c,d,e){var g=e[0],i=e[1]||Oa;i.$addControl(g);c.bind("$destroy",function(){i.$removeControl(g)})}}},rd=I({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),cc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&(T(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);
+d.$observe("required",function(){g(e.$viewValue)})}}}},sd=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&m(a.split(g),function(a){a&&c.push(R(a))});return c});e.$formatters.push(function(a){return J(a)?a.join(", "):p})}}},td=/^(true|false|\d+)$/,ud=function(){return{priority:100,compile:function(a,c){return td.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a,
+c,g){a.$watch(g.ngValue,function(a){g.$set("value",a,!1)})}}}},vd=S(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==p?"":a)})}),wd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],xd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe,
+function(a){c.html(a||"")})}}],yd=jb("",!0),zd=jb("Odd",0),Ad=jb("Even",1),Bd=S({compile:function(a,c){c.$set("ngCloak",p);a.removeClass("ng-cloak")}}),Cd=[function(){return{scope:!0,controller:"@"}}],Dd=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],dc={};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave".split(" "),function(a){var c=fa("ng-"+a);dc[c]=["$parse",function(d){return function(e,g,i){var f=d(i[c]);g.bind(E(a),function(a){e.$apply(function(){f(e,
+{$event:a})})})}}]});var Ed=S(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),Fd=["$http","$templateCache","$anchorScroll","$compile",function(a,c,d,e){return{restrict:"ECA",terminal:!0,compile:function(g,i){var f=i.ngInclude||i.src,h=i.onload||"",k=i.autoscroll;return function(g,i){var o=0,m,n=function(){m&&(m.$destroy(),m=null);i.html("")};g.$watch(f,function(f){var p=++o;f?a.get(f,{cache:c}).success(function(a){p===o&&(m&&m.$destroy(),m=g.$new(),i.html(a),e(i.contents())(m),
+v(k)&&(!k||g.$eval(k))&&d(),m.$emit("$includeContentLoaded"),g.$eval(h))}).error(function(){p===o&&n()}):n()})}}}}],Gd=S({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Hd=S({terminal:!0,priority:1E3}),Id=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,i){var f=i.count,h=g.attr(i.$attr.when),k=i.offset||0,j=e.$eval(h),l={},o=c.startSymbol(),r=c.endSymbol();m(j,function(a,e){l[e]=c(a.replace(d,o+f+"-"+k+r))});e.$watch(function(){var c=
+parseFloat(e.$eval(f));return isNaN(c)?"":(j[c]||(c=a.pluralCat(c-k)),l[c](e,g,!0))},function(a){g.text(a)})}}}],Jd=S({transclude:"element",priority:1E3,terminal:!0,compile:function(a,c,d){return function(a,c,i){var f=i.ngRepeat,i=f.match(/^\s*(.+)\s+in\s+(.*)\s*$/),h,k,j;if(!i)throw B("Expected ngRepeat in form of '_item_ in _collection_' but got '"+f+"'.");f=i[1];h=i[2];i=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!i)throw B("'item' in 'item in collection' should be identifier or (key, value) but got '"+
+f+"'.");k=i[3]||i[1];j=i[2];var l=new eb;a.$watch(function(a){var e,f,i=a.$eval(h),m=gc(i,!0),p,u=new eb,C,A,v,t,y=c;if(J(i))v=i||[];else{v=[];for(C in i)i.hasOwnProperty(C)&&C.charAt(0)!="$"&&v.push(C);v.sort()}e=0;for(f=v.length;ex;)t.pop().element.remove()}for(;v.length>w;)v.pop()[0].element.remove()}var i;if(!(i=w.match(d)))throw B("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+w+"'.");var j=c(i[2]||i[1]),k=i[4]||
+i[6],l=i[5],m=c(i[3]||""),o=c(i[2]?i[1]:k),r=c(i[7]),v=[[{element:f,label:""}]];q&&(a(q)(e),q.removeClass("ng-scope"),q.remove());f.html("");f.bind("change",function(){e.$apply(function(){var a,c=r(e)||[],d={},h,i,j,m,q,s;if(n){i=[];m=0;for(s=v.length;m@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}');
diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,224 @@
+// 'use strict';
+
+// Declare app level module which depends on filters, and services
+angular.module('bck2brwsr', []).
+ directive('uiCodemirror', ['$timeout', function($timeout) {
+ 'use strict';
+
+ var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"];
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, elm, attrs, ngModel) {
+ var options, opts, onChange, deferCodeMirror, codeMirror, timeoutId, val;
+
+ if (elm[0].type !== 'textarea') {
+ throw new Error('uiCodemirror3 can only be applied to a textarea element');
+ }
+
+ options = /* uiConfig.codemirror || */ {};
+ opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror));
+
+ onChange = function(instance, changeObj) {
+ val = instance.getValue();
+ $timeout.cancel(timeoutId);
+ timeoutId = $timeout(function() {
+ ngModel.$setViewValue(val);
+ }, 500);
+ };
+
+ deferCodeMirror = function() {
+ codeMirror = CodeMirror.fromTextArea(elm[0], opts);
+ elm[0].codeMirror = codeMirror;
+ // codeMirror.on("change", onChange(opts.onChange));
+ codeMirror.on("change", onChange);
+
+ for (var i = 0, n = events.length, aEvent; i < n; ++i) {
+ aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)];
+ if (aEvent === void 0)
+ continue;
+ if (typeof aEvent !== "function")
+ continue;
+
+ var bound = _.bind( aEvent, scope );
+
+ codeMirror.on(events[i], bound);
+ }
+
+ // CodeMirror expects a string, so make sure it gets one.
+ // This does not change the model.
+ ngModel.$formatters.push(function(value) {
+ if (angular.isUndefined(value) || value === null) {
+ return '';
+ }
+ else if (angular.isObject(value) || angular.isArray(value)) {
+ throw new Error('ui-codemirror cannot use an object or an array as a model');
+ }
+ return value;
+ });
+
+ // Override the ngModelController $render method, which is what gets called when the model is updated.
+ // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
+ ngModel.$render = function() {
+ codeMirror.setValue(ngModel.$viewValue);
+ };
+
+ };
+
+ $timeout(deferCodeMirror);
+
+ }
+ };
+}]);
+
+function DevCtrl( $scope, $http ) {
+ var templateHtml =
+"\n" +
+" \n" +
+" \n" +
+" * 0 \n" +
+" = 0\n" +
+" \n" +
+" \n" +
+" " +
+" \n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+" \n" +
+" \n" +
+"";
+ var templateJava =
+"package bck2brwsr.demo;\n" +
+"import org.apidesign.bck2brwsr.htmlpage.api.*;\n" +
+"import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;\n" +
+"\n" +
+"@Page(xhtml=\"index.html\", className=\"Index\", properties={\n" +
+" @Property(name=\"value\", type=int.class)\n" +
+"})\n" +
+"class YourFirstHTML5PageInRealLanguage {\n" +
+" static { new Index().applyBindings(); }\n" +
+" @On(event=CLICK, id=\"dupl\") static void duplicateValue(Index m) {\n" +
+" m.setValue(m.getValue() * 2);\n" +
+" }\n" +
+" @On(event=CLICK, id=\"clear\") static void zeroTheValue(Index m) {\n" +
+" m.setValue(0);;\n" +
+" }\n" +
+" @ComputedProperty static int powerValue(int value) {\n" +
+" return value * value;\n" +
+" }\n" +
+"}";
+
+
+ $scope.makeMarker = function( editor, line ) {
+ var marker = document.createElement("div");
+ marker.innerHTML = " ";
+ marker.className = "issue";
+
+ var info = editor.lineInfo(line);
+ editor.setGutterMarker(line, "issues", info.markers ? null : marker);
+
+ return marker;
+ };
+
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ $scope.debounce = function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) result = func.apply(context, args);
+ return result;
+ };
+ };
+
+ $scope.reload = function() {
+ $scope.errors = null;
+ var frame = document.getElementById("result");
+ frame.src = "result.html";
+ frame.contentDocument.location.reload(true);
+ frame.contentWindow.location.reload();
+ document.getElementById("editorJava").codeMirror.clearGutter("issues");
+ };
+
+ $scope.fail = function( data ) {
+ $scope.errors = eval( data );
+ var editor = document.getElementById("editorJava").codeMirror;
+ editor.clearGutter( "issues" );
+
+ for( var i = 0; i < $scope.errors.length; i ++ ) {
+ $scope.makeMarker( editor, $scope.errors[i].line - 1 );
+ }
+
+ };
+
+ $scope.post = function() {
+ return $http({url: ".",
+ method: "POST",
+ //headers: this.headers,
+ data: { html : $scope.html, java : $scope.java}
+ }).success( $scope.reload ).error( $scope.fail );
+ };
+
+ $scope.errorClass = function( kind ) {
+ switch( kind ) {
+ case "ERROR" :
+ return "error";
+ default :
+ return "warning";
+ }
+ };
+
+ $scope.gotoError = function( line, col ) {
+ var editor = document.getElementById("editorJava").codeMirror;
+ editor.setCursor({ line: line - 1, ch : col - 1 });
+ editor.focus();
+ };
+
+ $scope.tab = "html";
+ $scope.html= templateHtml;
+ $scope.java = templateJava;
+
+ $scope.$watch( "html", $scope.debounce( $scope.post, 2000 ) );
+ $scope.$watch( "java", $scope.debounce( $scope.post, 2000 ) );
+ $scope.post();
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,239 @@
+/* BASICS */
+
+.CodeMirror {
+ /* Set height, width, borders, and global font properties here */
+ font-family: monospace;
+ height: 300px;
+}
+.CodeMirror-scroll {
+ /* Set scrolling behaviour here */
+ overflow: auto;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+ padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+ padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler {
+ background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+ border-right: 1px solid #ddd;
+ background-color: #f7f7f7;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+ padding: 0 3px 0 5px;
+ min-width: 20px;
+ text-align: right;
+ color: #999;
+}
+
+/* CURSOR */
+
+.CodeMirror pre.CodeMirror-cursor {
+ border-left: 1px solid black;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror pre.CodeMirror-secondarycursor {
+ border-left: 1px solid silver;
+}
+.cm-keymap-fat-cursor pre.CodeMirror-cursor {
+ width: auto;
+ border: 0;
+ background: transparent;
+ background: rgba(0, 200, 0, .4);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
+}
+/* Kludge to turn off filter in ie9+, which also accepts rgba */
+.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+/* Can style cursor different in overwrite (non-insert) mode */
+.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable {color: black;}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3 {color: #085;}
+.cm-s-default .cm-property {color: black;}
+.cm-s-default .cm-operator {color: black;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-error {color: #f00;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-emstrong {font-style: italic; font-weight: bold;}
+.cm-link {text-decoration: underline;}
+
+.cm-invalidchar {color: #f00;}
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+ the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+ line-height: 1;
+ position: relative;
+ overflow: hidden;
+}
+
+.CodeMirror-scroll {
+ /* 30px is the magic margin used to hide the element's real scrollbars */
+ /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
+ margin-bottom: -30px; margin-right: -30px;
+ padding-bottom: 30px; padding-right: 30px;
+ height: 100%;
+ outline: none; /* Prevent dragging from highlighting the element */
+ position: relative;
+}
+.CodeMirror-sizer {
+ position: relative;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+ before actuall scrolling happens, thus preventing shaking and
+ flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
+ position: absolute;
+ z-index: 6;
+ display: none;
+}
+.CodeMirror-vscrollbar {
+ right: 0; top: 0;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+ bottom: 0; left: 0;
+ overflow-y: hidden;
+ overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+ right: 0; bottom: 0;
+ z-index: 6;
+}
+
+.CodeMirror-gutters {
+ position: absolute; left: 0; top: 0;
+ height: 100%;
+ z-index: 3;
+}
+.CodeMirror-gutter {
+ height: 100%;
+ display: inline-block;
+ /* Hack to make IE7 behave */
+ *zoom:1;
+ *display:inline;
+}
+.CodeMirror-gutter-elt {
+ position: absolute;
+ cursor: default;
+ z-index: 4;
+}
+
+.CodeMirror-lines {
+ cursor: text;
+}
+.CodeMirror pre {
+ /* Reset some styles that the rest of the page might have set */
+ -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
+ border-width: 0;
+ background: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ margin: 0;
+ white-space: pre;
+ word-wrap: normal;
+ line-height: inherit;
+ color: inherit;
+ z-index: 2;
+ position: relative;
+ overflow: visible;
+}
+.CodeMirror-wrap pre {
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ word-break: normal;
+}
+.CodeMirror-linebackground {
+ position: absolute;
+ left: 0; right: 0; top: 0; bottom: 0;
+ z-index: 0;
+}
+
+.CodeMirror-linewidget {
+ position: relative;
+ z-index: 2;
+}
+
+.CodeMirror-wrap .CodeMirror-scroll {
+ overflow-x: hidden;
+}
+
+.CodeMirror-measure {
+ position: absolute;
+ width: 100%; height: 0px;
+ overflow: hidden;
+ visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror pre.CodeMirror-cursor {
+ position: absolute;
+ visibility: hidden;
+ border-right: none;
+ width: 0;
+}
+.CodeMirror-focused pre.CodeMirror-cursor {
+ visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+
+.CodeMirror-searching {
+ background: #ffa;
+ background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+@media print {
+ /* Hide the cursor when printing */
+ .CodeMirror pre.CodeMirror-cursor {
+ visibility: hidden;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,4553 @@
+// CodeMirror version 3.0
+//
+// CodeMirror is the only global var we claim
+window.CodeMirror = (function() {
+ "use strict";
+
+ // BROWSER SNIFFING
+
+ // Crude, but necessary to handle a number of hard-to-feature-detect
+ // bugs and behavior differences.
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
+ var ie = /MSIE \d/.test(navigator.userAgent);
+ var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
+ var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
+ var webkit = /WebKit\//.test(navigator.userAgent);
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
+ var chrome = /Chrome\//.test(navigator.userAgent);
+ var opera = /Opera\//.test(navigator.userAgent);
+ var safari = /Apple Computer/.test(navigator.vendor);
+ var khtml = /KHTML\//.test(navigator.userAgent);
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
+ var phantom = /PhantomJS/.test(navigator.userAgent);
+
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent);
+ var mac = ios || /Mac/.test(navigator.platform);
+
+ // Optimize some code when these features are not used
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
+
+ // CONSTRUCTOR
+
+ function CodeMirror(place, options) {
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
+
+ this.options = options = options || {};
+ // Determine effective options based on given values and defaults.
+ for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
+ options[opt] = defaults[opt];
+ setGuttersForLineNumbers(options);
+
+ var display = this.display = makeDisplay(place);
+ display.wrapper.CodeMirror = this;
+ updateGutters(this);
+ if (options.autofocus && !mobile) focusInput(this);
+
+ this.view = makeView(new BranchChunk([new LeafChunk([makeLine("", null, textHeight(display))])]));
+ this.nextOpId = 0;
+ loadMode(this);
+ themeChanged(this);
+ if (options.lineWrapping)
+ this.display.wrapper.className += " CodeMirror-wrap";
+
+ // Initialize the content.
+ this.setValue(options.value || "");
+ // Override magic textarea content restore that IE sometimes does
+ // on our hidden textarea on reload
+ if (ie) setTimeout(bind(resetInput, this, true), 20);
+ this.view.history = makeHistory();
+
+ registerEventHandlers(this);
+ // IE throws unspecified error in certain cases, when
+ // trying to access activeElement before onload
+ var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
+ if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
+ else onBlur(this);
+
+ operation(this, function() {
+ for (var opt in optionHandlers)
+ if (optionHandlers.propertyIsEnumerable(opt))
+ optionHandlers[opt](this, options[opt], Init);
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
+ })();
+ }
+
+ // DISPLAY CONSTRUCTOR
+
+ function makeDisplay(place) {
+ var d = {};
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none;");
+ input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
+ // Wraps and hides input textarea
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
+ // The actual fake scrollbars.
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
+ d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
+ // DIVs containing the selection and the actual code
+ d.lineDiv = elt("div");
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
+ // Blinky cursor, and element used to ensure cursor fits at the end of a line
+ d.cursor = elt("pre", "\u00a0", "CodeMirror-cursor");
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
+ d.otherCursor = elt("pre", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
+ // Used to measure text size
+ d.measure = elt("div", null, "CodeMirror-measure");
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
+ d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
+ null, "position: relative; outline: none");
+ // Moved around its parent to cover visible view
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
+ // Set to the height of the text, causes scrolling
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
+ // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
+ d.heightForcer = elt("div", "\u00a0", null, "position: absolute; height: " + scrollerCutOff + "px");
+ // Will contain the gutters, if any
+ d.gutters = elt("div", null, "CodeMirror-gutters");
+ d.lineGutter = null;
+ // Helper element to properly size the gutter backgrounds
+ var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%");
+ // Provides scrolling
+ d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll");
+ d.scroller.setAttribute("tabIndex", "-1");
+ // The element in which the editor lives.
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
+ d.scrollbarFiller, d.scroller], "CodeMirror");
+ // Work around IE7 z-index bug
+ if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
+ if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
+
+ // Needed to hide big blue blinking cursor on Mobile Safari
+ if (ios) input.style.width = "0px";
+ if (!webkit) d.scroller.draggable = true;
+ // Needed to handle Tab key in KHTML
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
+ else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
+
+ // Current visible range (may be bigger than the view window).
+ d.viewOffset = d.showingFrom = d.showingTo = d.lastSizeC = 0;
+
+ // Used to only resize the line number gutter when necessary (when
+ // the amount of lines crosses a boundary that makes its width change)
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
+ // See readInput and resetInput
+ d.prevInput = "";
+ // Set to true when a non-horizontal-scrolling widget is added. As
+ // an optimization, widget aligning is skipped when d is false.
+ d.alignWidgets = false;
+ // Flag that indicates whether we currently expect input to appear
+ // (after some event like 'keypress' or 'input') and are polling
+ // intensively.
+ d.pollingFast = false;
+ // Self-resetting timeout for the poller
+ d.poll = new Delayed();
+ // True when a drag from the editor is active
+ d.draggingText = false;
+
+ d.cachedCharWidth = d.cachedTextHeight = null;
+ d.measureLineCache = [];
+ d.measureLineCachePos = 0;
+
+ // Tracks when resetInput has punted to just putting a short
+ // string instead of the (large) selection.
+ d.inaccurateSelection = false;
+
+ // Used to adjust overwrite behaviour when a paste has been
+ // detected
+ d.pasteIncoming = false;
+
+ return d;
+ }
+
+ // VIEW CONSTRUCTOR
+
+ function makeView(doc) {
+ var selPos = {line: 0, ch: 0};
+ return {
+ doc: doc,
+ // frontier is the point up to which the content has been parsed,
+ frontier: 0, highlight: new Delayed(),
+ sel: {from: selPos, to: selPos, head: selPos, anchor: selPos, shift: false, extend: false},
+ scrollTop: 0, scrollLeft: 0,
+ overwrite: false, focused: false,
+ // Tracks the maximum line length so that
+ // the horizontal scrollbar can be kept
+ // static when scrolling.
+ maxLine: getLine(doc, 0),
+ maxLineLength: 0,
+ maxLineChanged: false,
+ suppressEdits: false,
+ goalColumn: null,
+ cantEdit: false,
+ keyMaps: []
+ };
+ }
+
+ // STATE UPDATES
+
+ // Used to get the editor into a consistent state again when options change.
+
+ function loadMode(cm) {
+ var doc = cm.view.doc;
+ cm.view.mode = CodeMirror.getMode(cm.options, cm.options.mode);
+ doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
+ cm.view.frontier = 0;
+ startWorker(cm, 100);
+ }
+
+ function wrappingChanged(cm) {
+ var doc = cm.view.doc, th = textHeight(cm.display);
+ if (cm.options.lineWrapping) {
+ cm.display.wrapper.className += " CodeMirror-wrap";
+ var perLine = cm.display.scroller.clientWidth / charWidth(cm.display) - 3;
+ doc.iter(0, doc.size, function(line) {
+ if (line.height == 0) return;
+ var guess = Math.ceil(line.text.length / perLine) || 1;
+ if (guess != 1) updateLineHeight(line, guess * th);
+ });
+ cm.display.sizer.style.minWidth = "";
+ } else {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
+ computeMaxLength(cm.view);
+ doc.iter(0, doc.size, function(line) {
+ if (line.height != 0) updateLineHeight(line, th);
+ });
+ }
+ regChange(cm, 0, doc.size);
+ clearCaches(cm);
+ setTimeout(function(){updateScrollbars(cm.display, cm.view.doc.height);}, 100);
+ }
+
+ function keyMapChanged(cm) {
+ var style = keyMap[cm.options.keyMap].style;
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
+ (style ? " cm-keymap-" + style : "");
+ }
+
+ function themeChanged(cm) {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
+ clearCaches(cm);
+ }
+
+ function guttersChanged(cm) {
+ updateGutters(cm);
+ updateDisplay(cm, true);
+ }
+
+ function updateGutters(cm) {
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
+ removeChildren(gutters);
+ for (var i = 0; i < specs.length; ++i) {
+ var gutterClass = specs[i];
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
+ if (gutterClass == "CodeMirror-linenumbers") {
+ cm.display.lineGutter = gElt;
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
+ }
+ }
+ gutters.style.display = i ? "" : "none";
+ }
+
+ function lineLength(doc, line) {
+ if (line.height == 0) return 0;
+ var len = line.text.length, merged, cur = line;
+ while (merged = collapsedSpanAtStart(cur)) {
+ var found = merged.find();
+ cur = getLine(doc, found.from.line);
+ len += found.from.ch - found.to.ch;
+ }
+ cur = line;
+ while (merged = collapsedSpanAtEnd(cur)) {
+ var found = merged.find();
+ len -= cur.text.length - found.from.ch;
+ cur = getLine(doc, found.to.line);
+ len += cur.text.length - found.to.ch;
+ }
+ return len;
+ }
+
+ function computeMaxLength(view) {
+ view.maxLine = getLine(view.doc, 0);
+ view.maxLineLength = lineLength(view.doc, view.maxLine);
+ view.maxLineChanged = true;
+ view.doc.iter(1, view.doc.size, function(line) {
+ var len = lineLength(view.doc, line);
+ if (len > view.maxLineLength) {
+ view.maxLineLength = len;
+ view.maxLine = line;
+ }
+ });
+ }
+
+ // Make sure the gutters options contains the element
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
+ function setGuttersForLineNumbers(options) {
+ var found = false;
+ for (var i = 0; i < options.gutters.length; ++i) {
+ if (options.gutters[i] == "CodeMirror-linenumbers") {
+ if (options.lineNumbers) found = true;
+ else options.gutters.splice(i--, 1);
+ }
+ }
+ if (!found && options.lineNumbers)
+ options.gutters.push("CodeMirror-linenumbers");
+ }
+
+ // SCROLLBARS
+
+ // Re-synchronize the fake scrollbars with the actual size of the
+ // content. Optionally force a scrollTop.
+ function updateScrollbars(d /* display */, docHeight) {
+ var totalHeight = docHeight + 2 * paddingTop(d);
+ d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
+ var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
+ var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
+ var needsV = scrollHeight > d.scroller.clientHeight;
+ if (needsV) {
+ d.scrollbarV.style.display = "block";
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
+ d.scrollbarV.firstChild.style.height =
+ (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
+ } else d.scrollbarV.style.display = "";
+ if (needsH) {
+ d.scrollbarH.style.display = "block";
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
+ d.scrollbarH.firstChild.style.width =
+ (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
+ } else d.scrollbarH.style.display = "";
+ if (needsH && needsV) {
+ d.scrollbarFiller.style.display = "block";
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
+ } else d.scrollbarFiller.style.display = "";
+
+ if (mac_geLion && scrollbarWidth(d.measure) === 0)
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
+ }
+
+ function visibleLines(display, doc, viewPort) {
+ var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
+ if (typeof viewPort == "number") top = viewPort;
+ else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
+ top = Math.floor(top - paddingTop(display));
+ var bottom = Math.ceil(top + height);
+ return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
+ }
+
+ // LINE NUMBERS
+
+ function alignHorizontally(cm) {
+ var display = cm.display;
+ if (!display.alignWidgets && !display.gutters.firstChild) return;
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.view.scrollLeft;
+ var gutterW = display.gutters.offsetWidth, l = comp + "px";
+ for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
+ for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
+ }
+ display.gutters.style.left = (comp + gutterW) + "px";
+ }
+
+ function maybeUpdateLineNumberWidth(cm) {
+ if (!cm.options.lineNumbers) return false;
+ var doc = cm.view.doc, last = lineNumberFor(cm.options, doc.size - 1), display = cm.display;
+ if (last.length != display.lineNumChars) {
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
+ display.lineGutter.style.width = "";
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
+ display.lineGutter.style.width = display.lineNumWidth + "px";
+ return true;
+ }
+ return false;
+ }
+
+ function lineNumberFor(options, i) {
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
+ }
+ function compensateForHScroll(display) {
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
+ }
+
+ // DISPLAY DRAWING
+
+ function updateDisplay(cm, changes, viewPort) {
+ var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo;
+ var updated = updateDisplayInner(cm, changes, viewPort);
+ if (updated) {
+ signalLater(cm, cm, "update", cm);
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
+ signalLater(cm, cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
+ }
+ updateSelection(cm);
+ updateScrollbars(cm.display, cm.view.doc.height);
+
+ return updated;
+ }
+
+ // Uses a set of changes plus the current scroll position to
+ // determine which DOM updates have to be made, and makes the
+ // updates.
+ function updateDisplayInner(cm, changes, viewPort) {
+ var display = cm.display, doc = cm.view.doc;
+ if (!display.wrapper.clientWidth) {
+ display.showingFrom = display.showingTo = display.viewOffset = 0;
+ return;
+ }
+
+ // Compute the new visible window
+ // If scrollTop is specified, use that to determine which lines
+ // to render instead of the current scrollbar position.
+ var visible = visibleLines(display, doc, viewPort);
+ // Bail out if the visible area is already rendered and nothing changed.
+ if (changes !== true && changes.length == 0 &&
+ visible.from > display.showingFrom && visible.to < display.showingTo)
+ return;
+
+ if (changes && maybeUpdateLineNumberWidth(cm))
+ changes = true;
+ display.sizer.style.marginLeft = display.scrollbarH.style.left = display.gutters.offsetWidth + "px";
+
+ // When merged lines are present, the line that needs to be
+ // redrawn might not be the one that was changed.
+ if (changes !== true && sawCollapsedSpans)
+ for (var i = 0; i < changes.length; ++i) {
+ var ch = changes[i], merged;
+ while (merged = collapsedSpanAtStart(getLine(doc, ch.from))) {
+ var from = merged.find().from.line;
+ if (ch.diff) ch.diff -= ch.from - from;
+ ch.from = from;
+ }
+ }
+
+ // Used to determine which lines need their line numbers updated
+ var positionsChangedFrom = changes === true ? 0 : Infinity;
+ if (cm.options.lineNumbers && changes && changes !== true)
+ for (var i = 0; i < changes.length; ++i)
+ if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+
+ var from = Math.max(visible.from - cm.options.viewportMargin, 0);
+ var to = Math.min(doc.size, visible.to + cm.options.viewportMargin);
+ if (display.showingFrom < from && from - display.showingFrom < 20) from = display.showingFrom;
+ if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(doc.size, display.showingTo);
+ if (sawCollapsedSpans) {
+ from = lineNo(visualLine(doc, getLine(doc, from)));
+ while (to < doc.size && lineIsHidden(getLine(doc, to))) ++to;
+ }
+
+ // Create a range of theoretically intact lines, and punch holes
+ // in that using the change info.
+ var intact = changes === true ? [] :
+ computeIntact([{from: display.showingFrom, to: display.showingTo}], changes);
+ // Clip off the parts that won't be visible
+ var intactLines = 0;
+ for (var i = 0; i < intact.length; ++i) {
+ var range = intact[i];
+ if (range.from < from) range.from = from;
+ if (range.to > to) range.to = to;
+ if (range.from >= range.to) intact.splice(i--, 1);
+ else intactLines += range.to - range.from;
+ }
+ if (intactLines == to - from && from == display.showingFrom && to == display.showingTo)
+ return;
+ intact.sort(function(a, b) {return a.from - b.from;});
+
+ if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
+ patchDisplay(cm, from, to, intact, positionsChangedFrom);
+ display.lineDiv.style.display = "";
+
+ var different = from != display.showingFrom || to != display.showingTo ||
+ display.lastSizeC != display.wrapper.clientHeight;
+ // This is just a bogus formula that detects when the editor is
+ // resized or the font size changes.
+ if (different) display.lastSizeC = display.wrapper.clientHeight;
+ display.showingFrom = from; display.showingTo = to;
+ startWorker(cm, 100);
+
+ var prevBottom = display.lineDiv.offsetTop;
+ for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
+ if (ie_lt8) {
+ var bot = node.offsetTop + node.offsetHeight;
+ height = bot - prevBottom;
+ prevBottom = bot;
+ } else {
+ var box = node.getBoundingClientRect();
+ height = box.bottom - box.top;
+ }
+ var diff = node.lineObj.height - height;
+ if (height < 2) height = textHeight(display);
+ if (diff > .001 || diff < -.001)
+ updateLineHeight(node.lineObj, height);
+ }
+ display.viewOffset = heightAtLine(cm, getLine(doc, from));
+ // Position the mover div to align with the current virtual scroll position
+ display.mover.style.top = display.viewOffset + "px";
+ return true;
+ }
+
+ function computeIntact(intact, changes) {
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
+ var range = intact[j];
+ if (change.to <= range.from && change.diff) {
+ intact2.push({from: range.from + diff, to: range.to + diff});
+ } else if (change.to <= range.from || change.from >= range.to) {
+ intact2.push(range);
+ } else {
+ if (change.from > range.from)
+ intact2.push({from: range.from, to: change.from});
+ if (change.to < range.to)
+ intact2.push({from: change.to + diff, to: range.to + diff});
+ }
+ }
+ intact = intact2;
+ }
+ return intact;
+ }
+
+ function getDimensions(cm) {
+ var d = cm.display, left = {}, width = {};
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
+ left[cm.options.gutters[i]] = n.offsetLeft;
+ width[cm.options.gutters[i]] = n.offsetWidth;
+ }
+ return {fixedPos: compensateForHScroll(d),
+ gutterTotalWidth: d.gutters.offsetWidth,
+ gutterLeft: left,
+ gutterWidth: width,
+ wrapperWidth: d.wrapper.clientWidth};
+ }
+
+ function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
+ var dims = getDimensions(cm);
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
+ // IE does bad things to nodes when .innerHTML = "" is used on a parent
+ // we still need widgets and markers intact to add back to the new content later
+ if (!intact.length && !ie && (!webkit || !cm.display.currentWheelTarget))
+ removeChildren(display.lineDiv);
+ var container = display.lineDiv, cur = container.firstChild;
+
+ function rm(node) {
+ var next = node.nextSibling;
+ if (webkit && mac && cm.display.currentWheelTarget == node) {
+ node.style.display = "none";
+ node.lineObj = null;
+ } else {
+ container.removeChild(node);
+ }
+ return next;
+ }
+
+ var nextIntact = intact.shift(), lineNo = from;
+ cm.view.doc.iter(from, to, function(line) {
+ if (nextIntact && nextIntact.to == lineNo) nextIntact = intact.shift();
+ if (lineIsHidden(line)) {
+ if (line.height != 0) updateLineHeight(line, 0);
+ } else if (nextIntact && nextIntact.from <= lineNo && nextIntact.to > lineNo) {
+ // This line is intact. Skip to the actual node. Update its
+ // line number if needed.
+ while (cur.lineObj != line) cur = rm(cur);
+ if (lineNumbers && updateNumbersFrom <= lineNo && cur.lineNumber)
+ setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineNo));
+ cur = cur.nextSibling;
+ } else {
+ // This line needs to be generated.
+ var lineNode = buildLineElement(cm, line, lineNo, dims);
+ container.insertBefore(lineNode, cur);
+ lineNode.lineObj = line;
+ }
+ ++lineNo;
+ });
+ while (cur) cur = rm(cur);
+ }
+
+ function buildLineElement(cm, line, lineNo, dims) {
+ var lineElement = lineContent(cm, line);
+ var markers = line.gutterMarkers, display = cm.display;
+
+ if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass &&
+ (!line.widgets || !line.widgets.length)) return lineElement;
+
+ // Lines with gutter elements or a background class need
+ // to be wrapped again, and have the extra elements added
+ // to the wrapper div
+
+ var wrap = elt("div", null, line.wrapClass, "position: relative");
+ if (cm.options.lineNumbers || markers) {
+ var gutterWrap = wrap.appendChild(elt("div", null, null, "position: absolute; left: " +
+ dims.fixedPos + "px"));
+ wrap.alignable = [gutterWrap];
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
+ wrap.lineNumber = gutterWrap.appendChild(
+ elt("div", lineNumberFor(cm.options, lineNo),
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
+ + display.lineNumInnerWidth + "px"));
+ if (markers)
+ for (var k = 0; k < cm.options.gutters.length; ++k) {
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
+ if (found)
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
+ }
+ }
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
+ if (line.bgClass)
+ wrap.appendChild(elt("div", "\u00a0", line.bgClass + " CodeMirror-linebackground"));
+ wrap.appendChild(lineElement);
+ if (line.widgets)
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
+ node.widget = widget;
+ if (widget.noHScroll) {
+ (wrap.alignable || (wrap.alignable = [])).push(node);
+ var width = dims.wrapperWidth;
+ node.style.left = dims.fixedPos + "px";
+ if (!widget.coverGutter) {
+ width -= dims.gutterTotalWidth;
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
+ }
+ node.style.width = width + "px";
+ }
+ if (widget.coverGutter) {
+ node.style.zIndex = 5;
+ node.style.position = "relative";
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
+ }
+ if (widget.above)
+ wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
+ else
+ wrap.appendChild(node);
+ }
+
+ if (ie_lt8) wrap.style.zIndex = 2;
+ return wrap;
+ }
+
+ // SELECTION / CURSOR
+
+ function updateSelection(cm) {
+ var display = cm.display;
+ var collapsed = posEq(cm.view.sel.from, cm.view.sel.to);
+ if (collapsed || cm.options.showCursorWhenSelecting)
+ updateSelectionCursor(cm);
+ else
+ display.cursor.style.display = display.otherCursor.style.display = "none";
+ if (!collapsed)
+ updateSelectionRange(cm);
+ else
+ display.selectionDiv.style.display = "none";
+
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
+ var headPos = cursorCoords(cm, cm.view.sel.head, "div");
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
+ display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
+ headPos.top + lineOff.top - wrapOff.top)) + "px";
+ display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
+ headPos.left + lineOff.left - wrapOff.left)) + "px";
+ }
+
+ // No selection, plain cursor
+ function updateSelectionCursor(cm) {
+ var display = cm.display, pos = cursorCoords(cm, cm.view.sel.head, "div");
+ display.cursor.style.left = pos.left + "px";
+ display.cursor.style.top = pos.top + "px";
+ display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
+ display.cursor.style.display = "";
+
+ if (pos.other) {
+ display.otherCursor.style.display = "";
+ display.otherCursor.style.left = pos.other.left + "px";
+ display.otherCursor.style.top = pos.other.top + "px";
+ display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
+ } else { display.otherCursor.style.display = "none"; }
+ }
+
+ // Highlight selection
+ function updateSelectionRange(cm) {
+ var display = cm.display, doc = cm.view.doc, sel = cm.view.sel;
+ var fragment = document.createDocumentFragment();
+ var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
+
+ function add(left, top, width, bottom) {
+ if (top < 0) top = 0;
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
+ "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
+ "px; height: " + (bottom - top) + "px"));
+ }
+
+ function drawForLine(line, fromArg, toArg, retTop) {
+ var lineObj = getLine(doc, line);
+ var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
+ function coords(ch) {
+ return charCoords(cm, {line: line, ch: ch}, "div", lineObj);
+ }
+
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
+ var leftPos = coords(dir == "rtl" ? to - 1 : from);
+ var rightPos = coords(dir == "rtl" ? from : to - 1);
+ var left = leftPos.left, right = rightPos.right;
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
+ add(left, leftPos.top, null, leftPos.bottom);
+ left = pl;
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
+ }
+ if (toArg == null && to == lineLen) right = clientWidth;
+ if (fromArg == null && from == 0) left = pl;
+ rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
+ if (left < pl + 1) left = pl;
+ add(left, rightPos.top, right - left, rightPos.bottom);
+ });
+ return rVal;
+ }
+
+ if (sel.from.line == sel.to.line) {
+ drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
+ } else {
+ var fromObj = getLine(doc, sel.from.line);
+ var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
+ while (merged = collapsedSpanAtEnd(cur)) {
+ var found = merged.find();
+ path.push(found.from.ch, found.to.line, found.to.ch);
+ if (found.to.line == sel.to.line) {
+ path.push(sel.to.ch);
+ singleLine = true;
+ break;
+ }
+ cur = getLine(doc, found.to.line);
+ }
+
+ // This is a single, merged line
+ if (singleLine) {
+ for (var i = 0; i < path.length; i += 3)
+ drawForLine(path[i], path[i+1], path[i+2]);
+ } else {
+ var middleTop, middleBot, toObj = getLine(doc, sel.to.line);
+ if (sel.from.ch)
+ // Draw the first line of selection.
+ middleTop = drawForLine(sel.from.line, sel.from.ch, null, false);
+ else
+ // Simply include it in the middle block.
+ middleTop = heightAtLine(cm, fromObj) - display.viewOffset;
+
+ if (!sel.to.ch)
+ middleBot = heightAtLine(cm, toObj) - display.viewOffset;
+ else
+ middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true);
+
+ if (middleTop < middleBot) add(pl, middleTop, null, middleBot);
+ }
+ }
+
+ removeChildrenAndAdd(display.selectionDiv, fragment);
+ display.selectionDiv.style.display = "";
+ }
+
+ // Cursor-blinking
+ function restartBlink(cm) {
+ var display = cm.display;
+ clearInterval(display.blinker);
+ var on = true;
+ display.cursor.style.visibility = display.otherCursor.style.visibility = "";
+ display.blinker = setInterval(function() {
+ if (!display.cursor.offsetHeight) return;
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
+ }
+
+ // HIGHLIGHT WORKER
+
+ function startWorker(cm, time) {
+ if (cm.view.frontier < cm.display.showingTo)
+ cm.view.highlight.set(time, bind(highlightWorker, cm));
+ }
+
+ function highlightWorker(cm) {
+ var view = cm.view, doc = view.doc;
+ if (view.frontier >= cm.display.showingTo) return;
+ var end = +new Date + cm.options.workTime;
+ var state = copyState(view.mode, getStateBefore(cm, view.frontier));
+ var changed = [], prevChange;
+ doc.iter(view.frontier, Math.min(doc.size, cm.display.showingTo + 500), function(line) {
+ if (view.frontier >= cm.display.showingFrom) { // Visible
+ if (highlightLine(cm, line, state) && view.frontier >= cm.display.showingFrom) {
+ if (prevChange && prevChange.end == view.frontier) prevChange.end++;
+ else changed.push(prevChange = {start: view.frontier, end: view.frontier + 1});
+ }
+ line.stateAfter = copyState(view.mode, state);
+ } else {
+ processLine(cm, line, state);
+ line.stateAfter = view.frontier % 5 == 0 ? copyState(view.mode, state) : null;
+ }
+ ++view.frontier;
+ if (+new Date > end) {
+ startWorker(cm, cm.options.workDelay);
+ return true;
+ }
+ });
+ if (changed.length)
+ operation(cm, function() {
+ for (var i = 0; i < changed.length; ++i)
+ regChange(this, changed[i].start, changed[i].end);
+ })();
+ }
+
+ // Finds the line to start with when starting a parse. Tries to
+ // find a line with a stateAfter, so that it can start with a
+ // valid state. If that fails, it returns the line with the
+ // smallest indentation, which tends to need the least context to
+ // parse correctly.
+ function findStartLine(cm, n) {
+ var minindent, minline, doc = cm.view.doc;
+ for (var search = n, lim = n - 100; search > lim; --search) {
+ if (search == 0) return 0;
+ var line = getLine(doc, search-1);
+ if (line.stateAfter) return search;
+ var indented = countColumn(line.text, null, cm.options.tabSize);
+ if (minline == null || minindent > indented) {
+ minline = search - 1;
+ minindent = indented;
+ }
+ }
+ return minline;
+ }
+
+ function getStateBefore(cm, n) {
+ var view = cm.view;
+ var pos = findStartLine(cm, n), state = pos && getLine(view.doc, pos-1).stateAfter;
+ if (!state) state = startState(view.mode);
+ else state = copyState(view.mode, state);
+ view.doc.iter(pos, n, function(line) {
+ processLine(cm, line, state);
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= view.showingFrom && pos < view.showingTo;
+ line.stateAfter = save ? copyState(view.mode, state) : null;
+ ++pos;
+ });
+ return state;
+ }
+
+ // POSITION MEASUREMENT
+
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
+ function paddingLeft(display) {
+ var e = removeChildrenAndAdd(display.measure, elt("pre")).appendChild(elt("span", "x"));
+ return e.offsetLeft;
+ }
+
+ function measureChar(cm, line, ch, data) {
+ var data = data || measureLine(cm, line), dir = -1;
+ for (var pos = ch;; pos += dir) {
+ var r = data[pos];
+ if (r) break;
+ if (dir < 0 && pos == 0) dir = 1;
+ }
+ return {left: pos < ch ? r.right : r.left,
+ right: pos > ch ? r.left : r.right,
+ top: r.top, bottom: r.bottom};
+ }
+
+ function measureLine(cm, line) {
+ // First look in the cache
+ var display = cm.display, cache = cm.display.measureLineCache;
+ for (var i = 0; i < cache.length; ++i) {
+ var memo = cache[i];
+ if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
+ display.scroller.clientWidth == memo.width)
+ return memo.measure;
+ }
+
+ var measure = measureLineInner(cm, line);
+ // Store result in the cache
+ var memo = {text: line.text, width: display.scroller.clientWidth,
+ markedSpans: line.markedSpans, measure: measure};
+ if (cache.length == 16) cache[++display.measureLineCachePos % 16] = memo;
+ else cache.push(memo);
+ return measure;
+ }
+
+ function measureLineInner(cm, line) {
+ var display = cm.display, measure = emptyArray(line.text.length);
+ var pre = lineContent(cm, line, measure);
+
+ // IE does not cache element positions of inline elements between
+ // calls to getBoundingClientRect. This makes the loop below,
+ // which gathers the positions of all the characters on the line,
+ // do an amount of layout work quadratic to the number of
+ // characters. When line wrapping is off, we try to improve things
+ // by first subdividing the line into a bunch of inline blocks, so
+ // that IE can reuse most of the layout information from caches
+ // for those blocks. This does interfere with line wrapping, so it
+ // doesn't work when wrapping is on, but in that case the
+ // situation is slightly better, since IE does cache line-wrapping
+ // information and only recomputes per-line.
+ if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
+ var fragment = document.createDocumentFragment();
+ var chunk = 10, n = pre.childNodes.length;
+ for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
+ var wrap = elt("div", null, null, "display: inline-block");
+ for (var j = 0; j < chunk && n; ++j) {
+ wrap.appendChild(pre.firstChild);
+ --n;
+ }
+ fragment.appendChild(wrap);
+ }
+ pre.appendChild(fragment);
+ }
+
+ removeChildrenAndAdd(display.measure, pre);
+
+ var outer = display.lineDiv.getBoundingClientRect();
+ var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
+ for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
+ var size = cur.getBoundingClientRect();
+ var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
+ for (var j = 0; j < vranges.length; j += 2) {
+ var rtop = vranges[j], rbot = vranges[j+1];
+ if (rtop > bot || rbot < top) continue;
+ if (rtop <= top && rbot >= bot ||
+ top <= rtop && bot >= rbot ||
+ Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
+ vranges[j] = Math.min(top, rtop);
+ vranges[j+1] = Math.max(bot, rbot);
+ break;
+ }
+ }
+ if (j == vranges.length) vranges.push(top, bot);
+ data[i] = {left: size.left - outer.left, right: size.right - outer.left, top: j};
+ }
+ for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
+ var vr = cur.top;
+ cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
+ }
+ return data;
+ }
+
+ function clearCaches(cm) {
+ cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
+ cm.view.maxLineChanged = true;
+ }
+
+ // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
+ function intoCoordSystem(cm, lineObj, rect, context) {
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
+ var size = lineObj.widgets[i].node.offsetHeight;
+ rect.top += size; rect.bottom += size;
+ }
+ if (context == "line") return rect;
+ if (!context) context = "local";
+ var yOff = heightAtLine(cm, lineObj);
+ if (context != "local") yOff -= cm.display.viewOffset;
+ if (context == "page") {
+ var lOff = cm.display.lineSpace.getBoundingClientRect();
+ yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
+ var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
+ rect.left += xOff; rect.right += xOff;
+ }
+ rect.top += yOff; rect.bottom += yOff;
+ return rect;
+ }
+
+ function charCoords(cm, pos, context, lineObj) {
+ if (!lineObj) lineObj = getLine(cm.view.doc, pos.line);
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context);
+ }
+
+ function cursorCoords(cm, pos, context, lineObj, measurement) {
+ lineObj = lineObj || getLine(cm.view.doc, pos.line);
+ if (!measurement) measurement = measureLine(cm, lineObj);
+ function get(ch, right) {
+ var m = measureChar(cm, lineObj, ch, measurement);
+ if (right) m.left = m.right; else m.right = m.left;
+ return intoCoordSystem(cm, lineObj, m, context);
+ }
+ var order = getOrder(lineObj), ch = pos.ch;
+ if (!order) return get(ch);
+ var main, other, linedir = order[0].level;
+ for (var i = 0; i < order.length; ++i) {
+ var part = order[i], rtl = part.level % 2, nb, here;
+ if (part.from < ch && part.to > ch) return get(ch, rtl);
+ var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
+ if (left == ch) {
+ // Opera and IE return bogus offsets and widths for edges
+ // where the direction flips, but only for the side with the
+ // lower level. So we try to use the side with the higher
+ // level.
+ if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
+ else here = get(rtl && part.from != part.to ? ch - 1 : ch);
+ if (rtl == linedir) main = here; else other = here;
+ } else if (right == ch) {
+ var nb = i < order.length - 1 && order[i+1];
+ if (!rtl && nb && nb.from == nb.to) continue;
+ if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from);
+ else here = get(rtl ? ch : ch - 1, true);
+ if (rtl == linedir) main = here; else other = here;
+ }
+ }
+ if (linedir && !ch) other = get(order[0].to - 1);
+ if (!main) return other;
+ if (other) main.other = other;
+ return main;
+ }
+
+ // Coords must be lineSpace-local
+ function coordsChar(cm, x, y) {
+ var doc = cm.view.doc;
+ y += cm.display.viewOffset;
+ if (y < 0) return {line: 0, ch: 0, outside: true};
+ var lineNo = lineAtHeight(doc, y);
+ if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc, doc.size - 1).text.length};
+ if (x < 0) x = 0;
+
+ for (;;) {
+ var lineObj = getLine(doc, lineNo);
+ var found = coordsCharInner(cm, lineObj, lineNo, x, y);
+ var merged = collapsedSpanAtEnd(lineObj);
+ if (merged && found.ch == lineRight(lineObj))
+ lineNo = merged.find().to.line;
+ else
+ return found;
+ }
+ }
+
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
+ var innerOff = y - heightAtLine(cm, lineObj);
+ var wrongLine = false, cWidth = cm.display.wrapper.clientWidth;
+ var measurement = measureLine(cm, lineObj);
+
+ function getX(ch) {
+ var sp = cursorCoords(cm, {line: lineNo, ch: ch}, "line",
+ lineObj, measurement);
+ wrongLine = true;
+ if (innerOff > sp.bottom) return Math.max(0, sp.left - cWidth);
+ else if (innerOff < sp.top) return sp.left + cWidth;
+ else wrongLine = false;
+ return sp.left;
+ }
+
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
+ var fromX = paddingLeft(cm.display), toX = getX(to);
+
+ if (x > toX) return {line: lineNo, ch: to, outside: wrongLine};
+ // Do a binary search between these bounds.
+ for (;;) {
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
+ var after = x - fromX < toX - x, ch = after ? from : to;
+ while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
+ return {line: lineNo, ch: ch, after: after, outside: wrongLine};
+ }
+ var step = Math.ceil(dist / 2), middle = from + step;
+ if (bidi) {
+ middle = from;
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
+ }
+ var middleX = getX(middle);
+ if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; dist -= step;}
+ else {from = middle; fromX = middleX; dist = step;}
+ }
+ }
+
+ var measureText;
+ function textHeight(display) {
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
+ if (measureText == null) {
+ measureText = elt("pre");
+ // Measure a bunch of lines, for browsers that compute
+ // fractional heights.
+ for (var i = 0; i < 49; ++i) {
+ measureText.appendChild(document.createTextNode("x"));
+ measureText.appendChild(elt("br"));
+ }
+ measureText.appendChild(document.createTextNode("x"));
+ }
+ removeChildrenAndAdd(display.measure, measureText);
+ var height = measureText.offsetHeight / 50;
+ if (height > 3) display.cachedTextHeight = height;
+ removeChildren(display.measure);
+ return height || 1;
+ }
+
+ function charWidth(display) {
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
+ var anchor = elt("span", "x");
+ var pre = elt("pre", [anchor]);
+ removeChildrenAndAdd(display.measure, pre);
+ var width = anchor.offsetWidth;
+ if (width > 2) display.cachedCharWidth = width;
+ return width || 10;
+ }
+
+ // OPERATIONS
+
+ // Operations are used to wrap changes in such a way that each
+ // change won't have to update the cursor and display (which would
+ // be awkward, slow, and error-prone), but instead updates are
+ // batched and then all combined and executed at once.
+
+ function startOperation(cm) {
+ if (cm.curOp) ++cm.curOp.depth;
+ else cm.curOp = {
+ // Nested operations delay update until the outermost one
+ // finishes.
+ depth: 1,
+ // An array of ranges of lines that have to be updated. See
+ // updateDisplay.
+ changes: [],
+ delayedCallbacks: [],
+ updateInput: null,
+ userSelChange: null,
+ textChanged: null,
+ selectionChanged: false,
+ updateMaxLine: false,
+ id: ++cm.nextOpId
+ };
+ }
+
+ function endOperation(cm) {
+ var op = cm.curOp;
+ if (--op.depth) return;
+ cm.curOp = null;
+ var view = cm.view, display = cm.display;
+ if (op.updateMaxLine) computeMaxLength(view);
+ if (view.maxLineChanged && !cm.options.lineWrapping) {
+ var width = measureChar(cm, view.maxLine, view.maxLine.text.length).right;
+ display.sizer.style.minWidth = (width + 3 + scrollerCutOff) + "px";
+ view.maxLineChanged = false;
+ }
+ var newScrollPos, updated;
+ if (op.selectionChanged) {
+ var coords = cursorCoords(cm, view.sel.head);
+ newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
+ }
+ if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null)
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
+ if (!updated && op.selectionChanged) updateSelection(cm);
+ if (newScrollPos) scrollCursorIntoView(cm);
+ if (op.selectionChanged) restartBlink(cm);
+
+ if (view.focused && op.updateInput)
+ resetInput(cm, op.userSelChange);
+
+ if (op.textChanged)
+ signal(cm, "change", cm, op.textChanged);
+ if (op.selectionChanged) signal(cm, "cursorActivity", cm);
+ for (var i = 0; i < op.delayedCallbacks.length; ++i) op.delayedCallbacks[i](cm);
+ }
+
+ // Wraps a function in an operation. Returns the wrapped function.
+ function operation(cm1, f) {
+ return function() {
+ var cm = cm1 || this;
+ startOperation(cm);
+ try {var result = f.apply(cm, arguments);}
+ finally {endOperation(cm);}
+ return result;
+ };
+ }
+
+ function regChange(cm, from, to, lendiff) {
+ cm.curOp.changes.push({from: from, to: to, diff: lendiff});
+ }
+
+ // INPUT HANDLING
+
+ function slowPoll(cm) {
+ if (cm.view.pollingFast) return;
+ cm.display.poll.set(cm.options.pollInterval, function() {
+ readInput(cm);
+ if (cm.view.focused) slowPoll(cm);
+ });
+ }
+
+ function fastPoll(cm) {
+ var missed = false;
+ cm.display.pollingFast = true;
+ function p() {
+ var changed = readInput(cm);
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
+ else {cm.display.pollingFast = false; slowPoll(cm);}
+ }
+ cm.display.poll.set(20, p);
+ }
+
+ // prevInput is a hack to work with IME. If we reset the textarea
+ // on every change, that breaks IME. So we look for changes
+ // compared to the previous content instead. (Modern browsers have
+ // events that indicate IME taking place, but these are not widely
+ // supported or compatible enough yet to rely on.)
+ function readInput(cm) {
+ var input = cm.display.input, prevInput = cm.display.prevInput, view = cm.view, sel = view.sel;
+ if (!view.focused || hasSelection(input) || isReadOnly(cm)) return false;
+ var text = input.value;
+ if (text == prevInput && posEq(sel.from, sel.to)) return false;
+ startOperation(cm);
+ view.sel.shift = false;
+ var same = 0, l = Math.min(prevInput.length, text.length);
+ while (same < l && prevInput[same] == text[same]) ++same;
+ var from = sel.from, to = sel.to;
+ if (same < prevInput.length)
+ from = {line: from.line, ch: from.ch - (prevInput.length - same)};
+ else if (view.overwrite && posEq(from, to) && !cm.display.pasteIncoming)
+ to = {line: to.line, ch: Math.min(getLine(cm.view.doc, to.line).text.length, to.ch + (text.length - same))};
+ var updateInput = cm.curOp.updateInput;
+ updateDoc(cm, from, to, splitLines(text.slice(same)), "end",
+ cm.display.pasteIncoming ? "paste" : "input", {from: from, to: to});
+ cm.curOp.updateInput = updateInput;
+ if (text.length > 1000) input.value = cm.display.prevInput = "";
+ else cm.display.prevInput = text;
+ endOperation(cm);
+ cm.display.pasteIncoming = false;
+ return true;
+ }
+
+ function resetInput(cm, user) {
+ var view = cm.view, minimal, selected;
+ if (!posEq(view.sel.from, view.sel.to)) {
+ cm.display.prevInput = "";
+ minimal = hasCopyEvent &&
+ (view.sel.to.line - view.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
+ if (minimal) cm.display.input.value = "-";
+ else cm.display.input.value = selected || cm.getSelection();
+ if (view.focused) selectInput(cm.display.input);
+ } else if (user) cm.display.prevInput = cm.display.input.value = "";
+ cm.display.inaccurateSelection = minimal;
+ }
+
+ function focusInput(cm) {
+ if (cm.options.readOnly != "nocursor" && (ie || document.activeElement != cm.display.input))
+ cm.display.input.focus();
+ }
+
+ function isReadOnly(cm) {
+ return cm.options.readOnly || cm.view.cantEdit;
+ }
+
+ // EVENT HANDLERS
+
+ function registerEventHandlers(cm) {
+ var d = cm.display;
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
+ on(d.scroller, "dblclick", operation(cm, e_preventDefault));
+ on(d.lineSpace, "selectstart", function(e) {
+ if (!mouseEventInWidget(d, e)) e_preventDefault(e);
+ });
+ // Gecko browsers fire contextmenu *after* opening the menu, at
+ // which point we can't mess with it anymore. Context menu is
+ // handled in onMouseDown for Gecko.
+ if (!gecko) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
+
+ on(d.scroller, "scroll", function() {
+ setScrollTop(cm, d.scroller.scrollTop);
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
+ signal(cm, "scroll", cm);
+ });
+ on(d.scrollbarV, "scroll", function() {
+ setScrollTop(cm, d.scrollbarV.scrollTop);
+ });
+ on(d.scrollbarH, "scroll", function() {
+ setScrollLeft(cm, d.scrollbarH.scrollLeft);
+ });
+
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
+
+ function reFocus() { if (cm.view.focused) setTimeout(bind(focusInput, cm), 0); }
+ on(d.scrollbarH, "mousedown", reFocus);
+ on(d.scrollbarV, "mousedown", reFocus);
+ // Prevent wrapper from ever scrolling
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
+ on(window, "resize", function resizeHandler() {
+ // Might be a text scaling operation, clear size caches.
+ d.cachedCharWidth = d.cachedTextHeight = null;
+ clearCaches(cm);
+ if (d.wrapper.parentNode) updateDisplay(cm, true);
+ else off(window, "resize", resizeHandler);
+ });
+
+ on(d.input, "keyup", operation(cm, function(e) {
+ if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ if (e_prop(e, "keyCode") == 16) cm.view.sel.shift = false;
+ }));
+ on(d.input, "input", bind(fastPoll, cm));
+ on(d.input, "keydown", operation(cm, onKeyDown));
+ on(d.input, "keypress", operation(cm, onKeyPress));
+ on(d.input, "focus", bind(onFocus, cm));
+ on(d.input, "blur", bind(onBlur, cm));
+
+ function drag_(e) {
+ if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
+ e_stop(e);
+ }
+ if (cm.options.dragDrop) {
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
+ on(d.scroller, "dragenter", drag_);
+ on(d.scroller, "dragover", drag_);
+ on(d.scroller, "drop", operation(cm, onDrop));
+ }
+ on(d.scroller, "paste", function(){focusInput(cm); fastPoll(cm);});
+ on(d.input, "paste", function() {
+ d.pasteIncoming = true;
+ fastPoll(cm);
+ });
+
+ function prepareCopy() {
+ if (d.inaccurateSelection) {
+ d.prevInput = "";
+ d.inaccurateSelection = false;
+ d.input.value = cm.getSelection();
+ selectInput(d.input);
+ }
+ }
+ on(d.input, "cut", prepareCopy);
+ on(d.input, "copy", prepareCopy);
+
+ // Needed to handle Tab key in KHTML
+ if (khtml) on(d.sizer, "mouseup", function() {
+ if (document.activeElement == d.input) d.input.blur();
+ focusInput(cm);
+ });
+ }
+
+ function mouseEventInWidget(display, e) {
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode)
+ if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
+ n.parentNode == display.sizer && n != display.mover) return true;
+ }
+
+ function posFromMouse(cm, e, liberal) {
+ var display = cm.display;
+ if (!liberal) {
+ var target = e_target(e);
+ if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
+ target == display.scrollbarV || target == display.scrollbarV.firstChild ||
+ target == display.scrollbarFiller) return null;
+ }
+ var x, y, space = display.lineSpace.getBoundingClientRect();
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
+ return coordsChar(cm, x - space.left, y - space.top);
+ }
+
+ var lastClick, lastDoubleClick;
+ function onMouseDown(e) {
+ var cm = this, display = cm.display, view = cm.view, sel = view.sel, doc = view.doc;
+ sel.shift = e_prop(e, "shiftKey");
+
+ if (mouseEventInWidget(display, e)) {
+ if (!webkit) {
+ display.scroller.draggable = false;
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
+ }
+ return;
+ }
+ if (clickInGutter(cm, e)) return;
+ var start = posFromMouse(cm, e);
+
+ switch (e_button(e)) {
+ case 3:
+ if (gecko) onContextMenu.call(cm, cm, e);
+ return;
+ case 2:
+ if (start) extendSelection(cm, start);
+ setTimeout(bind(focusInput, cm), 20);
+ e_preventDefault(e);
+ return;
+ }
+ // For button 1, if it was clicked inside the editor
+ // (posFromMouse returning non-null), we have to adjust the
+ // selection.
+ if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
+
+ if (!view.focused) onFocus(cm);
+
+ var now = +new Date, type = "single";
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
+ type = "triple";
+ e_preventDefault(e);
+ setTimeout(bind(focusInput, cm), 20);
+ selectLine(cm, start.line);
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
+ type = "double";
+ lastDoubleClick = {time: now, pos: start};
+ e_preventDefault(e);
+ var word = findWordAt(getLine(doc, start.line).text, start);
+ extendSelection(cm, word.from, word.to);
+ } else { lastClick = {time: now, pos: start}; }
+
+ var last = start;
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
+ !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
+ var dragEnd = operation(cm, function(e2) {
+ if (webkit) display.scroller.draggable = false;
+ view.draggingText = false;
+ off(document, "mouseup", dragEnd);
+ off(display.scroller, "drop", dragEnd);
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
+ e_preventDefault(e2);
+ extendSelection(cm, start);
+ focusInput(cm);
+ }
+ });
+ // Let the drag handler handle this.
+ if (webkit) display.scroller.draggable = true;
+ view.draggingText = dragEnd;
+ // IE's approach to draggable
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
+ on(document, "mouseup", dragEnd);
+ on(display.scroller, "drop", dragEnd);
+ return;
+ }
+ e_preventDefault(e);
+ if (type == "single") extendSelection(cm, clipPos(doc, start));
+
+ var startstart = sel.from, startend = sel.to;
+
+ function doSelect(cur) {
+ if (type == "single") {
+ extendSelection(cm, clipPos(doc, start), cur);
+ return;
+ }
+
+ startstart = clipPos(doc, startstart);
+ startend = clipPos(doc, startend);
+ if (type == "double") {
+ var word = findWordAt(getLine(doc, cur.line).text, cur);
+ if (posLess(cur, startstart)) extendSelection(cm, word.from, startend);
+ else extendSelection(cm, startstart, word.to);
+ } else if (type == "triple") {
+ if (posLess(cur, startstart)) extendSelection(cm, startend, clipPos(doc, {line: cur.line, ch: 0}));
+ else extendSelection(cm, startstart, clipPos(doc, {line: cur.line + 1, ch: 0}));
+ }
+ }
+
+ var editorSize = display.wrapper.getBoundingClientRect();
+ // Used to ensure timeout re-tries don't fire when another extend
+ // happened in the meantime (clearTimeout isn't reliable -- at
+ // least on Chrome, the timeouts still happen even when cleared,
+ // if the clear happens after their scheduled firing time).
+ var counter = 0;
+
+ function extend(e) {
+ var curCount = ++counter;
+ var cur = posFromMouse(cm, e, true);
+ if (!cur) return;
+ if (!posEq(cur, last)) {
+ if (!view.focused) onFocus(cm);
+ last = cur;
+ doSelect(cur);
+ var visible = visibleLines(display, doc);
+ if (cur.line >= visible.to || cur.line < visible.from)
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
+ } else {
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
+ if (outside) setTimeout(operation(cm, function() {
+ if (counter != curCount) return;
+ display.scroller.scrollTop += outside;
+ extend(e);
+ }), 50);
+ }
+ }
+
+ function done(e) {
+ counter = Infinity;
+ var cur = posFromMouse(cm, e);
+ if (cur) doSelect(cur);
+ e_preventDefault(e);
+ focusInput(cm);
+ off(document, "mousemove", move);
+ off(document, "mouseup", up);
+ }
+
+ var move = operation(cm, function(e) {
+ if (!ie && !e_button(e)) done(e);
+ else extend(e);
+ });
+ var up = operation(cm, done);
+ on(document, "mousemove", move);
+ on(document, "mouseup", up);
+ }
+
+ function onDrop(e) {
+ var cm = this;
+ if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
+ e_preventDefault(e);
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
+ if (!pos || isReadOnly(cm)) return;
+ if (files && files.length && window.FileReader && window.File) {
+ var n = files.length, text = Array(n), read = 0;
+ var loadFile = function(file, i) {
+ var reader = new FileReader;
+ reader.onload = function() {
+ text[i] = reader.result;
+ if (++read == n) {
+ pos = clipPos(cm.view.doc, pos);
+ operation(cm, function() {
+ var end = replaceRange(cm, text.join(""), pos, pos, "paste");
+ setSelection(cm, pos, end);
+ })();
+ }
+ };
+ reader.readAsText(file);
+ };
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
+ } else {
+ // Don't do a replace if the drop happened inside of the selected text.
+ if (cm.view.draggingText && !(posLess(pos, cm.view.sel.from) || posLess(cm.view.sel.to, pos))) {
+ cm.view.draggingText(e);
+ if (ie) setTimeout(bind(focusInput, cm), 50);
+ return;
+ }
+ try {
+ var text = e.dataTransfer.getData("Text");
+ if (text) {
+ var curFrom = cm.view.sel.from, curTo = cm.view.sel.to;
+ setSelection(cm, pos, pos);
+ if (cm.view.draggingText) replaceRange(cm, "", curFrom, curTo, "paste");
+ cm.replaceSelection(text, null, "paste");
+ focusInput(cm);
+ onFocus(cm);
+ }
+ }
+ catch(e){}
+ }
+ }
+
+ function clickInGutter(cm, e) {
+ var display = cm.display;
+ try { var mX = e.clientX, mY = e.clientY; }
+ catch(e) { return false; }
+
+ if (mX >= Math.floor(display.gutters.getBoundingClientRect().right)) return false;
+ e_preventDefault(e);
+ if (!hasHandler(cm, "gutterClick")) return true;
+
+ var lineBox = display.lineDiv.getBoundingClientRect();
+ if (mY > lineBox.bottom) return true;
+ mY -= lineBox.top - display.viewOffset;
+
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
+ var g = display.gutters.childNodes[i];
+ if (g && g.getBoundingClientRect().right >= mX) {
+ var line = lineAtHeight(cm.view.doc, mY);
+ var gutter = cm.options.gutters[i];
+ signalLater(cm, cm, "gutterClick", cm, line, gutter, e);
+ break;
+ }
+ }
+ return true;
+ }
+
+ function onDragStart(cm, e) {
+ var txt = cm.getSelection();
+ e.dataTransfer.setData("Text", txt);
+
+ // Use dummy image instead of default browsers image.
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
+ if (e.dataTransfer.setDragImage && !safari)
+ e.dataTransfer.setDragImage(elt('img'), 0, 0);
+ }
+
+ function setScrollTop(cm, val) {
+ if (Math.abs(cm.view.scrollTop - val) < 2) return;
+ cm.view.scrollTop = val;
+ if (!gecko) updateDisplay(cm, [], val);
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
+ if (gecko) updateDisplay(cm, []);
+ }
+ function setScrollLeft(cm, val, isScroller) {
+ if (isScroller ? val == cm.view.scrollLeft : Math.abs(cm.view.scrollLeft - val) < 2) return;
+ cm.view.scrollLeft = val;
+ alignHorizontally(cm);
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
+ }
+
+ // Since the delta values reported on mouse wheel events are
+ // unstandardized between browsers and even browser versions, and
+ // generally horribly unpredictable, this code starts by measuring
+ // the scroll effect that the first few mouse wheel events have,
+ // and, from that, detects the way it can convert deltas to pixel
+ // offsets afterwards.
+ //
+ // The reason we want to know the amount a wheel event will scroll
+ // is that it gives us a chance to update the display before the
+ // actual scrolling happens, reducing flickering.
+
+ var wheelSamples = 0, wheelDX, wheelDY, wheelStartX, wheelStartY, wheelPixelsPerUnit = null;
+ // Fill in a browser-detected starting value on browsers where we
+ // know one. These don't have to be accurate -- the result of them
+ // being wrong would just be a slight flicker on the first wheel
+ // scroll (if it is large enough).
+ if (ie) wheelPixelsPerUnit = -.53;
+ else if (gecko) wheelPixelsPerUnit = 15;
+ else if (chrome) wheelPixelsPerUnit = -.7;
+ else if (safari) wheelPixelsPerUnit = -1/3;
+
+ function onScrollWheel(cm, e) {
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
+ else if (dy == null) dy = e.wheelDelta;
+
+ // Webkit browsers on OS X abort momentum scrolls when the target
+ // of the scroll event is removed from the scrollable element.
+ // This hack (see related code in patchDisplay) makes sure the
+ // element is kept around.
+ if (dy && mac && webkit) {
+ for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
+ if (cur.lineObj) {
+ cm.display.currentWheelTarget = cur;
+ break;
+ }
+ }
+ }
+
+ var scroll = cm.display.scroller;
+ // On some browsers, horizontal scrolling will cause redraws to
+ // happen before the gutter has been realigned, causing it to
+ // wriggle around in a most unseemly way. When we have an
+ // estimated pixels/delta value, we just handle horizontal
+ // scrolling entirely here. It'll be slightly off from native, but
+ // better than glitching out.
+ if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
+ if (dy)
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
+ e_preventDefault(e);
+ wheelStartX = null; // Abort measurement, if in progress
+ return;
+ }
+
+ if (dy && wheelPixelsPerUnit != null) {
+ var pixels = dy * wheelPixelsPerUnit;
+ var top = cm.view.scrollTop, bot = top + cm.display.wrapper.clientHeight;
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
+ else bot = Math.min(cm.view.doc.height, bot + pixels + 50);
+ updateDisplay(cm, [], {top: top, bottom: bot});
+ }
+
+ if (wheelSamples < 20) {
+ if (wheelStartX == null) {
+ wheelStartX = scroll.scrollLeft; wheelStartY = scroll.scrollTop;
+ wheelDX = dx; wheelDY = dy;
+ setTimeout(function() {
+ if (wheelStartX == null) return;
+ var movedX = scroll.scrollLeft - wheelStartX;
+ var movedY = scroll.scrollTop - wheelStartY;
+ var sample = (movedY && wheelDY && movedY / wheelDY) ||
+ (movedX && wheelDX && movedX / wheelDX);
+ wheelStartX = wheelStartY = null;
+ if (!sample) return;
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
+ ++wheelSamples;
+ }, 200);
+ } else {
+ wheelDX += dx; wheelDY += dy;
+ }
+ }
+ }
+
+ function doHandleBinding(cm, bound, dropShift) {
+ if (typeof bound == "string") {
+ bound = commands[bound];
+ if (!bound) return false;
+ }
+ // Ensure previous input has been read, so that the handler sees a
+ // consistent view of the document
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
+ var view = cm.view, prevShift = view.sel.shift;
+ try {
+ if (isReadOnly(cm)) view.suppressEdits = true;
+ if (dropShift) view.sel.shift = false;
+ bound(cm);
+ } catch(e) {
+ if (e != Pass) throw e;
+ return false;
+ } finally {
+ view.sel.shift = prevShift;
+ view.suppressEdits = false;
+ }
+ return true;
+ }
+
+ function allKeyMaps(cm) {
+ var maps = cm.view.keyMaps.slice(0);
+ maps.push(cm.options.keyMap);
+ if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys);
+ return maps;
+ }
+
+ var maybeTransition;
+ function handleKeyBinding(cm, e) {
+ // Handle auto keymap transitions
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
+ clearTimeout(maybeTransition);
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
+ if (getKeyMap(cm.options.keyMap) == startMap)
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
+ }, 50);
+
+ var name = keyNames[e_prop(e, "keyCode")], handled = false;
+ var flipCtrlCmd = mac && (opera || qtwebkit);
+ if (name == null || e.altGraphKey) return false;
+ if (e_prop(e, "altKey")) name = "Alt-" + name;
+ if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name;
+ if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name;
+
+ var stopped = false;
+ function stop() { stopped = true; }
+ var keymaps = allKeyMaps(cm);
+
+ if (e_prop(e, "shiftKey")) {
+ handled = lookupKey("Shift-" + name, keymaps,
+ function(b) {return doHandleBinding(cm, b, true);}, stop)
+ || lookupKey(name, keymaps, function(b) {
+ if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b);
+ }, stop);
+ } else {
+ handled = lookupKey(name, keymaps,
+ function(b) { return doHandleBinding(cm, b); }, stop);
+ }
+ if (stopped) handled = false;
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
+ }
+ return handled;
+ }
+
+ function handleCharBinding(cm, e, ch) {
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
+ function(b) { return doHandleBinding(cm, b, true); });
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ }
+ return handled;
+ }
+
+ var lastStoppedKey = null;
+ function onKeyDown(e) {
+ var cm = this;
+ if (!cm.view.focused) onFocus(cm);
+ if (ie && e.keyCode == 27) { e.returnValue = false; }
+ if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ var code = e_prop(e, "keyCode");
+ // IE does strange things with escape.
+ cm.view.sel.shift = code == 16 || e_prop(e, "shiftKey");
+ // First give onKeyEvent option a chance to handle this.
+ var handled = handleKeyBinding(cm, e);
+ if (opera) {
+ lastStoppedKey = handled ? code : null;
+ // Opera has no cut event... we try to at least catch the key combo
+ if (!handled && code == 88 && !hasCopyEvent && e_prop(e, mac ? "metaKey" : "ctrlKey"))
+ cm.replaceSelection("");
+ }
+ }
+
+ function onKeyPress(e) {
+ var cm = this;
+ if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
+ if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
+ if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
+ if (this.options.electricChars && this.view.mode.electricChars &&
+ this.options.smartIndent && !isReadOnly(this) &&
+ this.view.mode.electricChars.indexOf(ch) > -1)
+ setTimeout(operation(cm, function() {indentLine(cm, cm.view.sel.to.line, "smart");}), 75);
+ if (handleCharBinding(cm, e, ch)) return;
+ fastPoll(cm);
+ }
+
+ function onFocus(cm) {
+ if (cm.options.readOnly == "nocursor") return;
+ if (!cm.view.focused) {
+ signal(cm, "focus", cm);
+ cm.view.focused = true;
+ if (cm.display.scroller.className.search(/\bCodeMirror-focused\b/) == -1)
+ cm.display.scroller.className += " CodeMirror-focused";
+ resetInput(cm, true);
+ }
+ slowPoll(cm);
+ restartBlink(cm);
+ }
+ function onBlur(cm) {
+ if (cm.view.focused) {
+ signal(cm, "blur", cm);
+ cm.view.focused = false;
+ cm.display.scroller.className = cm.display.scroller.className.replace(" CodeMirror-focused", "");
+ }
+ clearInterval(cm.display.blinker);
+ setTimeout(function() {if (!cm.view.focused) cm.view.sel.shift = false;}, 150);
+ }
+
+ var detectingSelectAll;
+ function onContextMenu(cm, e) {
+ var display = cm.display, sel = cm.view.sel;
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
+ if (!pos || opera) return; // Opera is difficult.
+ if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
+ operation(cm, setSelection)(cm, pos, pos);
+
+ var oldCSS = display.input.style.cssText;
+ display.inputDiv.style.position = "absolute";
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
+ "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
+ focusInput(cm);
+ resetInput(cm, true);
+ // Adds "Select all" to context menu in FF
+ if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
+
+ function rehide() {
+ display.inputDiv.style.position = "relative";
+ display.input.style.cssText = oldCSS;
+ if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
+ slowPoll(cm);
+
+ // Try to detect the user choosing select-all
+ if (display.input.selectionStart != null) {
+ clearTimeout(detectingSelectAll);
+ var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
+ display.prevInput = " ";
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
+ detectingSelectAll = setTimeout(function poll(){
+ if (display.prevInput == " " && display.input.selectionStart == 0)
+ operation(cm, commands.selectAll)(cm);
+ else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
+ else resetInput(cm);
+ }, 200);
+ }
+ }
+
+ if (gecko) {
+ e_stop(e);
+ on(window, "mouseup", function mouseup() {
+ off(window, "mouseup", mouseup);
+ setTimeout(rehide, 20);
+ });
+ } else {
+ setTimeout(rehide, 50);
+ }
+ }
+
+ // UPDATING
+
+ // Replace the range from from to to by the strings in newText.
+ // Afterwards, set the selection to selFrom, selTo.
+ function updateDoc(cm, from, to, newText, selUpdate, origin) {
+ // Possibly split or suppress the update based on the presence
+ // of read-only spans in its range.
+ var split = sawReadOnlySpans &&
+ removeReadOnlyRanges(cm.view.doc, from, to);
+ if (split) {
+ for (var i = split.length - 1; i >= 1; --i)
+ updateDocInner(cm, split[i].from, split[i].to, [""], origin);
+ if (split.length)
+ return updateDocInner(cm, split[0].from, split[0].to, newText, selUpdate, origin);
+ } else {
+ return updateDocInner(cm, from, to, newText, selUpdate, origin);
+ }
+ }
+
+ function updateDocInner(cm, from, to, newText, selUpdate, origin) {
+ if (cm.view.suppressEdits) return;
+
+ var view = cm.view, doc = view.doc, old = [];
+ doc.iter(from.line, to.line + 1, function(line) {
+ old.push(newHL(line.text, line.markedSpans));
+ });
+ var startSelFrom = view.sel.from, startSelTo = view.sel.to;
+ var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText);
+ var retval = updateDocNoUndo(cm, from, to, lines, selUpdate, origin);
+ if (view.history) addChange(cm, from.line, newText.length, old, origin,
+ startSelFrom, startSelTo, view.sel.from, view.sel.to);
+ return retval;
+ }
+
+ function unredoHelper(cm, type) {
+ var doc = cm.view.doc, hist = cm.view.history;
+ var set = (type == "undo" ? hist.done : hist.undone).pop();
+ if (!set) return;
+ var anti = {events: [], fromBefore: set.fromAfter, toBefore: set.toAfter,
+ fromAfter: set.fromBefore, toAfter: set.toBefore};
+ for (var i = set.events.length - 1; i >= 0; i -= 1) {
+ hist.dirtyCounter += type == "undo" ? -1 : 1;
+ var change = set.events[i];
+ var replaced = [], end = change.start + change.added;
+ doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); });
+ anti.events.push({start: change.start, added: change.old.length, old: replaced});
+ var selPos = i ? null : {from: set.fromBefore, to: set.toBefore};
+ updateDocNoUndo(cm, {line: change.start, ch: 0}, {line: end - 1, ch: getLine(doc, end-1).text.length},
+ change.old, selPos, type);
+ }
+ (type == "undo" ? hist.undone : hist.done).push(anti);
+ }
+
+ function updateDocNoUndo(cm, from, to, lines, selUpdate, origin) {
+ var view = cm.view, doc = view.doc, display = cm.display;
+ if (view.suppressEdits) return;
+
+ var nlines = to.line - from.line, firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
+ var recomputeMaxLength = false, checkWidthStart = from.line;
+ if (!cm.options.lineWrapping) {
+ checkWidthStart = lineNo(visualLine(doc, firstLine));
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
+ if (lineLength(doc, line) == view.maxLineLength) {
+ recomputeMaxLength = true;
+ return true;
+ }
+ });
+ }
+
+ var lastHL = lst(lines), th = textHeight(display);
+
+ // First adjust the line structure
+ if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") {
+ // This is a whole-line replace. Treated specially to make
+ // sure line objects move the way they are supposed to.
+ var added = [];
+ for (var i = 0, e = lines.length - 1; i < e; ++i)
+ added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
+ updateLine(cm, lastLine, lastLine.text, hlSpans(lastHL));
+ if (nlines) doc.remove(from.line, nlines, cm);
+ if (added.length) doc.insert(from.line, added);
+ } else if (firstLine == lastLine) {
+ if (lines.length == 1) {
+ updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
+ firstLine.text.slice(to.ch), hlSpans(lines[0]));
+ } else {
+ for (var added = [], i = 1, e = lines.length - 1; i < e; ++i)
+ added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
+ added.push(makeLine(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL), th));
+ updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
+ doc.insert(from.line + 1, added);
+ }
+ } else if (lines.length == 1) {
+ updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
+ lastLine.text.slice(to.ch), hlSpans(lines[0]));
+ doc.remove(from.line + 1, nlines, cm);
+ } else {
+ var added = [];
+ updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
+ updateLine(cm, lastLine, hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL));
+ for (var i = 1, e = lines.length - 1; i < e; ++i)
+ added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1, cm);
+ doc.insert(from.line + 1, added);
+ }
+
+ if (cm.options.lineWrapping) {
+ var perLine = Math.max(5, display.scroller.clientWidth / charWidth(display) - 3);
+ doc.iter(from.line, from.line + lines.length, function(line) {
+ if (line.height == 0) return;
+ var guess = (Math.ceil(line.text.length / perLine) || 1) * th;
+ if (guess != line.height) updateLineHeight(line, guess);
+ });
+ } else {
+ doc.iter(checkWidthStart, from.line + lines.length, function(line) {
+ var len = lineLength(doc, line);
+ if (len > view.maxLineLength) {
+ view.maxLine = line;
+ view.maxLineLength = len;
+ view.maxLineChanged = true;
+ recomputeMaxLength = false;
+ }
+ });
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
+ }
+
+ // Adjust frontier, schedule worker
+ view.frontier = Math.min(view.frontier, from.line);
+ startWorker(cm, 400);
+
+ var lendiff = lines.length - nlines - 1;
+ // Remember that these lines changed, for updating the display
+ regChange(cm, from.line, to.line + 1, lendiff);
+ if (hasHandler(cm, "change")) {
+ // Normalize lines to contain only strings, since that's what
+ // the change event handler expects
+ for (var i = 0; i < lines.length; ++i)
+ if (typeof lines[i] != "string") lines[i] = lines[i].text;
+ var changeObj = {from: from, to: to, text: lines, origin: origin};
+ if (cm.curOp.textChanged) {
+ for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
+ cur.next = changeObj;
+ } else cm.curOp.textChanged = changeObj;
+ }
+
+ // Update the selection
+ var newSelFrom, newSelTo, end = {line: from.line + lines.length - 1,
+ ch: hlText(lastHL).length + (lines.length == 1 ? from.ch : 0)};
+ if (selUpdate && typeof selUpdate != "string") {
+ if (selUpdate.from) { newSelFrom = selUpdate.from; newSelTo = selUpdate.to; }
+ else newSelFrom = newSelTo = selUpdate;
+ } else if (selUpdate == "end") {
+ newSelFrom = newSelTo = end;
+ } else if (selUpdate == "start") {
+ newSelFrom = newSelTo = from;
+ } else if (selUpdate == "around") {
+ newSelFrom = from; newSelTo = end;
+ } else {
+ var adjustPos = function(pos) {
+ if (posLess(pos, from)) return pos;
+ if (!posLess(to, pos)) return end;
+ var line = pos.line + lendiff;
+ var ch = pos.ch;
+ if (pos.line == to.line)
+ ch += hlText(lastHL).length - (to.ch - (to.line == from.line ? from.ch : 0));
+ return {line: line, ch: ch};
+ };
+ newSelFrom = adjustPos(view.sel.from);
+ newSelTo = adjustPos(view.sel.to);
+ }
+ setSelection(cm, newSelFrom, newSelTo, null, true);
+ return end;
+ }
+
+ function replaceRange(cm, code, from, to, origin) {
+ if (!to) to = from;
+ if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
+ return updateDoc(cm, from, to, splitLines(code), null, origin);
+ }
+
+ // SELECTION
+
+ function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
+ function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
+ function copyPos(x) {return {line: x.line, ch: x.ch};}
+
+ function clipLine(doc, n) {return Math.max(0, Math.min(n, doc.size-1));}
+ function clipPos(doc, pos) {
+ if (pos.line < 0) return {line: 0, ch: 0};
+ if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc, doc.size-1).text.length};
+ var ch = pos.ch, linelen = getLine(doc, pos.line).text.length;
+ if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
+ else if (ch < 0) return {line: pos.line, ch: 0};
+ else return pos;
+ }
+ function isLine(doc, l) {return l >= 0 && l < doc.size;}
+
+ // If shift is held, this will move the selection anchor. Otherwise,
+ // it'll set the whole selection.
+ function extendSelection(cm, pos, other, bias) {
+ var sel = cm.view.sel;
+ if (sel.shift || sel.extend) {
+ var anchor = sel.anchor;
+ if (other) {
+ var posBefore = posLess(pos, anchor);
+ if (posBefore != posLess(other, anchor)) {
+ anchor = pos;
+ pos = other;
+ } else if (posBefore != posLess(pos, other)) {
+ pos = other;
+ }
+ }
+ setSelection(cm, anchor, pos, bias);
+ } else {
+ setSelection(cm, pos, other || pos, bias);
+ }
+ cm.curOp.userSelChange = true;
+ }
+
+ // Update the selection. Last two args are only used by
+ // updateDoc, since they have to be expressed in the line
+ // numbers before the update.
+ function setSelection(cm, anchor, head, bias, checkAtomic) {
+ cm.view.goalColumn = null;
+ var sel = cm.view.sel;
+ // Skip over atomic spans.
+ if (checkAtomic || !posEq(anchor, sel.anchor))
+ anchor = skipAtomic(cm, anchor, bias, checkAtomic != "push");
+ if (checkAtomic || !posEq(head, sel.head))
+ head = skipAtomic(cm, head, bias, checkAtomic != "push");
+
+ if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
+
+ sel.anchor = anchor; sel.head = head;
+ var inv = posLess(head, anchor);
+ sel.from = inv ? head : anchor;
+ sel.to = inv ? anchor : head;
+
+ cm.curOp.updateInput = true;
+ cm.curOp.selectionChanged = true;
+ }
+
+ function reCheckSelection(cm) {
+ setSelection(cm, cm.view.sel.from, cm.view.sel.to, null, "push");
+ }
+
+ function skipAtomic(cm, pos, bias, mayClear) {
+ var doc = cm.view.doc, flipped = false, curPos = pos;
+ var dir = bias || 1;
+ cm.view.cantEdit = false;
+ search: for (;;) {
+ var line = getLine(doc, curPos.line), toClear;
+ if (line.markedSpans) {
+ for (var i = 0; i < line.markedSpans.length; ++i) {
+ var sp = line.markedSpans[i], m = sp.marker;
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
+ if (mayClear && m.clearOnEnter) {
+ (toClear || (toClear = [])).push(m);
+ continue;
+ } else if (!m.atomic) continue;
+ var newPos = m.find()[dir < 0 ? "from" : "to"];
+ if (posEq(newPos, curPos)) {
+ newPos.ch += dir;
+ if (newPos.ch < 0) {
+ if (newPos.line) newPos = clipPos(doc, {line: newPos.line - 1});
+ else newPos = null;
+ } else if (newPos.ch > line.text.length) {
+ if (newPos.line < doc.size - 1) newPos = {line: newPos.line + 1, ch: 0};
+ else newPos = null;
+ }
+ if (!newPos) {
+ if (flipped) {
+ // Driven in a corner -- no valid cursor position found at all
+ // -- try again *with* clearing, if we didn't already
+ if (!mayClear) return skipAtomic(cm, pos, bias, true);
+ // Otherwise, turn off editing until further notice, and return the start of the doc
+ cm.view.cantEdit = true;
+ return {line: 0, ch: 0};
+ }
+ flipped = true; newPos = pos; dir = -dir;
+ }
+ }
+ curPos = newPos;
+ continue search;
+ }
+ }
+ if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear();
+ }
+ return curPos;
+ }
+ }
+
+ // SCROLLING
+
+ function scrollCursorIntoView(cm) {
+ var view = cm.view;
+ var coords = scrollPosIntoView(cm, view.sel.head);
+ if (!view.focused) return;
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
+ if (coords.top + box.top < 0) doScroll = true;
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
+ if (doScroll != null && !phantom) {
+ var hidden = display.cursor.style.display == "none";
+ if (hidden) {
+ display.cursor.style.display = "";
+ display.cursor.style.left = coords.left + "px";
+ display.cursor.style.top = (coords.top - display.viewOffset) + "px";
+ }
+ display.cursor.scrollIntoView(doScroll);
+ if (hidden) display.cursor.style.display = "none";
+ }
+ }
+
+ function scrollPosIntoView(cm, pos) {
+ for (;;) {
+ var changed = false, coords = cursorCoords(cm, pos);
+ var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
+ var startTop = cm.view.scrollTop, startLeft = cm.view.scrollLeft;
+ if (scrollPos.scrollTop != null) {
+ setScrollTop(cm, scrollPos.scrollTop);
+ if (Math.abs(cm.view.scrollTop - startTop) > 1) changed = true;
+ }
+ if (scrollPos.scrollLeft != null) {
+ setScrollLeft(cm, scrollPos.scrollLeft);
+ if (Math.abs(cm.view.scrollLeft - startLeft) > 1) changed = true;
+ }
+ if (!changed) return coords;
+ }
+ }
+
+ function scrollIntoView(cm, x1, y1, x2, y2) {
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
+ }
+
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
+ var display = cm.display, pt = paddingTop(display);
+ y1 += pt; y2 += pt;
+ var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
+ var docBottom = cm.view.doc.height + 2 * pt;
+ var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
+ if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
+ else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
+
+ var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
+ x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
+ var gutterw = display.gutters.offsetWidth;
+ var atLeft = x1 < gutterw + 10;
+ if (x1 < screenleft + gutterw || atLeft) {
+ if (atLeft) x1 = 0;
+ result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
+ } else if (x2 > screenw + screenleft - 3) {
+ result.scrollLeft = x2 + 10 - screenw;
+ }
+ return result;
+ }
+
+ // API UTILITIES
+
+ function indentLine(cm, n, how, aggressive) {
+ var doc = cm.view.doc;
+ if (!how) how = "add";
+ if (how == "smart") {
+ if (!cm.view.mode.indent) how = "prev";
+ else var state = getStateBefore(cm, n);
+ }
+
+ var tabSize = cm.options.tabSize;
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
+ if (how == "smart") {
+ indentation = cm.view.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
+ if (indentation == Pass) {
+ if (!aggressive) return;
+ how = "prev";
+ }
+ }
+ if (how == "prev") {
+ if (n) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
+ else indentation = 0;
+ }
+ else if (how == "add") indentation = curSpace + cm.options.indentUnit;
+ else if (how == "subtract") indentation = curSpace - cm.options.indentUnit;
+ indentation = Math.max(0, indentation);
+
+ var indentString = "", pos = 0;
+ if (cm.options.indentWithTabs)
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
+
+ if (indentString != curSpaceString)
+ replaceRange(cm, indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}, "input");
+ line.stateAfter = null;
+ }
+
+ function changeLine(cm, handle, op) {
+ var no = handle, line = handle, doc = cm.view.doc;
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
+ else no = lineNo(handle);
+ if (no == null) return null;
+ if (op(line, no)) regChange(cm, no, no + 1);
+ else return null;
+ return line;
+ }
+
+ function findPosH(cm, dir, unit, visually) {
+ var doc = cm.view.doc, end = cm.view.sel.head, line = end.line, ch = end.ch;
+ var lineObj = getLine(doc, line);
+ function findNextLine() {
+ var l = line + dir;
+ if (l < 0 || l == doc.size) return false;
+ line = l;
+ return lineObj = getLine(doc, l);
+ }
+ function moveOnce(boundToLine) {
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
+ if (next == null) {
+ if (!boundToLine && findNextLine()) {
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
+ else ch = dir < 0 ? lineObj.text.length : 0;
+ } else return false;
+ } else ch = next;
+ return true;
+ }
+ if (unit == "char") moveOnce();
+ else if (unit == "column") moveOnce(true);
+ else if (unit == "word") {
+ var sawWord = false;
+ for (;;) {
+ if (dir < 0) if (!moveOnce()) break;
+ if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
+ else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
+ if (dir > 0) if (!moveOnce()) break;
+ }
+ }
+ return skipAtomic(cm, {line: line, ch: ch}, dir, true);
+ }
+
+ function findWordAt(line, pos) {
+ var start = pos.ch, end = pos.ch;
+ if (line) {
+ if (pos.after === false || end == line.length) --start; else ++end;
+ var startChar = line.charAt(start);
+ var check = isWordChar(startChar) ? isWordChar :
+ /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
+ function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
+ while (start > 0 && check(line.charAt(start - 1))) --start;
+ while (end < line.length && check(line.charAt(end))) ++end;
+ }
+ return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
+ }
+
+ function selectLine(cm, line) {
+ extendSelection(cm, {line: line, ch: 0}, clipPos(cm.view.doc, {line: line + 1, ch: 0}));
+ }
+
+ // PROTOTYPE
+
+ // The publicly visible API. Note that operation(null, f) means
+ // 'wrap f in an operation, performed on its `this` parameter'
+
+ CodeMirror.prototype = {
+ getValue: function(lineSep) {
+ var text = [], doc = this.view.doc;
+ doc.iter(0, doc.size, function(line) { text.push(line.text); });
+ return text.join(lineSep || "\n");
+ },
+
+ setValue: operation(null, function(code) {
+ var doc = this.view.doc, top = {line: 0, ch: 0}, lastLen = getLine(doc, doc.size-1).text.length;
+ updateDocInner(this, top, {line: doc.size - 1, ch: lastLen}, splitLines(code), top, top, "setValue");
+ }),
+
+ getSelection: function(lineSep) { return this.getRange(this.view.sel.from, this.view.sel.to, lineSep); },
+
+ replaceSelection: operation(null, function(code, collapse, origin) {
+ var sel = this.view.sel;
+ updateDoc(this, sel.from, sel.to, splitLines(code), collapse || "around", origin);
+ }),
+
+ focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
+
+ setOption: function(option, value) {
+ var options = this.options, old = options[option];
+ if (options[option] == value && option != "mode") return;
+ options[option] = value;
+ if (optionHandlers.hasOwnProperty(option))
+ operation(this, optionHandlers[option])(this, value, old);
+ },
+
+ getOption: function(option) {return this.options[option];},
+
+ getMode: function() {return this.view.mode;},
+
+ addKeyMap: function(map) {
+ this.view.keyMaps.push(map);
+ },
+
+ removeKeyMap: function(map) {
+ var maps = this.view.keyMaps;
+ for (var i = 0; i < maps.length; ++i)
+ if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
+ maps.splice(i, 1);
+ return true;
+ }
+ },
+
+ undo: operation(null, function() {unredoHelper(this, "undo");}),
+ redo: operation(null, function() {unredoHelper(this, "redo");}),
+
+ indentLine: operation(null, function(n, dir, aggressive) {
+ if (typeof dir != "string") {
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
+ else dir = dir ? "add" : "subtract";
+ }
+ if (isLine(this.view.doc, n)) indentLine(this, n, dir, aggressive);
+ }),
+
+ indentSelection: operation(null, function(how) {
+ var sel = this.view.sel;
+ if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
+ for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
+ }),
+
+ historySize: function() {
+ var hist = this.view.history;
+ return {undo: hist.done.length, redo: hist.undone.length};
+ },
+
+ clearHistory: function() {this.view.history = makeHistory();},
+
+ markClean: function() {
+ this.view.history.dirtyCounter = 0;
+ this.view.history.lastOp = this.view.history.lastOrigin = null;
+ },
+
+ isClean: function () {return this.view.history.dirtyCounter == 0;},
+
+ getHistory: function() {
+ var hist = this.view.history;
+ function cp(arr) {
+ for (var i = 0, nw = [], nwelt; i < arr.length; ++i) {
+ var set = arr[i];
+ nw.push({events: nwelt = [], fromBefore: set.fromBefore, toBefore: set.toBefore,
+ fromAfter: set.fromAfter, toAfter: set.toAfter});
+ for (var j = 0, elt = set.events; j < elt.length; ++j) {
+ var old = [], cur = elt[j];
+ nwelt.push({start: cur.start, added: cur.added, old: old});
+ for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k]));
+ }
+ }
+ return nw;
+ }
+ return {done: cp(hist.done), undone: cp(hist.undone)};
+ },
+
+ setHistory: function(histData) {
+ var hist = this.view.history = makeHistory();
+ hist.done = histData.done;
+ hist.undone = histData.undone;
+ },
+
+ // Fetch the parser token for a given character. Useful for hacks
+ // that want to inspect the mode state (say, for completion).
+ getTokenAt: function(pos) {
+ var doc = this.view.doc;
+ pos = clipPos(doc, pos);
+ var state = getStateBefore(this, pos.line), mode = this.view.mode;
+ var line = getLine(doc, pos.line);
+ var stream = new StringStream(line.text, this.options.tabSize);
+ while (stream.pos < pos.ch && !stream.eol()) {
+ stream.start = stream.pos;
+ var style = mode.token(stream, state);
+ }
+ return {start: stream.start,
+ end: stream.pos,
+ string: stream.current(),
+ className: style || null, // Deprecated, use 'type' instead
+ type: style || null,
+ state: state};
+ },
+
+ getStateAfter: function(line) {
+ var doc = this.view.doc;
+ line = clipLine(doc, line == null ? doc.size - 1: line);
+ return getStateBefore(this, line + 1);
+ },
+
+ cursorCoords: function(start, mode) {
+ var pos, sel = this.view.sel;
+ if (start == null) pos = sel.head;
+ else if (typeof start == "object") pos = clipPos(this.view.doc, start);
+ else pos = start ? sel.from : sel.to;
+ return cursorCoords(this, pos, mode || "page");
+ },
+
+ charCoords: function(pos, mode) {
+ return charCoords(this, clipPos(this.view.doc, pos), mode || "page");
+ },
+
+ coordsChar: function(coords) {
+ var off = this.display.lineSpace.getBoundingClientRect();
+ return coordsChar(this, coords.left - off.left, coords.top - off.top);
+ },
+
+ defaultTextHeight: function() { return textHeight(this.display); },
+
+ markText: operation(null, function(from, to, options) {
+ return markText(this, clipPos(this.view.doc, from), clipPos(this.view.doc, to),
+ options, "range");
+ }),
+
+ setBookmark: operation(null, function(pos, widget) {
+ pos = clipPos(this.view.doc, pos);
+ return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark");
+ }),
+
+ findMarksAt: function(pos) {
+ var doc = this.view.doc;
+ pos = clipPos(doc, pos);
+ var markers = [], spans = getLine(doc, pos.line).markedSpans;
+ if (spans) for (var i = 0; i < spans.length; ++i) {
+ var span = spans[i];
+ if ((span.from == null || span.from <= pos.ch) &&
+ (span.to == null || span.to >= pos.ch))
+ markers.push(span.marker);
+ }
+ return markers;
+ },
+
+ setGutterMarker: operation(null, function(line, gutterID, value) {
+ return changeLine(this, line, function(line) {
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
+ markers[gutterID] = value;
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
+ return true;
+ });
+ }),
+
+ clearGutter: operation(null, function(gutterID) {
+ var i = 0, cm = this, doc = cm.view.doc;
+ doc.iter(0, doc.size, function(line) {
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
+ line.gutterMarkers[gutterID] = null;
+ regChange(cm, i, i + 1);
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
+ }
+ ++i;
+ });
+ }),
+
+ addLineClass: operation(null, function(handle, where, cls) {
+ return changeLine(this, handle, function(line) {
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+ if (!line[prop]) line[prop] = cls;
+ else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false;
+ else line[prop] += " " + cls;
+ return true;
+ });
+ }),
+
+ removeLineClass: operation(null, function(handle, where, cls) {
+ return changeLine(this, handle, function(line) {
+ var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+ var cur = line[prop];
+ if (!cur) return false;
+ else if (cls == null) line[prop] = null;
+ else {
+ var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
+ if (upd == cur) return false;
+ line[prop] = upd || null;
+ }
+ return true;
+ });
+ }),
+
+ addLineWidget: operation(null, function(handle, node, options) {
+ var widget = options || {};
+ widget.node = node;
+ if (widget.noHScroll) this.display.alignWidgets = true;
+ changeLine(this, handle, function(line) {
+ (line.widgets || (line.widgets = [])).push(widget);
+ widget.line = line;
+ return true;
+ });
+ return widget;
+ }),
+
+ removeLineWidget: operation(null, function(widget) {
+ var ws = widget.line.widgets, no = lineNo(widget.line);
+ if (no == null) return;
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == widget) ws.splice(i--, 1);
+ regChange(this, no, no + 1);
+ }),
+
+ lineInfo: function(line) {
+ if (typeof line == "number") {
+ if (!isLine(this.view.doc, line)) return null;
+ var n = line;
+ line = getLine(this.view.doc, line);
+ if (!line) return null;
+ } else {
+ var n = lineNo(line);
+ if (n == null) return null;
+ }
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
+ widgets: line.widgets};
+ },
+
+ getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
+
+ addWidget: function(pos, node, scroll, vert, horiz) {
+ var display = this.display;
+ pos = cursorCoords(this, clipPos(this.view.doc, pos));
+ var top = pos.top, left = pos.left;
+ node.style.position = "absolute";
+ display.sizer.appendChild(node);
+ if (vert == "over") top = pos.top;
+ else if (vert == "near") {
+ var vspace = Math.max(display.wrapper.clientHeight, this.view.doc.height),
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
+ if (pos.bottom + node.offsetHeight > vspace && pos.top > node.offsetHeight)
+ top = pos.top - node.offsetHeight;
+ if (left + node.offsetWidth > hspace)
+ left = hspace - node.offsetWidth;
+ }
+ node.style.top = (top + paddingTop(display)) + "px";
+ node.style.left = node.style.right = "";
+ if (horiz == "right") {
+ left = display.sizer.clientWidth - node.offsetWidth;
+ node.style.right = "0px";
+ } else {
+ if (horiz == "left") left = 0;
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
+ node.style.left = left + "px";
+ }
+ if (scroll)
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
+ },
+
+ lineCount: function() {return this.view.doc.size;},
+
+ clipPos: function(pos) {return clipPos(this.view.doc, pos);},
+
+ getCursor: function(start) {
+ var sel = this.view.sel, pos;
+ if (start == null || start == "head") pos = sel.head;
+ else if (start == "anchor") pos = sel.anchor;
+ else if (start == "end" || start === false) pos = sel.to;
+ else pos = sel.from;
+ return copyPos(pos);
+ },
+
+ somethingSelected: function() {return !posEq(this.view.sel.from, this.view.sel.to);},
+
+ setCursor: operation(null, function(line, ch, extend) {
+ var pos = clipPos(this.view.doc, typeof line == "number" ? {line: line, ch: ch || 0} : line);
+ if (extend) extendSelection(this, pos);
+ else setSelection(this, pos, pos);
+ }),
+
+ setSelection: operation(null, function(anchor, head) {
+ var doc = this.view.doc;
+ setSelection(this, clipPos(doc, anchor), clipPos(doc, head || anchor));
+ }),
+
+ extendSelection: operation(null, function(from, to) {
+ var doc = this.view.doc;
+ extendSelection(this, clipPos(doc, from), to && clipPos(doc, to));
+ }),
+
+ setExtending: function(val) {this.view.sel.extend = val;},
+
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
+
+ getLineHandle: function(line) {
+ var doc = this.view.doc;
+ if (isLine(doc, line)) return getLine(doc, line);
+ },
+
+ getLineNumber: function(line) {return lineNo(line);},
+
+ setLine: operation(null, function(line, text) {
+ if (isLine(this.view.doc, line))
+ replaceRange(this, text, {line: line, ch: 0}, {line: line, ch: getLine(this.view.doc, line).text.length});
+ }),
+
+ removeLine: operation(null, function(line) {
+ if (isLine(this.view.doc, line))
+ replaceRange(this, "", {line: line, ch: 0}, clipPos(this.view.doc, {line: line+1, ch: 0}));
+ }),
+
+ replaceRange: operation(null, function(code, from, to) {
+ var doc = this.view.doc;
+ from = clipPos(doc, from);
+ to = to ? clipPos(doc, to) : from;
+ return replaceRange(this, code, from, to);
+ }),
+
+ getRange: function(from, to, lineSep) {
+ var doc = this.view.doc;
+ from = clipPos(doc, from); to = clipPos(doc, to);
+ var l1 = from.line, l2 = to.line;
+ if (l1 == l2) return getLine(doc, l1).text.slice(from.ch, to.ch);
+ var code = [getLine(doc, l1).text.slice(from.ch)];
+ doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
+ code.push(getLine(doc, l2).text.slice(0, to.ch));
+ return code.join(lineSep || "\n");
+ },
+
+ triggerOnKeyDown: operation(null, onKeyDown),
+
+ execCommand: function(cmd) {return commands[cmd](this);},
+
+ // Stuff used by commands, probably not much use to outside code.
+ moveH: operation(null, function(dir, unit) {
+ var sel = this.view.sel, pos = dir < 0 ? sel.from : sel.to;
+ if (sel.shift || sel.extend || posEq(sel.from, sel.to)) pos = findPosH(this, dir, unit, true);
+ extendSelection(this, pos, pos, dir);
+ }),
+
+ deleteH: operation(null, function(dir, unit) {
+ var sel = this.view.sel;
+ if (!posEq(sel.from, sel.to)) replaceRange(this, "", sel.from, sel.to, "delete");
+ else replaceRange(this, "", sel.from, findPosH(this, dir, unit, false), "delete");
+ this.curOp.userSelChange = true;
+ }),
+
+ moveV: operation(null, function(dir, unit) {
+ var view = this.view, doc = view.doc, display = this.display;
+ var cur = view.sel.head, pos = cursorCoords(this, cur, "div");
+ var x = pos.left, y;
+ if (view.goalColumn != null) x = view.goalColumn;
+ if (unit == "page") {
+ var pageSize = Math.min(display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
+ y = pos.top + dir * pageSize;
+ } else if (unit == "line") {
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
+ }
+ do {
+ var target = coordsChar(this, x, y);
+ y += dir * 5;
+ } while (target.outside && (dir < 0 ? y > 0 : y < doc.height));
+
+ if (unit == "page") display.scrollbarV.scrollTop += charCoords(this, target, "div").top - pos.top;
+ extendSelection(this, target, target, dir);
+ view.goalColumn = x;
+ }),
+
+ toggleOverwrite: function() {
+ if (this.view.overwrite = !this.view.overwrite)
+ this.display.cursor.className += " CodeMirror-overwrite";
+ else
+ this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
+ },
+
+ posFromIndex: function(off) {
+ var lineNo = 0, ch, doc = this.view.doc;
+ doc.iter(0, doc.size, function(line) {
+ var sz = line.text.length + 1;
+ if (sz > off) { ch = off; return true; }
+ off -= sz;
+ ++lineNo;
+ });
+ return clipPos(doc, {line: lineNo, ch: ch});
+ },
+ indexFromPos: function (coords) {
+ if (coords.line < 0 || coords.ch < 0) return 0;
+ var index = coords.ch;
+ this.view.doc.iter(0, coords.line, function (line) {
+ index += line.text.length + 1;
+ });
+ return index;
+ },
+
+ scrollTo: function(x, y) {
+ if (x != null) this.display.scrollbarH.scrollLeft = this.display.scroller.scrollLeft = x;
+ if (y != null) this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = y;
+ updateDisplay(this, []);
+ },
+ getScrollInfo: function() {
+ var scroller = this.display.scroller, co = scrollerCutOff;
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
+ height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
+ clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
+ },
+
+ scrollIntoView: function(pos) {
+ if (typeof pos == "number") pos = {line: pos, ch: 0};
+ pos = pos ? clipPos(this.view.doc, pos) : this.view.sel.head;
+ scrollPosIntoView(this, pos);
+ },
+
+ setSize: function(width, height) {
+ function interpret(val) {
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
+ }
+ if (width != null) this.display.wrapper.style.width = interpret(width);
+ if (height != null) this.display.wrapper.style.height = interpret(height);
+ this.refresh();
+ },
+
+ on: function(type, f) {on(this, type, f);},
+ off: function(type, f) {off(this, type, f);},
+
+ operation: function(f){return operation(this, f)();},
+
+ refresh: function() {
+ clearCaches(this);
+ if (this.display.scroller.scrollHeight > this.view.scrollTop)
+ this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = this.view.scrollTop;
+ updateDisplay(this, true);
+ },
+
+ getInputField: function(){return this.display.input;},
+ getWrapperElement: function(){return this.display.wrapper;},
+ getScrollerElement: function(){return this.display.scroller;},
+ getGutterElement: function(){return this.display.gutters;}
+ };
+
+ // OPTION DEFAULTS
+
+ var optionHandlers = CodeMirror.optionHandlers = {};
+
+ // The default configuration options.
+ var defaults = CodeMirror.defaults = {};
+
+ function option(name, deflt, handle, notOnInit) {
+ CodeMirror.defaults[name] = deflt;
+ if (handle) optionHandlers[name] =
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
+ }
+
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
+
+ // These two are, on init, called from the constructor because they
+ // have to be initialized before the editor can start at all.
+ option("value", "", function(cm, val) {cm.setValue(val);}, true);
+ option("mode", null, loadMode, true);
+
+ option("indentUnit", 2, loadMode, true);
+ option("indentWithTabs", false);
+ option("smartIndent", true);
+ option("tabSize", 4, function(cm) {
+ loadMode(cm);
+ clearCaches(cm);
+ updateDisplay(cm, true);
+ }, true);
+ option("electricChars", true);
+
+ option("theme", "default", function(cm) {
+ themeChanged(cm);
+ guttersChanged(cm);
+ }, true);
+ option("keyMap", "default", keyMapChanged);
+ option("extraKeys", null);
+
+ option("onKeyEvent", null);
+ option("onDragEvent", null);
+
+ option("lineWrapping", false, wrappingChanged, true);
+ option("gutters", [], function(cm) {
+ setGuttersForLineNumbers(cm.options);
+ guttersChanged(cm);
+ }, true);
+ option("lineNumbers", false, function(cm) {
+ setGuttersForLineNumbers(cm.options);
+ guttersChanged(cm);
+ }, true);
+ option("firstLineNumber", 1, guttersChanged, true);
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
+ option("showCursorWhenSelecting", false, updateSelection, true);
+
+ option("readOnly", false, function(cm, val) {
+ if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
+ else if (!val) resetInput(cm, true);
+ });
+ option("dragDrop", true);
+
+ option("cursorBlinkRate", 530);
+ option("cursorHeight", 1);
+ option("workTime", 100);
+ option("workDelay", 100);
+ option("flattenSpans", true);
+ option("pollInterval", 100);
+ option("undoDepth", 40);
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
+
+ option("tabindex", null, function(cm, val) {
+ cm.display.input.tabIndex = val || "";
+ });
+ option("autofocus", null);
+
+ // MODE DEFINITION AND QUERYING
+
+ // Known modes, by name and by MIME
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
+
+ CodeMirror.defineMode = function(name, mode) {
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
+ if (arguments.length > 2) {
+ mode.dependencies = [];
+ for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
+ }
+ modes[name] = mode;
+ };
+
+ CodeMirror.defineMIME = function(mime, spec) {
+ mimeModes[mime] = spec;
+ };
+
+ CodeMirror.resolveMode = function(spec) {
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
+ spec = mimeModes[spec];
+ else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
+ return CodeMirror.resolveMode("application/xml");
+ if (typeof spec == "string") return {name: spec};
+ else return spec || {name: "null"};
+ };
+
+ CodeMirror.getMode = function(options, spec) {
+ var spec = CodeMirror.resolveMode(spec);
+ var mfactory = modes[spec.name];
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
+ var modeObj = mfactory(options, spec);
+ if (modeExtensions.hasOwnProperty(spec.name)) {
+ var exts = modeExtensions[spec.name];
+ for (var prop in exts) {
+ if (!exts.hasOwnProperty(prop)) continue;
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
+ modeObj[prop] = exts[prop];
+ }
+ }
+ modeObj.name = spec.name;
+ return modeObj;
+ };
+
+ CodeMirror.defineMode("null", function() {
+ return {token: function(stream) {stream.skipToEnd();}};
+ });
+ CodeMirror.defineMIME("text/plain", "null");
+
+ var modeExtensions = CodeMirror.modeExtensions = {};
+ CodeMirror.extendMode = function(mode, properties) {
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+ for (var prop in properties) if (properties.hasOwnProperty(prop))
+ exts[prop] = properties[prop];
+ };
+
+ // EXTENSIONS
+
+ CodeMirror.defineExtension = function(name, func) {
+ CodeMirror.prototype[name] = func;
+ };
+
+ CodeMirror.defineOption = option;
+
+ var initHooks = [];
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
+
+ // MODE STATE HANDLING
+
+ // Utility functions for working with state. Exported because modes
+ // sometimes need to do this.
+ function copyState(mode, state) {
+ if (state === true) return state;
+ if (mode.copyState) return mode.copyState(state);
+ var nstate = {};
+ for (var n in state) {
+ var val = state[n];
+ if (val instanceof Array) val = val.concat([]);
+ nstate[n] = val;
+ }
+ return nstate;
+ }
+ CodeMirror.copyState = copyState;
+
+ function startState(mode, a1, a2) {
+ return mode.startState ? mode.startState(a1, a2) : true;
+ }
+ CodeMirror.startState = startState;
+
+ CodeMirror.innerMode = function(mode, state) {
+ while (mode.innerMode) {
+ var info = mode.innerMode(state);
+ state = info.state;
+ mode = info.mode;
+ }
+ return info || {mode: mode, state: state};
+ };
+
+ // STANDARD COMMANDS
+
+ var commands = CodeMirror.commands = {
+ selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
+ killLine: function(cm) {
+ var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
+ if (!sel && cm.getLine(from.line).length == from.ch)
+ cm.replaceRange("", from, {line: from.line + 1, ch: 0}, "delete");
+ else cm.replaceRange("", from, sel ? to : {line: from.line}, "delete");
+ },
+ deleteLine: function(cm) {
+ var l = cm.getCursor().line;
+ cm.replaceRange("", {line: l, ch: 0}, {line: l}, "delete");
+ },
+ undo: function(cm) {cm.undo();},
+ redo: function(cm) {cm.redo();},
+ goDocStart: function(cm) {cm.extendSelection({line: 0, ch: 0});},
+ goDocEnd: function(cm) {cm.extendSelection({line: cm.lineCount() - 1});},
+ goLineStart: function(cm) {
+ cm.extendSelection(lineStart(cm, cm.getCursor().line));
+ },
+ goLineStartSmart: function(cm) {
+ var cur = cm.getCursor(), start = lineStart(cm, cur.line);
+ var line = cm.getLineHandle(start.line);
+ var order = getOrder(line);
+ if (!order || order[0].level == 0) {
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
+ var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
+ cm.extendSelection({line: start.line, ch: inWS ? 0 : firstNonWS});
+ } else cm.extendSelection(start);
+ },
+ goLineEnd: function(cm) {
+ cm.extendSelection(lineEnd(cm, cm.getCursor().line));
+ },
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
+ goLineDown: function(cm) {cm.moveV(1, "line");},
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
+ goPageDown: function(cm) {cm.moveV(1, "page");},
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
+ goCharRight: function(cm) {cm.moveH(1, "char");},
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
+ goWordRight: function(cm) {cm.moveH(1, "word");},
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
+ indentAuto: function(cm) {cm.indentSelection("smart");},
+ indentMore: function(cm) {cm.indentSelection("add");},
+ indentLess: function(cm) {cm.indentSelection("subtract");},
+ insertTab: function(cm) {cm.replaceSelection("\t", "end", "input");},
+ defaultTab: function(cm) {
+ if (cm.somethingSelected()) cm.indentSelection("add");
+ else cm.replaceSelection("\t", "end", "input");
+ },
+ transposeChars: function(cm) {
+ var cur = cm.getCursor(), line = cm.getLine(cur.line);
+ if (cur.ch > 0 && cur.ch < line.length - 1)
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
+ {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
+ },
+ newlineAndIndent: function(cm) {
+ operation(cm, function() {
+ cm.replaceSelection("\n", "end", "input");
+ cm.indentLine(cm.getCursor().line, null, true);
+ })();
+ },
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
+ };
+
+ // STANDARD KEYMAPS
+
+ var keyMap = CodeMirror.keyMap = {};
+ keyMap.basic = {
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
+ };
+ // Note that the save and find-related commands aren't defined by
+ // default. Unknown commands are simply ignored.
+ keyMap.pcDefault = {
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
+ "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
+ "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
+ "Ctrl-Backspace": "delWordBefore", "Ctrl-Delete": "delWordAfter", "Ctrl-S": "save", "Ctrl-F": "find",
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
+ fallthrough: "basic"
+ };
+ keyMap.macDefault = {
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
+ "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordBefore",
+ "Ctrl-Alt-Backspace": "delWordAfter", "Alt-Delete": "delWordAfter", "Cmd-S": "save", "Cmd-F": "find",
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore",
+ fallthrough: ["basic", "emacsy"]
+ };
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
+ keyMap.emacsy = {
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
+ };
+
+ // KEYMAP DISPATCH
+
+ function getKeyMap(val) {
+ if (typeof val == "string") return keyMap[val];
+ else return val;
+ }
+
+ function lookupKey(name, maps, handle, stop) {
+ function lookup(map) {
+ map = getKeyMap(map);
+ var found = map[name];
+ if (found === false) {
+ if (stop) stop();
+ return true;
+ }
+ if (found != null && handle(found)) return true;
+ if (map.nofallthrough) {
+ if (stop) stop();
+ return true;
+ }
+ var fallthrough = map.fallthrough;
+ if (fallthrough == null) return false;
+ if (Object.prototype.toString.call(fallthrough) != "[object Array]")
+ return lookup(fallthrough);
+ for (var i = 0, e = fallthrough.length; i < e; ++i) {
+ if (lookup(fallthrough[i])) return true;
+ }
+ return false;
+ }
+
+ for (var i = 0; i < maps.length; ++i)
+ if (lookup(maps[i])) return true;
+ }
+ function isModifierKey(event) {
+ var name = keyNames[e_prop(event, "keyCode")];
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
+ }
+ CodeMirror.isModifierKey = isModifierKey;
+
+ // FROMTEXTAREA
+
+ CodeMirror.fromTextArea = function(textarea, options) {
+ if (!options) options = {};
+ options.value = textarea.value;
+ if (!options.tabindex && textarea.tabindex)
+ options.tabindex = textarea.tabindex;
+ // Set autofocus to true if this textarea is focused, or if it has
+ // autofocus and no other element is focused.
+ if (options.autofocus == null) {
+ var hasFocus = document.body;
+ // doc.activeElement occasionally throws on IE
+ try { hasFocus = document.activeElement; } catch(e) {}
+ options.autofocus = hasFocus == textarea ||
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
+ }
+
+ function save() {textarea.value = cm.getValue();}
+ if (textarea.form) {
+ // Deplorable hack to make the submit method do the right thing.
+ on(textarea.form, "submit", save);
+ var form = textarea.form, realSubmit = form.submit;
+ try {
+ form.submit = function wrappedSubmit() {
+ save();
+ form.submit = realSubmit;
+ form.submit();
+ form.submit = wrappedSubmit;
+ };
+ } catch(e) {}
+ }
+
+ textarea.style.display = "none";
+ var cm = CodeMirror(function(node) {
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
+ }, options);
+ cm.save = save;
+ cm.getTextArea = function() { return textarea; };
+ cm.toTextArea = function() {
+ save();
+ textarea.parentNode.removeChild(cm.getWrapperElement());
+ textarea.style.display = "";
+ if (textarea.form) {
+ off(textarea.form, "submit", save);
+ if (typeof textarea.form.submit == "function")
+ textarea.form.submit = realSubmit;
+ }
+ };
+ return cm;
+ };
+
+ // STRING STREAM
+
+ // Fed to the mode parsers, provides helper functions to make
+ // parsers more succinct.
+
+ // The character stream used by a mode's parser.
+ function StringStream(string, tabSize) {
+ this.pos = this.start = 0;
+ this.string = string;
+ this.tabSize = tabSize || 8;
+ }
+
+ StringStream.prototype = {
+ eol: function() {return this.pos >= this.string.length;},
+ sol: function() {return this.pos == 0;},
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
+ next: function() {
+ if (this.pos < this.string.length)
+ return this.string.charAt(this.pos++);
+ },
+ eat: function(match) {
+ var ch = this.string.charAt(this.pos);
+ if (typeof match == "string") var ok = ch == match;
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
+ if (ok) {++this.pos; return ch;}
+ },
+ eatWhile: function(match) {
+ var start = this.pos;
+ while (this.eat(match)){}
+ return this.pos > start;
+ },
+ eatSpace: function() {
+ var start = this.pos;
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+ return this.pos > start;
+ },
+ skipToEnd: function() {this.pos = this.string.length;},
+ skipTo: function(ch) {
+ var found = this.string.indexOf(ch, this.pos);
+ if (found > -1) {this.pos = found; return true;}
+ },
+ backUp: function(n) {this.pos -= n;},
+ column: function() {return countColumn(this.string, this.start, this.tabSize);},
+ indentation: function() {return countColumn(this.string, null, this.tabSize);},
+ match: function(pattern, consume, caseInsensitive) {
+ if (typeof pattern == "string") {
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+ if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+ if (consume !== false) this.pos += pattern.length;
+ return true;
+ }
+ } else {
+ var match = this.string.slice(this.pos).match(pattern);
+ if (match && match.index > 0) return null;
+ if (match && consume !== false) this.pos += match[0].length;
+ return match;
+ }
+ },
+ current: function(){return this.string.slice(this.start, this.pos);}
+ };
+ CodeMirror.StringStream = StringStream;
+
+ // TEXTMARKERS
+
+ function TextMarker(cm, type) {
+ this.lines = [];
+ this.type = type;
+ this.cm = cm;
+ }
+
+ TextMarker.prototype.clear = function() {
+ if (this.explicitlyCleared) return;
+ startOperation(this.cm);
+ var min = null, max = null;
+ for (var i = 0; i < this.lines.length; ++i) {
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
+ if (span.to != null) max = lineNo(line);
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
+ if (span.from != null)
+ min = lineNo(line);
+ else if (this.collapsed && !lineIsHidden(line))
+ updateLineHeight(line, textHeight(this.cm.display));
+ }
+ if (min != null) regChange(this.cm, min, max + 1);
+ this.lines.length = 0;
+ this.explicitlyCleared = true;
+ if (this.collapsed && this.cm.view.cantEdit) {
+ this.cm.view.cantEdit = false;
+ reCheckSelection(this.cm);
+ }
+ endOperation(this.cm);
+ signalLater(this.cm, this, "clear");
+ };
+
+ TextMarker.prototype.find = function() {
+ var from, to;
+ for (var i = 0; i < this.lines.length; ++i) {
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
+ if (span.from != null || span.to != null) {
+ var found = lineNo(line);
+ if (span.from != null) from = {line: found, ch: span.from};
+ if (span.to != null) to = {line: found, ch: span.to};
+ }
+ }
+ if (this.type == "bookmark") return from;
+ return from && {from: from, to: to};
+ };
+
+ function markText(cm, from, to, options, type) {
+ var doc = cm.view.doc;
+ var marker = new TextMarker(cm, type);
+ if (type == "range" && !posLess(from, to)) return marker;
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
+ marker[opt] = options[opt];
+ if (marker.replacedWith) {
+ marker.collapsed = true;
+ marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
+ }
+ if (marker.collapsed) sawCollapsedSpans = true;
+
+ var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd;
+ doc.iter(curLine, to.line + 1, function(line) {
+ var span = {from: null, to: null, marker: marker};
+ size += line.text.length;
+ if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
+ if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
+ if (marker.collapsed) {
+ if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
+ if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
+ else updateLineHeight(line, 0);
+ }
+ addMarkedSpan(line, span);
+ if (marker.collapsed && curLine == from.line && lineIsHidden(line))
+ updateLineHeight(line, 0);
+ ++curLine;
+ });
+
+ if (marker.readOnly) {
+ sawReadOnlySpans = true;
+ if (cm.view.history.done.length || cm.view.history.undone.length)
+ cm.clearHistory();
+ }
+ if (marker.collapsed) {
+ if (collapsedAtStart != collapsedAtEnd)
+ throw new Error("Inserting collapsed marker overlapping an existing one");
+ marker.size = size;
+ marker.atomic = true;
+ }
+ if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
+ regChange(cm, from.line, to.line + 1);
+ if (marker.atomic) reCheckSelection(cm);
+ return marker;
+ }
+
+ // TEXTMARKER SPANS
+
+ function getMarkedSpanFor(spans, marker) {
+ if (spans) for (var i = 0; i < spans.length; ++i) {
+ var span = spans[i];
+ if (span.marker == marker) return span;
+ }
+ }
+ function removeMarkedSpan(spans, span) {
+ for (var r, i = 0; i < spans.length; ++i)
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
+ return r;
+ }
+ function addMarkedSpan(line, span) {
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
+ span.marker.lines.push(line);
+ }
+
+ function markedSpansBefore(old, startCh) {
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
+ var span = old[i], marker = span.marker;
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
+ if (startsBefore || marker.type == "bookmark" && span.from == startCh) {
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
+ (nw || (nw = [])).push({from: span.from,
+ to: endsAfter ? null : span.to,
+ marker: marker});
+ }
+ }
+ return nw;
+ }
+
+ function markedSpansAfter(old, startCh, endCh) {
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
+ var span = old[i], marker = span.marker;
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
+ if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.from != startCh) {
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
+ (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
+ to: span.to == null ? null : span.to - endCh,
+ marker: marker});
+ }
+ }
+ return nw;
+ }
+
+ function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) {
+ if (!oldFirst && !oldLast) return newText;
+ // Get the spans that 'stick out' on both sides
+ var first = markedSpansBefore(oldFirst, startCh);
+ var last = markedSpansAfter(oldLast, startCh, endCh);
+
+ // Next, merge those two ends
+ var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0);
+ if (first) {
+ // Fix up .to properties of first
+ for (var i = 0; i < first.length; ++i) {
+ var span = first[i];
+ if (span.to == null) {
+ var found = getMarkedSpanFor(last, span.marker);
+ if (!found) span.to = startCh;
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
+ }
+ }
+ }
+ if (last) {
+ // Fix up .from in last (or move them into first in case of sameLine)
+ for (var i = 0; i < last.length; ++i) {
+ var span = last[i];
+ if (span.to != null) span.to += offset;
+ if (span.from == null) {
+ var found = getMarkedSpanFor(first, span.marker);
+ if (!found) {
+ span.from = offset;
+ if (sameLine) (first || (first = [])).push(span);
+ }
+ } else {
+ span.from += offset;
+ if (sameLine) (first || (first = [])).push(span);
+ }
+ }
+ }
+
+ var newMarkers = [newHL(newText[0], first)];
+ if (!sameLine) {
+ // Fill gap with whole-line-spans
+ var gap = newText.length - 2, gapMarkers;
+ if (gap > 0 && first)
+ for (var i = 0; i < first.length; ++i)
+ if (first[i].to == null)
+ (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
+ for (var i = 0; i < gap; ++i)
+ newMarkers.push(newHL(newText[i+1], gapMarkers));
+ newMarkers.push(newHL(lst(newText), last));
+ }
+ return newMarkers;
+ }
+
+ function removeReadOnlyRanges(doc, from, to) {
+ var markers = null;
+ doc.iter(from.line, to.line + 1, function(line) {
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
+ var mark = line.markedSpans[i].marker;
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
+ (markers || (markers = [])).push(mark);
+ }
+ });
+ if (!markers) return null;
+ var parts = [{from: from, to: to}];
+ for (var i = 0; i < markers.length; ++i) {
+ var m = markers[i].find();
+ for (var j = 0; j < parts.length; ++j) {
+ var p = parts[j];
+ if (!posLess(m.from, p.to) || posLess(m.to, p.from)) continue;
+ var newParts = [j, 1];
+ if (posLess(p.from, m.from)) newParts.push({from: p.from, to: m.from});
+ if (posLess(m.to, p.to)) newParts.push({from: m.to, to: p.to});
+ parts.splice.apply(parts, newParts);
+ j += newParts.length - 1;
+ }
+ }
+ return parts;
+ }
+
+ function collapsedSpanAt(line, ch) {
+ var sps = sawCollapsedSpans && line.markedSpans, found;
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+ sp = sps[i];
+ if (!sp.marker.collapsed) continue;
+ if ((sp.from == null || sp.from < ch) &&
+ (sp.to == null || sp.to > ch) &&
+ (!found || found.width < sp.marker.width))
+ found = sp.marker;
+ }
+ return found;
+ }
+ function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
+ function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
+
+ function visualLine(doc, line) {
+ var merged;
+ while (merged = collapsedSpanAtStart(line))
+ line = getLine(doc, merged.find().from.line);
+ return line;
+ }
+
+ function lineIsHidden(line) {
+ var sps = sawCollapsedSpans && line.markedSpans;
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+ sp = sps[i];
+ if (!sp.marker.collapsed) continue;
+ if (sp.from == null) return true;
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(line, sp))
+ return true;
+ }
+ }
+ window.lineIsHidden = lineIsHidden;
+ function lineIsHiddenInner(line, span) {
+ if (span.to == null || span.marker.inclusiveRight && span.to == line.text.length)
+ return true;
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
+ sp = line.markedSpans[i];
+ if (sp.marker.collapsed && sp.from == span.to &&
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
+ lineIsHiddenInner(line, sp)) return true;
+ }
+ }
+
+ // hl stands for history-line, a data structure that can be either a
+ // string (line without markers) or a {text, markedSpans} object.
+ function hlText(val) { return typeof val == "string" ? val : val.text; }
+ function hlSpans(val) {
+ if (typeof val == "string") return null;
+ var spans = val.markedSpans, out = null;
+ for (var i = 0; i < spans.length; ++i) {
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
+ else if (out) out.push(spans[i]);
+ }
+ return !out ? spans : out.length ? out : null;
+ }
+ function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
+
+ function detachMarkedSpans(line) {
+ var spans = line.markedSpans;
+ if (!spans) return;
+ for (var i = 0; i < spans.length; ++i) {
+ var lines = spans[i].marker.lines;
+ var ix = indexOf(lines, line);
+ lines.splice(ix, 1);
+ }
+ line.markedSpans = null;
+ }
+
+ function attachMarkedSpans(line, spans) {
+ if (!spans) return;
+ for (var i = 0; i < spans.length; ++i)
+ spans[i].marker.lines.push(line);
+ line.markedSpans = spans;
+ }
+
+ // LINE DATA STRUCTURE
+
+ // Line objects. These hold state related to a line, including
+ // highlighting info (the styles array).
+ function makeLine(text, markedSpans, height) {
+ var line = {text: text, height: height};
+ attachMarkedSpans(line, markedSpans);
+ if (lineIsHidden(line)) line.height = 0;
+ return line;
+ }
+
+ function updateLine(cm, line, text, markedSpans) {
+ line.text = text;
+ line.stateAfter = line.styles = null;
+ if (line.order != null) line.order = null;
+ detachMarkedSpans(line);
+ attachMarkedSpans(line, markedSpans);
+ if (lineIsHidden(line)) line.height = 0;
+ else if (!line.height) line.height = textHeight(cm.display);
+ signalLater(cm, line, "change");
+ }
+
+ function cleanUpLine(line) {
+ line.parent = null;
+ detachMarkedSpans(line);
+ }
+
+ // Run the given mode's parser over a line, update the styles
+ // array, which contains alternating fragments of text and CSS
+ // classes.
+ function highlightLine(cm, line, state) {
+ var mode = cm.view.mode, flattenSpans = cm.options.flattenSpans;
+ var changed = !line.styles, pos = 0, curText = "", curStyle = null;
+ var stream = new StringStream(line.text, cm.options.tabSize), st = line.styles || (line.styles = []);
+ if (line.text == "" && mode.blankLine) mode.blankLine(state);
+ while (!stream.eol()) {
+ var style = mode.token(stream, state), substr = stream.current();
+ stream.start = stream.pos;
+ if (!flattenSpans || curStyle != style) {
+ if (curText) {
+ changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
+ st[pos++] = curText; st[pos++] = curStyle;
+ }
+ curText = substr; curStyle = style;
+ } else curText = curText + substr;
+ // Give up when line is ridiculously long
+ if (stream.pos > 5000) break;
+ }
+ if (curText) {
+ changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
+ st[pos++] = curText; st[pos++] = curStyle;
+ }
+ if (stream.pos > 5000) { st[pos++] = line.text.slice(stream.pos); st[pos++] = null; }
+ if (pos != st.length) { st.length = pos; changed = true; }
+ return changed;
+ }
+
+ // Lightweight form of highlight -- proceed over this line and
+ // update state, but don't save a style array.
+ function processLine(cm, line, state) {
+ var mode = cm.view.mode;
+ var stream = new StringStream(line.text, cm.options.tabSize);
+ if (line.text == "" && mode.blankLine) mode.blankLine(state);
+ while (!stream.eol() && stream.pos <= 5000) {
+ mode.token(stream, state);
+ stream.start = stream.pos;
+ }
+ }
+
+ var styleToClassCache = {};
+ function styleToClass(style) {
+ if (!style) return null;
+ return styleToClassCache[style] ||
+ (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
+ }
+
+ function lineContent(cm, realLine, measure) {
+ var merged, line = realLine, lineBefore, sawBefore, simple = true;
+ while (merged = collapsedSpanAtStart(line)) {
+ simple = false;
+ line = getLine(cm.view.doc, merged.find().from.line);
+ if (!lineBefore) lineBefore = line;
+ }
+
+ var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
+ measure: null, addedOne: false, cm: cm};
+ if (line.textClass) builder.pre.className = line.textClass;
+
+ do {
+ if (!line.styles)
+ highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
+ builder.measure = line == realLine && measure;
+ builder.pos = 0;
+ builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
+ if (measure && sawBefore && line != realLine && !builder.addedOne) {
+ measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
+ builder.addedOne = true;
+ }
+ var next = insertLineContent(line, builder);
+ sawBefore = line == lineBefore;
+ if (next) {
+ line = getLine(cm.view.doc, next.to.line);
+ simple = false;
+ }
+ } while (next);
+
+ if (measure && !builder.addedOne)
+ measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
+ if (!builder.pre.firstChild && !lineIsHidden(realLine))
+ builder.pre.appendChild(document.createTextNode("\u00a0"));
+
+ return builder.pre;
+ }
+
+ var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
+ function buildToken(builder, text, style, startStyle, endStyle) {
+ if (!text) return;
+ if (!tokenSpecialChars.test(text)) {
+ builder.col += text.length;
+ var content = document.createTextNode(text);
+ } else {
+ var content = document.createDocumentFragment(), pos = 0;
+ while (true) {
+ tokenSpecialChars.lastIndex = pos;
+ var m = tokenSpecialChars.exec(text);
+ var skipped = m ? m.index - pos : text.length - pos;
+ if (skipped) {
+ content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
+ builder.col += skipped;
+ }
+ if (!m) break;
+ pos += skipped + 1;
+ if (m[0] == "\t") {
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
+ content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
+ builder.col += tabWidth;
+ } else {
+ var token = elt("span", "\u2022", "cm-invalidchar");
+ token.title = "\\u" + m[0].charCodeAt(0).toString(16);
+ content.appendChild(token);
+ builder.col += 1;
+ }
+ }
+ }
+ if (style || startStyle || endStyle || builder.measure) {
+ var fullStyle = style || "";
+ if (startStyle) fullStyle += startStyle;
+ if (endStyle) fullStyle += endStyle;
+ return builder.pre.appendChild(elt("span", [content], fullStyle));
+ }
+ builder.pre.appendChild(content);
+ }
+
+ function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
+ for (var i = 0; i < text.length; ++i) {
+ if (i && i < text.length - 1 &&
+ builder.cm.options.lineWrapping &&
+ spanAffectsWrapping.test(text.slice(i - 1, i + 1)))
+ builder.pre.appendChild(elt("wbr"));
+ builder.measure[builder.pos++] =
+ buildToken(builder, text.charAt(i), style,
+ i == 0 && startStyle, i == text.length - 1 && endStyle);
+ }
+ if (text.length) builder.addedOne = true;
+ }
+
+ function buildCollapsedSpan(builder, size, widget) {
+ if (widget) {
+ if (!builder.display) widget = widget.cloneNode(true);
+ builder.pre.appendChild(widget);
+ if (builder.measure && size) {
+ builder.measure[builder.pos] = widget;
+ builder.addedOne = true;
+ }
+ }
+ builder.pos += size;
+ }
+
+ // Outputs a number of spans to make up a line, taking highlighting
+ // and marked text into account.
+ function insertLineContent(line, builder) {
+ var st = line.styles, spans = line.markedSpans;
+ if (!spans) {
+ for (var i = 0; i < st.length; i+=2)
+ builder.addToken(builder, st[i], styleToClass(st[i+1]));
+ return;
+ }
+
+ var allText = line.text, len = allText.length;
+ var pos = 0, i = 0, text = "", style;
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
+ for (;;) {
+ if (nextChange == pos) { // Update current marker set
+ spanStyle = spanEndStyle = spanStartStyle = "";
+ collapsed = null; nextChange = Infinity;
+ var foundBookmark = null;
+ for (var j = 0; j < spans.length; ++j) {
+ var sp = spans[j], m = sp.marker;
+ if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
+ if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+ if (m.className) spanStyle += " " + m.className;
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
+ if (m.collapsed && (!collapsed || collapsed.marker.width < m.width))
+ collapsed = sp;
+ } else if (sp.from > pos && nextChange > sp.from) {
+ nextChange = sp.from;
+ }
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
+ foundBookmark = m.replacedWith;
+ }
+ if (collapsed && (collapsed.from || 0) == pos) {
+ buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
+ collapsed.from != null && collapsed.marker.replacedWith);
+ if (collapsed.to == null) return collapsed.marker.find();
+ }
+ if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
+ }
+ if (pos >= len) break;
+
+ var upto = Math.min(len, nextChange);
+ while (true) {
+ if (text) {
+ var end = pos + text.length;
+ if (!collapsed) {
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
+ builder.addToken(builder, tokenText, style + spanStyle,
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
+ }
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+ pos = end;
+ spanStartStyle = "";
+ }
+ text = st[i++]; style = styleToClass(st[i++]);
+ }
+ }
+ }
+
+ // DOCUMENT DATA STRUCTURE
+
+ function LeafChunk(lines) {
+ this.lines = lines;
+ this.parent = null;
+ for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
+ lines[i].parent = this;
+ height += lines[i].height;
+ }
+ this.height = height;
+ }
+
+ LeafChunk.prototype = {
+ chunkSize: function() { return this.lines.length; },
+ remove: function(at, n, cm) {
+ for (var i = at, e = at + n; i < e; ++i) {
+ var line = this.lines[i];
+ this.height -= line.height;
+ cleanUpLine(line);
+ signalLater(cm, line, "delete");
+ }
+ this.lines.splice(at, n);
+ },
+ collapse: function(lines) {
+ lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
+ },
+ insertHeight: function(at, lines, height) {
+ this.height += height;
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
+ for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
+ },
+ iterN: function(at, n, op) {
+ for (var e = at + n; at < e; ++at)
+ if (op(this.lines[at])) return true;
+ }
+ };
+
+ function BranchChunk(children) {
+ this.children = children;
+ var size = 0, height = 0;
+ for (var i = 0, e = children.length; i < e; ++i) {
+ var ch = children[i];
+ size += ch.chunkSize(); height += ch.height;
+ ch.parent = this;
+ }
+ this.size = size;
+ this.height = height;
+ this.parent = null;
+ }
+
+ BranchChunk.prototype = {
+ chunkSize: function() { return this.size; },
+ remove: function(at, n, callbacks) {
+ this.size -= n;
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at < sz) {
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
+ child.remove(at, rm, callbacks);
+ this.height -= oldHeight - child.height;
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
+ if ((n -= rm) == 0) break;
+ at = 0;
+ } else at -= sz;
+ }
+ if (this.size - n < 25) {
+ var lines = [];
+ this.collapse(lines);
+ this.children = [new LeafChunk(lines)];
+ this.children[0].parent = this;
+ }
+ },
+ collapse: function(lines) {
+ for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
+ },
+ insert: function(at, lines) {
+ var height = 0;
+ for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
+ this.insertHeight(at, lines, height);
+ },
+ insertHeight: function(at, lines, height) {
+ this.size += lines.length;
+ this.height += height;
+ for (var i = 0, e = this.children.length; i < e; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at <= sz) {
+ child.insertHeight(at, lines, height);
+ if (child.lines && child.lines.length > 50) {
+ while (child.lines.length > 50) {
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
+ var newleaf = new LeafChunk(spilled);
+ child.height -= newleaf.height;
+ this.children.splice(i + 1, 0, newleaf);
+ newleaf.parent = this;
+ }
+ this.maybeSpill();
+ }
+ break;
+ }
+ at -= sz;
+ }
+ },
+ maybeSpill: function() {
+ if (this.children.length <= 10) return;
+ var me = this;
+ do {
+ var spilled = me.children.splice(me.children.length - 5, 5);
+ var sibling = new BranchChunk(spilled);
+ if (!me.parent) { // Become the parent node
+ var copy = new BranchChunk(me.children);
+ copy.parent = me;
+ me.children = [copy, sibling];
+ me = copy;
+ } else {
+ me.size -= sibling.size;
+ me.height -= sibling.height;
+ var myIndex = indexOf(me.parent.children, me);
+ me.parent.children.splice(myIndex + 1, 0, sibling);
+ }
+ sibling.parent = me.parent;
+ } while (me.children.length > 10);
+ me.parent.maybeSpill();
+ },
+ iter: function(from, to, op) { this.iterN(from, to - from, op); },
+ iterN: function(at, n, op) {
+ for (var i = 0, e = this.children.length; i < e; ++i) {
+ var child = this.children[i], sz = child.chunkSize();
+ if (at < sz) {
+ var used = Math.min(n, sz - at);
+ if (child.iterN(at, used, op)) return true;
+ if ((n -= used) == 0) break;
+ at = 0;
+ } else at -= sz;
+ }
+ }
+ };
+
+ // LINE UTILITIES
+
+ function getLine(chunk, n) {
+ while (!chunk.lines) {
+ for (var i = 0;; ++i) {
+ var child = chunk.children[i], sz = child.chunkSize();
+ if (n < sz) { chunk = child; break; }
+ n -= sz;
+ }
+ }
+ return chunk.lines[n];
+ }
+
+ function updateLineHeight(line, height) {
+ var diff = height - line.height;
+ for (var n = line; n; n = n.parent) n.height += diff;
+ }
+
+ function lineNo(line) {
+ if (line.parent == null) return null;
+ var cur = line.parent, no = indexOf(cur.lines, line);
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
+ for (var i = 0;; ++i) {
+ if (chunk.children[i] == cur) break;
+ no += chunk.children[i].chunkSize();
+ }
+ }
+ return no;
+ }
+
+ function lineAtHeight(chunk, h) {
+ var n = 0;
+ outer: do {
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
+ var child = chunk.children[i], ch = child.height;
+ if (h < ch) { chunk = child; continue outer; }
+ h -= ch;
+ n += child.chunkSize();
+ }
+ return n;
+ } while (!chunk.lines);
+ for (var i = 0, e = chunk.lines.length; i < e; ++i) {
+ var line = chunk.lines[i], lh = line.height;
+ if (h < lh) break;
+ h -= lh;
+ }
+ return n + i;
+ }
+
+ function heightAtLine(cm, lineObj) {
+ lineObj = visualLine(cm.view.doc, lineObj);
+
+ var h = 0, chunk = lineObj.parent;
+ for (var i = 0; i < chunk.lines.length; ++i) {
+ var line = chunk.lines[i];
+ if (line == lineObj) break;
+ else h += line.height;
+ }
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
+ for (var i = 0; i < p.children.length; ++i) {
+ var cur = p.children[i];
+ if (cur == chunk) break;
+ else h += cur.height;
+ }
+ }
+ return h;
+ }
+
+ function getOrder(line) {
+ var order = line.order;
+ if (order == null) order = line.order = bidiOrdering(line.text);
+ return order;
+ }
+
+ // HISTORY
+
+ function makeHistory() {
+ return {
+ // Arrays of history events. Doing something adds an event to
+ // done and clears undo. Undoing moves events from done to
+ // undone, redoing moves them in the other direction.
+ done: [], undone: [],
+ // Used to track when changes can be merged into a single undo
+ // event
+ lastTime: 0, lastOp: null, lastOrigin: null,
+ // Used by the isClean() method
+ dirtyCounter: 0
+ };
+ }
+
+ function addChange(cm, start, added, old, origin, fromBefore, toBefore, fromAfter, toAfter) {
+ var history = cm.view.history;
+ history.undone.length = 0;
+ var time = +new Date, cur = lst(history.done);
+
+ if (cur &&
+ (history.lastOp == cm.curOp.id ||
+ history.lastOrigin == origin && (origin == "input" || origin == "delete") &&
+ history.lastTime > time - 600)) {
+ // Merge this change into the last event
+ var last = lst(cur.events);
+ if (last.start > start + old.length || last.start + last.added < start) {
+ // Doesn't intersect with last sub-event, add new sub-event
+ cur.events.push({start: start, added: added, old: old});
+ } else {
+ // Patch up the last sub-event
+ var startBefore = Math.max(0, last.start - start),
+ endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
+ for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
+ for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
+ if (startBefore) last.start = start;
+ last.added += added - (old.length - startBefore - endAfter);
+ }
+ cur.fromAfter = fromAfter; cur.toAfter = toAfter;
+ } else {
+ // Can not be merged, start a new event.
+ cur = {events: [{start: start, added: added, old: old}],
+ fromBefore: fromBefore, toBefore: toBefore, fromAfter: fromAfter, toAfter: toAfter};
+ history.done.push(cur);
+ while (history.done.length > cm.options.undoDepth)
+ history.done.shift();
+ if (history.dirtyCounter < 0)
+ // The user has made a change after undoing past the last clean state.
+ // We can never get back to a clean state now until markClean() is called.
+ history.dirtyCounter = NaN;
+ else
+ history.dirtyCounter++;
+ }
+ history.lastTime = time;
+ history.lastOp = cm.curOp.id;
+ history.lastOrigin = origin;
+ }
+
+ // EVENT OPERATORS
+
+ function stopMethod() {e_stop(this);}
+ // Ensure an event has a stop method.
+ function addStop(event) {
+ if (!event.stop) event.stop = stopMethod;
+ return event;
+ }
+
+ function e_preventDefault(e) {
+ if (e.preventDefault) e.preventDefault();
+ else e.returnValue = false;
+ }
+ function e_stopPropagation(e) {
+ if (e.stopPropagation) e.stopPropagation();
+ else e.cancelBubble = true;
+ }
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
+ CodeMirror.e_stop = e_stop;
+ CodeMirror.e_preventDefault = e_preventDefault;
+ CodeMirror.e_stopPropagation = e_stopPropagation;
+
+ function e_target(e) {return e.target || e.srcElement;}
+ function e_button(e) {
+ var b = e.which;
+ if (b == null) {
+ if (e.button & 1) b = 1;
+ else if (e.button & 2) b = 3;
+ else if (e.button & 4) b = 2;
+ }
+ if (mac && e.ctrlKey && b == 1) b = 3;
+ return b;
+ }
+
+ // Allow 3rd-party code to override event properties by adding an override
+ // object to an event object.
+ function e_prop(e, prop) {
+ var overridden = e.override && e.override.hasOwnProperty(prop);
+ return overridden ? e.override[prop] : e[prop];
+ }
+
+ // EVENT HANDLING
+
+ function on(emitter, type, f) {
+ if (emitter.addEventListener)
+ emitter.addEventListener(type, f, false);
+ else if (emitter.attachEvent)
+ emitter.attachEvent("on" + type, f);
+ else {
+ var map = emitter._handlers || (emitter._handlers = {});
+ var arr = map[type] || (map[type] = []);
+ arr.push(f);
+ }
+ }
+
+ function off(emitter, type, f) {
+ if (emitter.removeEventListener)
+ emitter.removeEventListener(type, f, false);
+ else if (emitter.detachEvent)
+ emitter.detachEvent("on" + type, f);
+ else {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ for (var i = 0; i < arr.length; ++i)
+ if (arr[i] == f) { arr.splice(i, 1); break; }
+ }
+ }
+
+ function signal(emitter, type /*, values...*/) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ var args = Array.prototype.slice.call(arguments, 2);
+ for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
+ }
+
+ function signalLater(cm, emitter, type /*, values...*/) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ if (!arr) return;
+ var args = Array.prototype.slice.call(arguments, 3), flist = cm.curOp && cm.curOp.delayedCallbacks;
+ function bnd(f) {return function(){f.apply(null, args);};};
+ for (var i = 0; i < arr.length; ++i)
+ if (flist) flist.push(bnd(arr[i]));
+ else arr[i].apply(null, args);
+ }
+
+ function hasHandler(emitter, type) {
+ var arr = emitter._handlers && emitter._handlers[type];
+ return arr && arr.length > 0;
+ }
+
+ CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
+
+ // MISC UTILITIES
+
+ // Number of pixels added to scroller and sizer to hide scrollbar
+ var scrollerCutOff = 30;
+
+ // Returned or thrown by various protocols to signal 'I'm not
+ // handling this'.
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
+
+ function Delayed() {this.id = null;}
+ Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
+
+ // Counts the column offset in a string, taking tabs into account.
+ // Used mostly to find indentation.
+ function countColumn(string, end, tabSize) {
+ if (end == null) {
+ end = string.search(/[^\s\u00a0]/);
+ if (end == -1) end = string.length;
+ }
+ for (var i = 0, n = 0; i < end; ++i) {
+ if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
+ else ++n;
+ }
+ return n;
+ }
+ CodeMirror.countColumn = countColumn;
+
+ var spaceStrs = [""];
+ function spaceStr(n) {
+ while (spaceStrs.length <= n)
+ spaceStrs.push(lst(spaceStrs) + " ");
+ return spaceStrs[n];
+ }
+
+ function lst(arr) { return arr[arr.length-1]; }
+
+ function selectInput(node) {
+ if (ios) { // Mobile Safari apparently has a bug where select() is broken.
+ node.selectionStart = 0;
+ node.selectionEnd = node.value.length;
+ } else node.select();
+ }
+
+ function indexOf(collection, elt) {
+ if (collection.indexOf) return collection.indexOf(elt);
+ for (var i = 0, e = collection.length; i < e; ++i)
+ if (collection[i] == elt) return i;
+ return -1;
+ }
+
+ function emptyArray(size) {
+ for (var a = [], i = 0; i < size; ++i) a.push(undefined);
+ return a;
+ }
+
+ function bind(f) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function(){return f.apply(null, args);};
+ }
+
+ var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
+ function isWordChar(ch) {
+ return /\w/.test(ch) || ch > "\x80" &&
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
+ }
+
+ function isEmpty(obj) {
+ var c = 0;
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) ++c;
+ return !c;
+ }
+
+ var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F]/;
+
+ // DOM UTILITIES
+
+ function elt(tag, content, className, style) {
+ var e = document.createElement(tag);
+ if (className) e.className = className;
+ if (style) e.style.cssText = style;
+ if (typeof content == "string") setTextContent(e, content);
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
+ return e;
+ }
+
+ function removeChildren(e) {
+ e.innerHTML = "";
+ return e;
+ }
+
+ function removeChildrenAndAdd(parent, e) {
+ return removeChildren(parent).appendChild(e);
+ }
+
+ function setTextContent(e, str) {
+ if (ie_lt9) {
+ e.innerHTML = "";
+ e.appendChild(document.createTextNode(str));
+ } else e.textContent = str;
+ }
+
+ // FEATURE DETECTION
+
+ // Detect drag-and-drop
+ var dragAndDrop = function() {
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
+ // couldn't get it to work yet.
+ if (ie_lt9) return false;
+ var div = elt('div');
+ return "draggable" in div || "dragDrop" in div;
+ }();
+
+ // For a reason I have yet to figure out, some browsers disallow
+ // word wrapping between certain characters *only* if a new inline
+ // element is started between them. This makes it hard to reliably
+ // measure the position of things, since that requires inserting an
+ // extra span. This terribly fragile set of regexps matches the
+ // character combinations that suffer from this phenomenon on the
+ // various browsers.
+ var spanAffectsWrapping = /^$/; // Won't match any two-character string
+ if (gecko) spanAffectsWrapping = /$'/;
+ else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
+ else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
+
+ var knownScrollbarWidth;
+ function scrollbarWidth(measure) {
+ if (knownScrollbarWidth != null) return knownScrollbarWidth;
+ var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
+ removeChildrenAndAdd(measure, test);
+ if (test.offsetWidth)
+ knownScrollbarWidth = test.offsetHeight - test.clientHeight;
+ return knownScrollbarWidth || 0;
+ }
+
+ var zwspSupported;
+ function zeroWidthElement(measure) {
+ if (zwspSupported == null) {
+ var test = elt("span", "\u200b");
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
+ if (measure.firstChild.offsetHeight != 0)
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
+ }
+ if (zwspSupported) return elt("span", "\u200b");
+ else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
+ }
+
+ // See if "".split is the broken IE version, if so, provide an
+ // alternative way to split lines.
+ var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
+ var pos = 0, result = [], l = string.length;
+ while (pos <= l) {
+ var nl = string.indexOf("\n", pos);
+ if (nl == -1) nl = string.length;
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
+ var rt = line.indexOf("\r");
+ if (rt != -1) {
+ result.push(line.slice(0, rt));
+ pos += rt + 1;
+ } else {
+ result.push(line);
+ pos = nl + 1;
+ }
+ }
+ return result;
+ } : function(string){return string.split(/\r\n?|\n/);};
+ CodeMirror.splitLines = splitLines;
+
+ var hasSelection = window.getSelection ? function(te) {
+ try { return te.selectionStart != te.selectionEnd; }
+ catch(e) { return false; }
+ } : function(te) {
+ try {var range = te.ownerDocument.selection.createRange();}
+ catch(e) {}
+ if (!range || range.parentElement() != te) return false;
+ return range.compareEndPoints("StartToEnd", range) != 0;
+ };
+
+ var hasCopyEvent = (function() {
+ var e = elt("div");
+ if ("oncopy" in e) return true;
+ e.setAttribute("oncopy", "return;");
+ return typeof e.oncopy == 'function';
+ })();
+
+ // KEY NAMING
+
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
+ 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+ 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
+ 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
+ CodeMirror.keyNames = keyNames;
+ (function() {
+ // Number keys
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
+ // Alphabetic keys
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
+ // Function keys
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
+ })();
+
+ // BIDI HELPERS
+
+ function iterateBidiSections(order, from, to, f) {
+ if (!order) return f(from, to, "ltr");
+ for (var i = 0; i < order.length; ++i) {
+ var part = order[i];
+ if (part.from < to && part.to > from)
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
+ }
+ }
+
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
+
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
+ function lineRight(line) {
+ var order = getOrder(line);
+ if (!order) return line.text.length;
+ return bidiRight(lst(order));
+ }
+
+ function lineStart(cm, lineN) {
+ var line = getLine(cm.view.doc, lineN);
+ var visual = visualLine(cm.view.doc, line);
+ if (visual != line) lineN = lineNo(visual);
+ var order = getOrder(visual);
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
+ return {line: lineN, ch: ch};
+ }
+ function lineEnd(cm, lineNo) {
+ var merged, line;
+ while (merged = collapsedSpanAtEnd(line = getLine(cm.view.doc, lineNo)))
+ lineNo = merged.find().to.line;
+ var order = getOrder(line);
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
+ return {line: lineNo, ch: ch};
+ }
+
+ // This is somewhat involved. It is needed in order to move
+ // 'visually' through bi-directional text -- i.e., pressing left
+ // should make the cursor go left, even when in RTL text. The
+ // tricky part is the 'jumps', where RTL and LTR text touch each
+ // other. This often requires the cursor offset to move more than
+ // one unit, in order to visually move one unit.
+ function moveVisually(line, start, dir, byUnit) {
+ var bidi = getOrder(line);
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
+ var moveOneUnit = byUnit ? function(pos, dir) {
+ do pos += dir;
+ while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
+ return pos;
+ } : function(pos, dir) { return pos + dir; };
+ var linedir = bidi[0].level;
+ for (var i = 0; i < bidi.length; ++i) {
+ var part = bidi[i], sticky = part.level % 2 == linedir;
+ if ((part.from < start && part.to > start) ||
+ (sticky && (part.from == start || part.to == start))) break;
+ }
+ var target = moveOneUnit(start, part.level % 2 ? -dir : dir);
+
+ while (target != null) {
+ if (part.level % 2 == linedir) {
+ if (target < part.from || target > part.to) {
+ part = bidi[i += dir];
+ target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1));
+ } else break;
+ } else {
+ if (target == bidiLeft(part)) {
+ part = bidi[--i];
+ target = part && bidiRight(part);
+ } else if (target == bidiRight(part)) {
+ part = bidi[++i];
+ target = part && bidiLeft(part);
+ } else break;
+ }
+ }
+
+ return target < 0 || target > line.text.length ? null : target;
+ }
+
+ function moveLogically(line, start, dir, byUnit) {
+ var target = start + dir;
+ if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
+ return target < 0 || target > line.text.length ? null : target;
+ }
+
+ // Bidirectional ordering algorithm
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
+ // that this (partially) implements.
+
+ // One-char codes used for character types:
+ // L (L): Left-to-Right
+ // R (R): Right-to-Left
+ // r (AL): Right-to-Left Arabic
+ // 1 (EN): European Number
+ // + (ES): European Number Separator
+ // % (ET): European Number Terminator
+ // n (AN): Arabic Number
+ // , (CS): Common Number Separator
+ // m (NSM): Non-Spacing Mark
+ // b (BN): Boundary Neutral
+ // s (B): Paragraph Separator
+ // t (S): Segment Separator
+ // w (WS): Whitespace
+ // N (ON): Other Neutrals
+
+ // Returns null if characters are ordered as they appear
+ // (left-to-right), or an array of sections ({from, to, level}
+ // objects) in the order in which they occur visually.
+ var bidiOrdering = (function() {
+ // Character types for codepoints 0 to 0xff
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
+ // Character types for codepoints 0x600 to 0x6ff
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
+ function charType(code) {
+ if (code <= 0xff) return lowTypes.charAt(code);
+ else if (0x590 <= code && code <= 0x5f4) return "R";
+ else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
+ else if (0x700 <= code && code <= 0x8ac) return "r";
+ else return "L";
+ }
+
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
+
+ return function charOrdering(str) {
+ if (!bidiRE.test(str)) return false;
+ var len = str.length, types = [], startType = null;
+ for (var i = 0, type; i < len; ++i) {
+ types.push(type = charType(str.charCodeAt(i)));
+ if (startType == null) {
+ if (type == "L") startType = "L";
+ else if (type == "R" || type == "r") startType = "R";
+ }
+ }
+ if (startType == null) startType = "L";
+
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
+ // change the type of the NSM to the type of the previous
+ // character. If the NSM is at the start of the level run, it will
+ // get the type of sor.
+ for (var i = 0, prev = startType; i < len; ++i) {
+ var type = types[i];
+ if (type == "m") types[i] = prev;
+ else prev = type;
+ }
+
+ // W2. Search backwards from each instance of a European number
+ // until the first strong type (R, L, AL, or sor) is found. If an
+ // AL is found, change the type of the European number to Arabic
+ // number.
+ // W3. Change all ALs to R.
+ for (var i = 0, cur = startType; i < len; ++i) {
+ var type = types[i];
+ if (type == "1" && cur == "r") types[i] = "n";
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
+ }
+
+ // W4. A single European separator between two European numbers
+ // changes to a European number. A single common separator between
+ // two numbers of the same type changes to that type.
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
+ var type = types[i];
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
+ else if (type == "," && prev == types[i+1] &&
+ (prev == "1" || prev == "n")) types[i] = prev;
+ prev = type;
+ }
+
+ // W5. A sequence of European terminators adjacent to European
+ // numbers changes to all European numbers.
+ // W6. Otherwise, separators and terminators change to Other
+ // Neutral.
+ for (var i = 0; i < len; ++i) {
+ var type = types[i];
+ if (type == ",") types[i] = "N";
+ else if (type == "%") {
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
+ var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
+ for (var j = i; j < end; ++j) types[j] = replace;
+ i = end - 1;
+ }
+ }
+
+ // W7. Search backwards from each instance of a European number
+ // until the first strong type (R, L, or sor) is found. If an L is
+ // found, then change the type of the European number to L.
+ for (var i = 0, cur = startType; i < len; ++i) {
+ var type = types[i];
+ if (cur == "L" && type == "1") types[i] = "L";
+ else if (isStrong.test(type)) cur = type;
+ }
+
+ // N1. A sequence of neutrals takes the direction of the
+ // surrounding strong text if the text on both sides has the same
+ // direction. European and Arabic numbers act as if they were R in
+ // terms of their influence on neutrals. Start-of-level-run (sor)
+ // and end-of-level-run (eor) are used at level run boundaries.
+ // N2. Any remaining neutrals take the embedding direction.
+ for (var i = 0; i < len; ++i) {
+ if (isNeutral.test(types[i])) {
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
+ var before = (i ? types[i-1] : startType) == "L";
+ var after = (end < len - 1 ? types[end] : startType) == "L";
+ var replace = before || after ? "L" : "R";
+ for (var j = i; j < end; ++j) types[j] = replace;
+ i = end - 1;
+ }
+ }
+
+ // Here we depart from the documented algorithm, in order to avoid
+ // building up an actual levels array. Since there are only three
+ // levels (0, 1, 2) in an implementation that doesn't take
+ // explicit embedding into account, we can build up the order on
+ // the fly, without following the level-based algorithm.
+ var order = [], m;
+ for (var i = 0; i < len;) {
+ if (countsAsLeft.test(types[i])) {
+ var start = i;
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
+ order.push({from: start, to: i, level: 0});
+ } else {
+ var pos = i, at = order.length;
+ for (++i; i < len && types[i] != "L"; ++i) {}
+ for (var j = pos; j < i;) {
+ if (countsAsNum.test(types[j])) {
+ if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
+ var nstart = j;
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
+ order.splice(at, 0, {from: nstart, to: j, level: 2});
+ pos = j;
+ } else ++j;
+ }
+ if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
+ }
+ }
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
+ order[0].from = m[0].length;
+ order.unshift({from: 0, to: m[0].length, level: 0});
+ }
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
+ lst(order).to -= m[0].length;
+ order.push({from: len - m[0].length, to: len, level: 0});
+ }
+ if (order[0].level != lst(order).level)
+ order.push({from: len, to: len, level: order[0].level});
+
+ return order;
+ };
+ })();
+
+ // THE END
+
+ CodeMirror.version = "3.0";
+
+ return CodeMirror;
+})();
diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,300 @@
+CodeMirror.defineMode("clike", function(config, parserConfig) {
+ var indentUnit = config.indentUnit,
+ statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
+ keywords = parserConfig.keywords || {},
+ builtin = parserConfig.builtin || {},
+ blockKeywords = parserConfig.blockKeywords || {},
+ atoms = parserConfig.atoms || {},
+ hooks = parserConfig.hooks || {},
+ multiLineStrings = parserConfig.multiLineStrings;
+ var isOperatorChar = /[+\-*&%=<>!?|\/]/;
+
+ var curPunc;
+
+ function tokenBase(stream, state) {
+ var ch = stream.next();
+ if (hooks[ch]) {
+ var result = hooks[ch](stream, state);
+ if (result !== false) return result;
+ }
+ if (ch == '"' || ch == "'") {
+ state.tokenize = tokenString(ch);
+ return state.tokenize(stream, state);
+ }
+ if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+ curPunc = ch;
+ return null;
+ }
+ if (/\d/.test(ch)) {
+ stream.eatWhile(/[\w\.]/);
+ return "number";
+ }
+ if (ch == "/") {
+ if (stream.eat("*")) {
+ state.tokenize = tokenComment;
+ return tokenComment(stream, state);
+ }
+ if (stream.eat("/")) {
+ stream.skipToEnd();
+ return "comment";
+ }
+ }
+ if (isOperatorChar.test(ch)) {
+ stream.eatWhile(isOperatorChar);
+ return "operator";
+ }
+ stream.eatWhile(/[\w\$_]/);
+ var cur = stream.current();
+ if (keywords.propertyIsEnumerable(cur)) {
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+ return "keyword";
+ }
+ if (builtin.propertyIsEnumerable(cur)) {
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+ return "builtin";
+ }
+ if (atoms.propertyIsEnumerable(cur)) return "atom";
+ return "variable";
+ }
+
+ function tokenString(quote) {
+ return function(stream, state) {
+ var escaped = false, next, end = false;
+ while ((next = stream.next()) != null) {
+ if (next == quote && !escaped) {end = true; break;}
+ escaped = !escaped && next == "\\";
+ }
+ if (end || !(escaped || multiLineStrings))
+ state.tokenize = null;
+ return "string";
+ };
+ }
+
+ function tokenComment(stream, state) {
+ var maybeEnd = false, ch;
+ while (ch = stream.next()) {
+ if (ch == "/" && maybeEnd) {
+ state.tokenize = null;
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return "comment";
+ }
+
+ function Context(indented, column, type, align, prev) {
+ this.indented = indented;
+ this.column = column;
+ this.type = type;
+ this.align = align;
+ this.prev = prev;
+ }
+ function pushContext(state, col, type) {
+ var indent = state.indented;
+ if (state.context && state.context.type == "statement")
+ indent = state.context.indented;
+ return state.context = new Context(indent, col, type, null, state.context);
+ }
+ function popContext(state) {
+ var t = state.context.type;
+ if (t == ")" || t == "]" || t == "}")
+ state.indented = state.context.indented;
+ return state.context = state.context.prev;
+ }
+
+ // Interface
+
+ return {
+ startState: function(basecolumn) {
+ return {
+ tokenize: null,
+ context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
+ indented: 0,
+ startOfLine: true
+ };
+ },
+
+ token: function(stream, state) {
+ var ctx = state.context;
+ if (stream.sol()) {
+ if (ctx.align == null) ctx.align = false;
+ state.indented = stream.indentation();
+ state.startOfLine = true;
+ }
+ if (stream.eatSpace()) return null;
+ curPunc = null;
+ var style = (state.tokenize || tokenBase)(stream, state);
+ if (style == "comment" || style == "meta") return style;
+ if (ctx.align == null) ctx.align = true;
+
+ if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
+ else if (curPunc == "}") {
+ while (ctx.type == "statement") ctx = popContext(state);
+ if (ctx.type == "}") ctx = popContext(state);
+ while (ctx.type == "statement") ctx = popContext(state);
+ }
+ else if (curPunc == ctx.type) popContext(state);
+ else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
+ pushContext(state, stream.column(), "statement");
+ state.startOfLine = false;
+ return style;
+ },
+
+ indent: function(state, textAfter) {
+ if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
+ var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
+ if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
+ var closing = firstChar == ctx.type;
+ if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
+ else if (ctx.align) return ctx.column + (closing ? 0 : 1);
+ else return ctx.indented + (closing ? 0 : indentUnit);
+ },
+
+ electricChars: "{}"
+ };
+});
+
+(function() {
+ function words(str) {
+ var obj = {}, words = str.split(" ");
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+ return obj;
+ }
+ var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
+ "double static else struct entry switch extern typedef float union for unsigned " +
+ "goto while enum void const signed volatile";
+
+ function cppHook(stream, state) {
+ if (!state.startOfLine) return false;
+ for (;;) {
+ if (stream.skipTo("\\")) {
+ stream.next();
+ if (stream.eol()) {
+ state.tokenize = cppHook;
+ break;
+ }
+ } else {
+ stream.skipToEnd();
+ state.tokenize = null;
+ break;
+ }
+ }
+ return "meta";
+ }
+
+ // C#-style strings where "" escapes a quote.
+ function tokenAtString(stream, state) {
+ var next;
+ while ((next = stream.next()) != null) {
+ if (next == '"' && !stream.eat('"')) {
+ state.tokenize = null;
+ break;
+ }
+ }
+ return "string";
+ }
+
+ function mimes(ms, mode) {
+ for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
+ }
+
+ mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
+ name: "clike",
+ keywords: words(cKeywords),
+ blockKeywords: words("case do else for if switch while struct"),
+ atoms: words("null"),
+ hooks: {"#": cppHook}
+ });
+ mimes(["text/x-c++src", "text/x-c++hdr"], {
+ name: "clike",
+ keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
+ "static_cast typeid catch operator template typename class friend private " +
+ "this using const_cast inline public throw virtual delete mutable protected " +
+ "wchar_t"),
+ blockKeywords: words("catch class do else finally for if struct switch try while"),
+ atoms: words("true false null"),
+ hooks: {"#": cppHook}
+ });
+ CodeMirror.defineMIME("text/x-java", {
+ name: "clike",
+ keywords: words("abstract assert boolean break byte case catch char class const continue default " +
+ "do double else enum extends final finally float for goto if implements import " +
+ "instanceof int interface long native new package private protected public " +
+ "return short static strictfp super switch synchronized this throw throws transient " +
+ "try void volatile while"),
+ blockKeywords: words("catch class do else finally for if switch try while"),
+ atoms: words("true false null"),
+ hooks: {
+ "@": function(stream) {
+ stream.eatWhile(/[\w\$_]/);
+ return "meta";
+ }
+ }
+ });
+ CodeMirror.defineMIME("text/x-csharp", {
+ name: "clike",
+ keywords: words("abstract as base break case catch checked class const continue" +
+ " default delegate do else enum event explicit extern finally fixed for" +
+ " foreach goto if implicit in interface internal is lock namespace new" +
+ " operator out override params private protected public readonly ref return sealed" +
+ " sizeof stackalloc static struct switch this throw try typeof unchecked" +
+ " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
+ " global group into join let orderby partial remove select set value var yield"),
+ blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
+ builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
+ " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
+ " UInt64 bool byte char decimal double short int long object" +
+ " sbyte float string ushort uint ulong"),
+ atoms: words("true false null"),
+ hooks: {
+ "@": function(stream, state) {
+ if (stream.eat('"')) {
+ state.tokenize = tokenAtString;
+ return tokenAtString(stream, state);
+ }
+ stream.eatWhile(/[\w\$_]/);
+ return "meta";
+ }
+ }
+ });
+ CodeMirror.defineMIME("text/x-scala", {
+ name: "clike",
+ keywords: words(
+
+ /* scala */
+ "abstract case catch class def do else extends false final finally for forSome if " +
+ "implicit import lazy match new null object override package private protected return " +
+ "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
+ "<% >: # @ " +
+
+ /* package scala */
+ "assert assume require print println printf readLine readBoolean readByte readShort " +
+ "readChar readInt readLong readFloat readDouble " +
+
+ "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
+ "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
+ "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
+ "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
+ "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
+
+ /* package java.lang */
+ "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
+ "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
+ "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
+ "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
+
+
+ ),
+ blockKeywords: words("catch class do else finally for forSome if match switch try while"),
+ atoms: words("true false null"),
+ hooks: {
+ "@": function(stream) {
+ stream.eatWhile(/[\w\$_]/);
+ return "meta";
+ }
+ }
+ });
+}());
diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,324 @@
+CodeMirror.defineMode("xml", function(config, parserConfig) {
+ var indentUnit = config.indentUnit;
+ var Kludges = parserConfig.htmlMode ? {
+ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
+ 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
+ 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
+ 'track': true, 'wbr': true},
+ implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
+ 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
+ 'th': true, 'tr': true},
+ contextGrabbers: {
+ 'dd': {'dd': true, 'dt': true},
+ 'dt': {'dd': true, 'dt': true},
+ 'li': {'li': true},
+ 'option': {'option': true, 'optgroup': true},
+ 'optgroup': {'optgroup': true},
+ 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
+ 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
+ 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
+ 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
+ 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
+ 'rp': {'rp': true, 'rt': true},
+ 'rt': {'rp': true, 'rt': true},
+ 'tbody': {'tbody': true, 'tfoot': true},
+ 'td': {'td': true, 'th': true},
+ 'tfoot': {'tbody': true},
+ 'th': {'td': true, 'th': true},
+ 'thead': {'tbody': true, 'tfoot': true},
+ 'tr': {'tr': true}
+ },
+ doNotIndent: {"pre": true},
+ allowUnquoted: true,
+ allowMissing: true
+ } : {
+ autoSelfClosers: {},
+ implicitlyClosed: {},
+ contextGrabbers: {},
+ doNotIndent: {},
+ allowUnquoted: false,
+ allowMissing: false
+ };
+ var alignCDATA = parserConfig.alignCDATA;
+
+ // Return variables for tokenizers
+ var tagName, type;
+
+ function inText(stream, state) {
+ function chain(parser) {
+ state.tokenize = parser;
+ return parser(stream, state);
+ }
+
+ var ch = stream.next();
+ if (ch == "<") {
+ if (stream.eat("!")) {
+ if (stream.eat("[")) {
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
+ else return null;
+ }
+ else if (stream.match("--")) return chain(inBlock("comment", "-->"));
+ else if (stream.match("DOCTYPE", true, true)) {
+ stream.eatWhile(/[\w\._\-]/);
+ return chain(doctype(1));
+ }
+ else return null;
+ }
+ else if (stream.eat("?")) {
+ stream.eatWhile(/[\w\._\-]/);
+ state.tokenize = inBlock("meta", "?>");
+ return "meta";
+ }
+ else {
+ var isClose = stream.eat("/");
+ tagName = "";
+ var c;
+ while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
+ if (!tagName) return "error";
+ type = isClose ? "closeTag" : "openTag";
+ state.tokenize = inTag;
+ return "tag";
+ }
+ }
+ else if (ch == "&") {
+ var ok;
+ if (stream.eat("#")) {
+ if (stream.eat("x")) {
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
+ } else {
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
+ }
+ } else {
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
+ }
+ return ok ? "atom" : "error";
+ }
+ else {
+ stream.eatWhile(/[^&<]/);
+ return null;
+ }
+ }
+
+ function inTag(stream, state) {
+ var ch = stream.next();
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
+ state.tokenize = inText;
+ type = ch == ">" ? "endTag" : "selfcloseTag";
+ return "tag";
+ }
+ else if (ch == "=") {
+ type = "equals";
+ return null;
+ }
+ else if (/[\'\"]/.test(ch)) {
+ state.tokenize = inAttribute(ch);
+ return state.tokenize(stream, state);
+ }
+ else {
+ stream.eatWhile(/[^\s\u00a0=<>\"\']/);
+ return "word";
+ }
+ }
+
+ function inAttribute(quote) {
+ return function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.next() == quote) {
+ state.tokenize = inTag;
+ break;
+ }
+ }
+ return "string";
+ };
+ }
+
+ function inBlock(style, terminator) {
+ return function(stream, state) {
+ while (!stream.eol()) {
+ if (stream.match(terminator)) {
+ state.tokenize = inText;
+ break;
+ }
+ stream.next();
+ }
+ return style;
+ };
+ }
+ function doctype(depth) {
+ return function(stream, state) {
+ var ch;
+ while ((ch = stream.next()) != null) {
+ if (ch == "<") {
+ state.tokenize = doctype(depth + 1);
+ return state.tokenize(stream, state);
+ } else if (ch == ">") {
+ if (depth == 1) {
+ state.tokenize = inText;
+ break;
+ } else {
+ state.tokenize = doctype(depth - 1);
+ return state.tokenize(stream, state);
+ }
+ }
+ }
+ return "meta";
+ };
+ }
+
+ var curState, setStyle;
+ function pass() {
+ for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
+ }
+ function cont() {
+ pass.apply(null, arguments);
+ return true;
+ }
+
+ function pushContext(tagName, startOfLine) {
+ var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
+ curState.context = {
+ prev: curState.context,
+ tagName: tagName,
+ indent: curState.indented,
+ startOfLine: startOfLine,
+ noIndent: noIndent
+ };
+ }
+ function popContext() {
+ if (curState.context) curState.context = curState.context.prev;
+ }
+
+ function element(type) {
+ if (type == "openTag") {
+ curState.tagName = tagName;
+ return cont(attributes, endtag(curState.startOfLine));
+ } else if (type == "closeTag") {
+ var err = false;
+ if (curState.context) {
+ if (curState.context.tagName != tagName) {
+ if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
+ popContext();
+ }
+ err = !curState.context || curState.context.tagName != tagName;
+ }
+ } else {
+ err = true;
+ }
+ if (err) setStyle = "error";
+ return cont(endclosetag(err));
+ }
+ return cont();
+ }
+ function endtag(startOfLine) {
+ return function(type) {
+ var tagName = curState.tagName;
+ curState.tagName = null;
+ if (type == "selfcloseTag" ||
+ (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
+ maybePopContext(tagName.toLowerCase());
+ return cont();
+ }
+ if (type == "endTag") {
+ maybePopContext(tagName.toLowerCase());
+ pushContext(tagName, startOfLine);
+ return cont();
+ }
+ return cont();
+ };
+ }
+ function endclosetag(err) {
+ return function(type) {
+ if (err) setStyle = "error";
+ if (type == "endTag") { popContext(); return cont(); }
+ setStyle = "error";
+ return cont(arguments.callee);
+ };
+ }
+ function maybePopContext(nextTagName) {
+ var parentTagName;
+ while (true) {
+ if (!curState.context) {
+ return;
+ }
+ parentTagName = curState.context.tagName.toLowerCase();
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
+ !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
+ return;
+ }
+ popContext();
+ }
+ }
+
+ function attributes(type) {
+ if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
+ if (type == "endTag" || type == "selfcloseTag") return pass();
+ setStyle = "error";
+ return cont(attributes);
+ }
+ function attribute(type) {
+ if (type == "equals") return cont(attvalue, attributes);
+ if (!Kludges.allowMissing) setStyle = "error";
+ else if (type == "word") setStyle = "attribute";
+ return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
+ }
+ function attvalue(type) {
+ if (type == "string") return cont(attvaluemaybe);
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
+ setStyle = "error";
+ return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
+ }
+ function attvaluemaybe(type) {
+ if (type == "string") return cont(attvaluemaybe);
+ else return pass();
+ }
+
+ return {
+ startState: function() {
+ return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
+ },
+
+ token: function(stream, state) {
+ if (stream.sol()) {
+ state.startOfLine = true;
+ state.indented = stream.indentation();
+ }
+ if (stream.eatSpace()) return null;
+
+ setStyle = type = tagName = null;
+ var style = state.tokenize(stream, state);
+ state.type = type;
+ if ((style || type) && style != "comment") {
+ curState = state;
+ while (true) {
+ var comb = state.cc.pop() || element;
+ if (comb(type || style)) break;
+ }
+ }
+ state.startOfLine = false;
+ return setStyle || style;
+ },
+
+ indent: function(state, textAfter, fullLine) {
+ var context = state.context;
+ if ((state.tokenize != inTag && state.tokenize != inText) ||
+ context && context.noIndent)
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
+ if (alignCDATA && /
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.dew;
+
+import java.io.IOException;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class CompileTest {
+ @Test public void testCompile() throws IOException {
+ String html = ""
+ + " "
+ + "";
+ String java = "package x.y.z;"
+ + "import org.apidesign.bck2brwsr.htmlpage.api.*;"
+ + "import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;"
+ + "@Page(xhtml=\"index.html\", className=\"Index\")"
+ + "class X { "
+ + " @On(event=CLICK, id=\"btn\") static void clcs() {}"
+ + "}";
+ Compile result = Compile.create(html, java);
+
+ assertNotNull(result.get("x/y/z/X.class"), "Class X is compiled: " + result);
+ assertNotNull(result.get("x/y/z/Index.class"), "Class Index is compiled: " + result);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/pom.xml
--- a/emul/pom.xml Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -5,11 +5,11 @@
org.apidesignbck2brwsr
- 1.0-SNAPSHOT
+ 0.3-SNAPSHOTorg.apidesign.bck2brwsremul
- 1.0-SNAPSHOT
+ 0.3-SNAPSHOTJava API Emulationhttp://maven.apache.org
@@ -17,15 +17,9 @@
- junit
- junit
- 3.8.1
- test
-
- org.apidesign.bck2brwsrcore
- 1.0-SNAPSHOT
+ 0.3-SNAPSHOTjar
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/ByteArrayInputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/ByteArrayInputStream.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * A ByteArrayInputStream contains
+ * an internal buffer that contains bytes that
+ * may be read from the stream. An internal
+ * counter keeps track of the next byte to
+ * be supplied by the read method.
+ *
+ * Closing a ByteArrayInputStream has no effect. The methods in
+ * this class can be called after the stream has been closed without
+ * generating an IOException.
+ *
+ * @author Arthur van Hoff
+ * @see java.io.StringBufferInputStream
+ * @since JDK1.0
+ */
+public
+class ByteArrayInputStream extends InputStream {
+
+ /**
+ * An array of bytes that was provided
+ * by the creator of the stream. Elements buf[0]
+ * through buf[count-1] are the
+ * only bytes that can ever be read from the
+ * stream; element buf[pos] is
+ * the next byte to be read.
+ */
+ protected byte buf[];
+
+ /**
+ * The index of the next character to read from the input stream buffer.
+ * This value should always be nonnegative
+ * and not larger than the value of count.
+ * The next byte to be read from the input stream buffer
+ * will be buf[pos].
+ */
+ protected int pos;
+
+ /**
+ * The currently marked position in the stream.
+ * ByteArrayInputStream objects are marked at position zero by
+ * default when constructed. They may be marked at another
+ * position within the buffer by the mark() method.
+ * The current buffer position is set to this point by the
+ * reset() method.
+ *
+ * If no mark has been set, then the value of mark is the offset
+ * passed to the constructor (or 0 if the offset was not supplied).
+ *
+ * @since JDK1.1
+ */
+ protected int mark = 0;
+
+ /**
+ * The index one greater than the last valid character in the input
+ * stream buffer.
+ * This value should always be nonnegative
+ * and not larger than the length of buf.
+ * It is one greater than the position of
+ * the last byte within buf that
+ * can ever be read from the input stream buffer.
+ */
+ protected int count;
+
+ /**
+ * Creates a ByteArrayInputStream
+ * so that it uses buf as its
+ * buffer array.
+ * The buffer array is not copied.
+ * The initial value of pos
+ * is 0 and the initial value
+ * of count is the length of
+ * buf.
+ *
+ * @param buf the input buffer.
+ */
+ public ByteArrayInputStream(byte buf[]) {
+ this.buf = buf;
+ this.pos = 0;
+ this.count = buf.length;
+ }
+
+ /**
+ * Creates ByteArrayInputStream
+ * that uses buf as its
+ * buffer array. The initial value of pos
+ * is offset and the initial value
+ * of count is the minimum of offset+length
+ * and buf.length.
+ * The buffer array is not copied. The buffer's mark is
+ * set to the specified offset.
+ *
+ * @param buf the input buffer.
+ * @param offset the offset in the buffer of the first byte to read.
+ * @param length the maximum number of bytes to read from the buffer.
+ */
+ public ByteArrayInputStream(byte buf[], int offset, int length) {
+ this.buf = buf;
+ this.pos = offset;
+ this.count = Math.min(offset + length, buf.length);
+ this.mark = offset;
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an int in the range
+ * 0 to 255. If no byte is available
+ * because the end of the stream has been reached, the value
+ * -1 is returned.
+ *
+ * This read method
+ * cannot block.
+ *
+ * @return the next byte of data, or -1 if the end of the
+ * stream has been reached.
+ */
+ public synchronized int read() {
+ return (pos < count) ? (buf[pos++] & 0xff) : -1;
+ }
+
+ /**
+ * Reads up to len bytes of data into an array of bytes
+ * from this input stream.
+ * If pos equals count,
+ * then -1 is returned to indicate
+ * end of file. Otherwise, the number k
+ * of bytes read is equal to the smaller of
+ * len and count-pos.
+ * If k is positive, then bytes
+ * buf[pos] through buf[pos+k-1]
+ * are copied into b[off] through
+ * b[off+k-1] in the manner performed
+ * by System.arraycopy. The
+ * value k is added into pos
+ * and k is returned.
+ *
+ * This read method cannot block.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception NullPointerException If b is null.
+ * @exception IndexOutOfBoundsException If off is negative,
+ * len is negative, or len is greater than
+ * b.length - off
+ */
+ public synchronized int read(byte b[], int off, int len) {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (pos >= count) {
+ return -1;
+ }
+
+ int avail = count - pos;
+ if (len > avail) {
+ len = avail;
+ }
+ if (len <= 0) {
+ return 0;
+ }
+ PushbackInputStream.arraycopy(buf, pos, b, off, len);
+ pos += len;
+ return len;
+ }
+
+ /**
+ * Skips n bytes of input from this input stream. Fewer
+ * bytes might be skipped if the end of the input stream is reached.
+ * The actual number k
+ * of bytes to be skipped is equal to the smaller
+ * of n and count-pos.
+ * The value k is added into pos
+ * and k is returned.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ */
+ public synchronized long skip(long n) {
+ long k = count - pos;
+ if (n < k) {
+ k = n < 0 ? 0 : n;
+ }
+
+ pos += k;
+ return k;
+ }
+
+ /**
+ * Returns the number of remaining bytes that can be read (or skipped over)
+ * from this input stream.
+ *
+ * The value returned is count - pos,
+ * which is the number of bytes remaining to be read from the input buffer.
+ *
+ * @return the number of remaining bytes that can be read (or skipped
+ * over) from this input stream without blocking.
+ */
+ public synchronized int available() {
+ return count - pos;
+ }
+
+ /**
+ * Tests if this InputStream supports mark/reset. The
+ * markSupported method of ByteArrayInputStream
+ * always returns true.
+ *
+ * @since JDK1.1
+ */
+ public boolean markSupported() {
+ return true;
+ }
+
+ /**
+ * Set the current marked position in the stream.
+ * ByteArrayInputStream objects are marked at position zero by
+ * default when constructed. They may be marked at another
+ * position within the buffer by this method.
+ *
+ * If no mark has been set, then the value of the mark is the
+ * offset passed to the constructor (or 0 if the offset was not
+ * supplied).
+ *
+ *
Note: The readAheadLimit for this class
+ * has no meaning.
+ *
+ * @since JDK1.1
+ */
+ public void mark(int readAheadLimit) {
+ mark = pos;
+ }
+
+ /**
+ * Resets the buffer to the marked position. The marked position
+ * is 0 unless another position was marked or an offset was specified
+ * in the constructor.
+ */
+ public synchronized void reset() {
+ pos = mark;
+ }
+
+ /**
+ * Closing a ByteArrayInputStream has no effect. The methods in
+ * this class can be called after the stream has been closed without
+ * generating an IOException.
+ *
+ */
+ public void close() throws IOException {
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/Closeable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/Closeable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+import java.io.IOException;
+
+/**
+ * A {@code Closeable} is a source or destination of data that can be closed.
+ * The close method is invoked to release resources that the object is
+ * holding (such as open files).
+ *
+ * @since 1.5
+ */
+
+public interface Closeable extends AutoCloseable {
+
+ /**
+ * Closes this stream and releases any system resources associated
+ * with it. If the stream is already closed then invoking this
+ * method has no effect.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException;
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/DataInput.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/DataInput.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * The DataInput interface provides
+ * for reading bytes from a binary stream and
+ * reconstructing from them data in any of
+ * the Java primitive types. There is also
+ * a
+ * facility for reconstructing a String
+ * from data in
+ * modified UTF-8
+ * format.
+ *
+ * It is generally true of all the reading
+ * routines in this interface that if end of
+ * file is reached before the desired number
+ * of bytes has been read, an EOFException
+ * (which is a kind of IOException)
+ * is thrown. If any byte cannot be read for
+ * any reason other than end of file, an IOException
+ * other than EOFException is
+ * thrown. In particular, an IOException
+ * may be thrown if the input stream has been
+ * closed.
+ *
+ *
+ * Implementations of the DataInput and DataOutput interfaces represent
+ * Unicode strings in a format that is a slight modification of UTF-8.
+ * (For information regarding the standard UTF-8 format, see section
+ * 3.9 Unicode Encoding Forms of The Unicode Standard, Version
+ * 4.0).
+ * Note that in the following tables, the most significant bit appears in the
+ * far left-hand column.
+ *
+ * All characters in the range '\u0001' to
+ * '\u007F' are represented by a single byte:
+ *
+ *
+ *
+ *
+ *
+ *
Bit Values
+ *
+ *
+ *
Byte 1
+ *
+ *
+ *
+ *
0
+ *
bits 6-0
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * The null character '\u0000' and characters in the
+ * range '\u0080' to '\u07FF' are
+ * represented by a pair of bytes:
+ *
+ *
+ *
+ *
+ *
+ *
Bit Values
+ *
+ *
+ *
Byte 1
+ *
+ *
+ *
+ *
1
+ *
1
+ *
0
+ *
bits 10-6
+ *
+ *
+ *
+ *
+ *
+ *
Byte 2
+ *
+ *
+ *
+ *
1
+ *
0
+ *
bits 5-0
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * char values in the range '\u0800' to
+ * '\uFFFF' are represented by three bytes:
+ *
+ *
+ *
+ *
+ *
+ *
Bit Values
+ *
+ *
+ *
Byte 1
+ *
+ *
+ *
+ *
1
+ *
1
+ *
1
+ *
0
+ *
bits 15-12
+ *
+ *
+ *
+ *
+ *
+ *
Byte 2
+ *
+ *
+ *
+ *
1
+ *
0
+ *
bits 11-6
+ *
+ *
+ *
+ *
+ *
+ *
Byte 3
+ *
+ *
+ *
+ *
1
+ *
0
+ *
bits 5-0
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * The differences between this format and the
+ * standard UTF-8 format are the following:
+ *
+ *
The null byte '\u0000' is encoded in 2-byte format
+ * rather than 1-byte, so that the encoded strings never have
+ * embedded nulls.
+ *
Only the 1-byte, 2-byte, and 3-byte formats are used.
+ *
+ * @author Frank Yellin
+ * @see java.io.DataInputStream
+ * @see java.io.DataOutput
+ * @since JDK1.0
+ */
+public
+interface DataInput {
+ /**
+ * Reads some bytes from an input
+ * stream and stores them into the buffer
+ * array b. The number of bytes
+ * read is equal
+ * to the length of b.
+ *
+ * This method blocks until one of the
+ * following conditions occurs:
+ *
+ *
b.length
+ * bytes of input data are available, in which
+ * case a normal return is made.
+ *
+ *
End of
+ * file is detected, in which case an EOFException
+ * is thrown.
+ *
+ *
An I/O error occurs, in
+ * which case an IOException other
+ * than EOFException is thrown.
+ *
+ *
+ * If b is null,
+ * a NullPointerException is thrown.
+ * If b.length is zero, then
+ * no bytes are read. Otherwise, the first
+ * byte read is stored into element b[0],
+ * the next one into b[1], and
+ * so on.
+ * If an exception is thrown from
+ * this method, then it may be that some but
+ * not all bytes of b have been
+ * updated with data from the input stream.
+ *
+ * @param b the buffer into which the data is read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ void readFully(byte b[]) throws IOException;
+
+ /**
+ *
+ * Reads len
+ * bytes from
+ * an input stream.
+ *
+ * This method
+ * blocks until one of the following conditions
+ * occurs:
+ *
+ *
len bytes
+ * of input data are available, in which case
+ * a normal return is made.
+ *
+ *
End of file
+ * is detected, in which case an EOFException
+ * is thrown.
+ *
+ *
An I/O error occurs, in
+ * which case an IOException other
+ * than EOFException is thrown.
+ *
+ *
+ * If b is null,
+ * a NullPointerException is thrown.
+ * If off is negative, or len
+ * is negative, or off+len is
+ * greater than the length of the array b,
+ * then an IndexOutOfBoundsException
+ * is thrown.
+ * If len is zero,
+ * then no bytes are read. Otherwise, the first
+ * byte read is stored into element b[off],
+ * the next one into b[off+1],
+ * and so on. The number of bytes read is,
+ * at most, equal to len.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off an int specifying the offset into the data.
+ * @param len an int specifying the number of bytes to read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ void readFully(byte b[], int off, int len) throws IOException;
+
+ /**
+ * Makes an attempt to skip over
+ * n bytes
+ * of data from the input
+ * stream, discarding the skipped bytes. However,
+ * it may skip
+ * over some smaller number of
+ * bytes, possibly zero. This may result from
+ * any of a
+ * number of conditions; reaching
+ * end of file before n bytes
+ * have been skipped is
+ * only one possibility.
+ * This method never throws an EOFException.
+ * The actual
+ * number of bytes skipped is returned.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the number of bytes actually skipped.
+ * @exception IOException if an I/O error occurs.
+ */
+ int skipBytes(int n) throws IOException;
+
+ /**
+ * Reads one input byte and returns
+ * true if that byte is nonzero,
+ * false if that byte is zero.
+ * This method is suitable for reading
+ * the byte written by the writeBoolean
+ * method of interface DataOutput.
+ *
+ * @return the boolean value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ boolean readBoolean() throws IOException;
+
+ /**
+ * Reads and returns one input byte.
+ * The byte is treated as a signed value in
+ * the range -128 through 127,
+ * inclusive.
+ * This method is suitable for
+ * reading the byte written by the writeByte
+ * method of interface DataOutput.
+ *
+ * @return the 8-bit value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ byte readByte() throws IOException;
+
+ /**
+ * Reads one input byte, zero-extends
+ * it to type int, and returns
+ * the result, which is therefore in the range
+ * 0
+ * through 255.
+ * This method is suitable for reading
+ * the byte written by the writeByte
+ * method of interface DataOutput
+ * if the argument to writeByte
+ * was intended to be a value in the range
+ * 0 through 255.
+ *
+ * @return the unsigned 8-bit value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ int readUnsignedByte() throws IOException;
+
+ /**
+ * Reads two input bytes and returns
+ * a short value. Let a
+ * be the first byte read and b
+ * be the second byte. The value
+ * returned
+ * is:
+ *
(short)((a << 8) | (b & 0xff))
+ *
+ * This method
+ * is suitable for reading the bytes written
+ * by the writeShort method of
+ * interface DataOutput.
+ *
+ * @return the 16-bit value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ short readShort() throws IOException;
+
+ /**
+ * Reads two input bytes and returns
+ * an int value in the range 0
+ * through 65535. Let a
+ * be the first byte read and
+ * b
+ * be the second byte. The value returned is:
+ *
(((a & 0xff) << 8) | (b & 0xff))
+ *
+ * This method is suitable for reading the bytes
+ * written by the writeShort method
+ * of interface DataOutput if
+ * the argument to writeShort
+ * was intended to be a value in the range
+ * 0 through 65535.
+ *
+ * @return the unsigned 16-bit value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ int readUnsignedShort() throws IOException;
+
+ /**
+ * Reads two input bytes and returns a char value.
+ * Let a
+ * be the first byte read and b
+ * be the second byte. The value
+ * returned is:
+ *
(char)((a << 8) | (b & 0xff))
+ *
+ * This method
+ * is suitable for reading bytes written by
+ * the writeChar method of interface
+ * DataOutput.
+ *
+ * @return the char value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ char readChar() throws IOException;
+
+ /**
+ * Reads four input bytes and returns an
+ * int value. Let a-d
+ * be the first through fourth bytes read. The value returned is:
+ *
+ * This method is suitable
+ * for reading bytes written by the writeInt
+ * method of interface DataOutput.
+ *
+ * @return the int value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ int readInt() throws IOException;
+
+ /**
+ * Reads eight input bytes and returns
+ * a long value. Let a-h
+ * be the first through eighth bytes read.
+ * The value returned is:
+ *
+ * This method is suitable
+ * for reading bytes written by the writeLong
+ * method of interface DataOutput.
+ *
+ * @return the long value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ long readLong() throws IOException;
+
+ /**
+ * Reads four input bytes and returns
+ * a float value. It does this
+ * by first constructing an int
+ * value in exactly the manner
+ * of the readInt
+ * method, then converting this int
+ * value to a float in
+ * exactly the manner of the method Float.intBitsToFloat.
+ * This method is suitable for reading
+ * bytes written by the writeFloat
+ * method of interface DataOutput.
+ *
+ * @return the float value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ float readFloat() throws IOException;
+
+ /**
+ * Reads eight input bytes and returns
+ * a double value. It does this
+ * by first constructing a long
+ * value in exactly the manner
+ * of the readlong
+ * method, then converting this long
+ * value to a double in exactly
+ * the manner of the method Double.longBitsToDouble.
+ * This method is suitable for reading
+ * bytes written by the writeDouble
+ * method of interface DataOutput.
+ *
+ * @return the double value read.
+ * @exception EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ double readDouble() throws IOException;
+
+ /**
+ * Reads the next line of text from the input stream.
+ * It reads successive bytes, converting
+ * each byte separately into a character,
+ * until it encounters a line terminator or
+ * end of
+ * file; the characters read are then
+ * returned as a String. Note
+ * that because this
+ * method processes bytes,
+ * it does not support input of the full Unicode
+ * character set.
+ *
+ * If end of file is encountered
+ * before even one byte can be read, then null
+ * is returned. Otherwise, each byte that is
+ * read is converted to type char
+ * by zero-extension. If the character '\n'
+ * is encountered, it is discarded and reading
+ * ceases. If the character '\r'
+ * is encountered, it is discarded and, if
+ * the following byte converts to the
+ * character '\n', then that is
+ * discarded also; reading then ceases. If
+ * end of file is encountered before either
+ * of the characters '\n' and
+ * '\r' is encountered, reading
+ * ceases. Once reading has ceased, a String
+ * is returned that contains all the characters
+ * read and not discarded, taken in order.
+ * Note that every character in this string
+ * will have a value less than \u0100,
+ * that is, (char)256.
+ *
+ * @return the next line of text from the input stream,
+ * or null if the end of file is
+ * encountered before a byte can be read.
+ * @exception IOException if an I/O error occurs.
+ */
+ String readLine() throws IOException;
+
+ /**
+ * Reads in a string that has been encoded using a
+ * modified UTF-8
+ * format.
+ * The general contract of readUTF
+ * is that it reads a representation of a Unicode
+ * character string encoded in modified
+ * UTF-8 format; this string of characters
+ * is then returned as a String.
+ *
+ * First, two bytes are read and used to
+ * construct an unsigned 16-bit integer in
+ * exactly the manner of the readUnsignedShort
+ * method . This integer value is called the
+ * UTF length and specifies the number
+ * of additional bytes to be read. These bytes
+ * are then converted to characters by considering
+ * them in groups. The length of each group
+ * is computed from the value of the first
+ * byte of the group. The byte following a
+ * group, if any, is the first byte of the
+ * next group.
+ *
+ * If the first byte of a group
+ * matches the bit pattern 0xxxxxxx
+ * (where x means "may be 0
+ * or 1"), then the group consists
+ * of just that byte. The byte is zero-extended
+ * to form a character.
+ *
+ * If the first byte
+ * of a group matches the bit pattern 110xxxxx,
+ * then the group consists of that byte a
+ * and a second byte b. If there
+ * is no byte b (because byte
+ * a was the last of the bytes
+ * to be read), or if byte b does
+ * not match the bit pattern 10xxxxxx,
+ * then a UTFDataFormatException
+ * is thrown. Otherwise, the group is converted
+ * to the character:
+ *
(char)(((a& 0x1F) << 6) | (b & 0x3F))
+ *
+ * If the first byte of a group
+ * matches the bit pattern 1110xxxx,
+ * then the group consists of that byte a
+ * and two more bytes b and c.
+ * If there is no byte c (because
+ * byte a was one of the last
+ * two of the bytes to be read), or either
+ * byte b or byte c
+ * does not match the bit pattern 10xxxxxx,
+ * then a UTFDataFormatException
+ * is thrown. Otherwise, the group is converted
+ * to the character:
+ * If the first byte of a group matches the
+ * pattern 1111xxxx or the pattern
+ * 10xxxxxx, then a UTFDataFormatException
+ * is thrown.
+ *
+ * If end of file is encountered
+ * at any time during this entire process,
+ * then an EOFException is thrown.
+ *
+ * After every group has been converted to
+ * a character by this process, the characters
+ * are gathered, in the same order in which
+ * their corresponding groups were read from
+ * the input stream, to form a String,
+ * which is returned.
+ *
+ * The writeUTF
+ * method of interface DataOutput
+ * may be used to write data that is suitable
+ * for reading by this method.
+ * @return a Unicode string.
+ * @exception EOFException if this stream reaches the end
+ * before reading all the bytes.
+ * @exception IOException if an I/O error occurs.
+ * @exception UTFDataFormatException if the bytes do not represent a
+ * valid modified UTF-8 encoding of a string.
+ */
+ String readUTF() throws IOException;
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/DataInputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/DataInputStream.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ * A data input stream lets an application read primitive Java data
+ * types from an underlying input stream in a machine-independent
+ * way. An application uses a data output stream to write data that
+ * can later be read by a data input stream.
+ *
+ * DataInputStream is not necessarily safe for multithreaded access.
+ * Thread safety is optional and is the responsibility of users of
+ * methods in this class.
+ *
+ * @author Arthur van Hoff
+ * @see java.io.DataOutputStream
+ * @since JDK1.0
+ */
+public
+class DataInputStream extends FilterInputStream implements DataInput {
+
+ /**
+ * Creates a DataInputStream that uses the specified
+ * underlying InputStream.
+ *
+ * @param in the specified input stream
+ */
+ public DataInputStream(InputStream in) {
+ super(in);
+ }
+
+ /**
+ * working arrays initialized on demand by readUTF
+ */
+ private byte bytearr[] = new byte[80];
+ private char chararr[] = new char[80];
+
+ /**
+ * Reads some number of bytes from the contained input stream and
+ * stores them into the buffer array b. The number of
+ * bytes actually read is returned as an integer. This method blocks
+ * until input data is available, end of file is detected, or an
+ * exception is thrown.
+ *
+ *
If b is null, a NullPointerException is
+ * thrown. If the length of b is zero, then no bytes are
+ * read and 0 is returned; otherwise, there is an attempt
+ * to read at least one byte. If no byte is available because the
+ * stream is at end of file, the value -1 is returned;
+ * otherwise, at least one byte is read and stored into b.
+ *
+ *
The first byte read is stored into element b[0], the
+ * next one into b[1], and so on. The number of bytes read
+ * is, at most, equal to the length of b. Let k
+ * be the number of bytes actually read; these bytes will be stored in
+ * elements b[0] through b[k-1], leaving
+ * elements b[k] through b[b.length-1]
+ * unaffected.
+ *
+ *
The read(b) method has the same effect as:
+ *
+ * read(b, 0, b.length)
+ *
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end
+ * of the stream has been reached.
+ * @exception IOException if the first byte cannot be read for any reason
+ * other than end of file, the stream has been closed and the underlying
+ * input stream does not support reading after close, or another I/O
+ * error occurs.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ public final int read(byte b[]) throws IOException {
+ return in.read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to len bytes of data from the contained
+ * input stream into an array of bytes. An attempt is made to read
+ * as many as len bytes, but a smaller number may be read,
+ * possibly zero. The number of bytes actually read is returned as an
+ * integer.
+ *
+ *
This method blocks until input data is available, end of file is
+ * detected, or an exception is thrown.
+ *
+ *
If len is zero, then no bytes are read and
+ * 0 is returned; otherwise, there is an attempt to read at
+ * least one byte. If no byte is available because the stream is at end of
+ * file, the value -1 is returned; otherwise, at least one
+ * byte is read and stored into b.
+ *
+ *
The first byte read is stored into element b[off], the
+ * next one into b[off+1], and so on. The number of bytes read
+ * is, at most, equal to len. Let k be the number of
+ * bytes actually read; these bytes will be stored in elements
+ * b[off] through b[off+k-1],
+ * leaving elements b[off+k] through
+ * b[off+len-1] unaffected.
+ *
+ *
In every case, elements b[0] through
+ * b[off] and elements b[off+len] through
+ * b[b.length-1] are unaffected.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end
+ * of the stream has been reached.
+ * @exception NullPointerException If b is null.
+ * @exception IndexOutOfBoundsException If off is negative,
+ * len is negative, or len is greater than
+ * b.length - off
+ * @exception IOException if the first byte cannot be read for any reason
+ * other than end of file, the stream has been closed and the underlying
+ * input stream does not support reading after close, or another I/O
+ * error occurs.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ public final int read(byte b[], int off, int len) throws IOException {
+ return in.read(b, off, len);
+ }
+
+ /**
+ * See the general contract of the readFully
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @param b the buffer into which the data is read.
+ * @exception EOFException if this input stream reaches the end before
+ * reading all the bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final void readFully(byte b[]) throws IOException {
+ readFully(b, 0, b.length);
+ }
+
+ /**
+ * See the general contract of the readFully
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset of the data.
+ * @param len the number of bytes to read.
+ * @exception EOFException if this input stream reaches the end before
+ * reading all the bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final void readFully(byte b[], int off, int len) throws IOException {
+ if (len < 0)
+ throw new IndexOutOfBoundsException();
+ int n = 0;
+ while (n < len) {
+ int count = in.read(b, off + n, len - n);
+ if (count < 0)
+ throw new EOFException();
+ n += count;
+ }
+ }
+
+ /**
+ * See the general contract of the skipBytes
+ * method of DataInput.
+ *
+ * Bytes for this operation are read from the contained
+ * input stream.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception IOException if the contained input stream does not support
+ * seek, or the stream has been closed and
+ * the contained input stream does not support
+ * reading after close, or another I/O error occurs.
+ */
+ public final int skipBytes(int n) throws IOException {
+ int total = 0;
+ int cur = 0;
+
+ while ((total 0)) {
+ total += cur;
+ }
+
+ return total;
+ }
+
+ /**
+ * See the general contract of the readBoolean
+ * method of DataInput.
+ *
+ * Bytes for this operation are read from the contained
+ * input stream.
+ *
+ * @return the boolean value read.
+ * @exception EOFException if this input stream has reached the end.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final boolean readBoolean() throws IOException {
+ int ch = in.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (ch != 0);
+ }
+
+ /**
+ * See the general contract of the readByte
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next byte of this input stream as a signed 8-bit
+ * byte.
+ * @exception EOFException if this input stream has reached the end.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final byte readByte() throws IOException {
+ int ch = in.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (byte)(ch);
+ }
+
+ /**
+ * See the general contract of the readUnsignedByte
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next byte of this input stream, interpreted as an
+ * unsigned 8-bit number.
+ * @exception EOFException if this input stream has reached the end.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final int readUnsignedByte() throws IOException {
+ int ch = in.read();
+ if (ch < 0)
+ throw new EOFException();
+ return ch;
+ }
+
+ /**
+ * See the general contract of the readShort
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next two bytes of this input stream, interpreted as a
+ * signed 16-bit number.
+ * @exception EOFException if this input stream reaches the end before
+ * reading two bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final short readShort() throws IOException {
+ int ch1 = in.read();
+ int ch2 = in.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (short)((ch1 << 8) + (ch2 << 0));
+ }
+
+ /**
+ * See the general contract of the readUnsignedShort
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next two bytes of this input stream, interpreted as an
+ * unsigned 16-bit integer.
+ * @exception EOFException if this input stream reaches the end before
+ * reading two bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final int readUnsignedShort() throws IOException {
+ int ch1 = in.read();
+ int ch2 = in.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (ch1 << 8) + (ch2 << 0);
+ }
+
+ /**
+ * See the general contract of the readChar
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next two bytes of this input stream, interpreted as a
+ * char.
+ * @exception EOFException if this input stream reaches the end before
+ * reading two bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final char readChar() throws IOException {
+ int ch1 = in.read();
+ int ch2 = in.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (char)((ch1 << 8) + (ch2 << 0));
+ }
+
+ /**
+ * See the general contract of the readInt
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next four bytes of this input stream, interpreted as an
+ * int.
+ * @exception EOFException if this input stream reaches the end before
+ * reading four bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final int readInt() throws IOException {
+ int ch1 = in.read();
+ int ch2 = in.read();
+ int ch3 = in.read();
+ int ch4 = in.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+ }
+
+ private byte readBuffer[] = new byte[8];
+
+ /**
+ * See the general contract of the readLong
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next eight bytes of this input stream, interpreted as a
+ * long.
+ * @exception EOFException if this input stream reaches the end before
+ * reading eight bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public final long readLong() throws IOException {
+ readFully(readBuffer, 0, 8);
+ return (((long)readBuffer[0] << 56) +
+ ((long)(readBuffer[1] & 255) << 48) +
+ ((long)(readBuffer[2] & 255) << 40) +
+ ((long)(readBuffer[3] & 255) << 32) +
+ ((long)(readBuffer[4] & 255) << 24) +
+ ((readBuffer[5] & 255) << 16) +
+ ((readBuffer[6] & 255) << 8) +
+ ((readBuffer[7] & 255) << 0));
+ }
+
+ /**
+ * See the general contract of the readFloat
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next four bytes of this input stream, interpreted as a
+ * float.
+ * @exception EOFException if this input stream reaches the end before
+ * reading four bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.DataInputStream#readInt()
+ * @see java.lang.Float#intBitsToFloat(int)
+ */
+ public final float readFloat() throws IOException {
+ return Float.intBitsToFloat(readInt());
+ }
+
+ /**
+ * See the general contract of the readDouble
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return the next eight bytes of this input stream, interpreted as a
+ * double.
+ * @exception EOFException if this input stream reaches the end before
+ * reading eight bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.DataInputStream#readLong()
+ * @see java.lang.Double#longBitsToDouble(long)
+ */
+ public final double readDouble() throws IOException {
+ int hi = readInt();
+ int low = readInt();
+ return toDouble(hi, low);
+ }
+
+ @JavaScriptBody(args={ "hi", "low" },
+ body=
+ "if (low == 0) {\n"
+ + " if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n"
+ + " if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n"
+ + "}\n"
+ + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n"
+ + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n"
+ + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n"
+ + "var e = (hi >> 20) & 0x7ff;\n"
+ + "var to32 = low >> 0;\n"
+ + "if (e === 0) {\n"
+ + " if (to32 & 0x80000000) {\n"
+ + " hi = hi << 1 + 1; low = low << 1;\n"
+ + " } else {\n"
+ + " hi = hi << 1; low = low << 1;\n"
+ + " }\n"
+ + "} else {\n"
+ + " hi = (hi & 0xfffff) | 0x100000;\n"
+ + "}\n"
+ + "to32 = low >> 0;\n"
+ + "var m = Math.pow(2.0, 32) * hi + to32;\n"
+ + "var r = s * m * Math.pow(2.0, e - 1075);\n"
+ + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n"
+ + "return r;\n"
+ )
+ private static double toDouble(int hi, int low) {
+ long both = hi;
+ both = (both << 32) & low;
+ return Double.doubleToLongBits(both);
+ }
+
+ private char lineBuffer[];
+
+ /**
+ * See the general contract of the readLine
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @deprecated This method does not properly convert bytes to characters.
+ * As of JDK 1.1, the preferred way to read lines of text is via the
+ * BufferedReader.readLine() method. Programs that use the
+ * DataInputStream class to read lines can be converted to use
+ * the BufferedReader class by replacing code of the form:
+ *
+ * DataInputStream d = new DataInputStream(in);
+ *
+ * with:
+ *
+ * BufferedReader d
+ * = new BufferedReader(new InputStreamReader(in));
+ *
+ *
+ * @return the next line of text from this input stream.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.BufferedReader#readLine()
+ * @see java.io.FilterInputStream#in
+ */
+ @Deprecated
+ public final String readLine() throws IOException {
+ char buf[] = lineBuffer;
+
+ if (buf == null) {
+ buf = lineBuffer = new char[128];
+ }
+
+ int room = buf.length;
+ int offset = 0;
+ int c;
+
+loop: while (true) {
+ switch (c = in.read()) {
+ case -1:
+ case '\n':
+ break loop;
+
+ case '\r':
+ int c2 = in.read();
+ if ((c2 != '\n') && (c2 != -1)) {
+ if (!(in instanceof PushbackInputStream)) {
+ this.in = new PushbackInputStream(in);
+ }
+ ((PushbackInputStream)in).unread(c2);
+ }
+ break loop;
+
+ default:
+ if (--room < 0) {
+ buf = new char[offset + 128];
+ room = buf.length - offset - 1;
+ arraycopy(lineBuffer, 0, buf, 0, offset);
+ lineBuffer = buf;
+ }
+ buf[offset++] = (char) c;
+ break;
+ }
+ }
+ if ((c == -1) && (offset == 0)) {
+ return null;
+ }
+ return String.copyValueOf(buf, 0, offset);
+ }
+
+ /**
+ * See the general contract of the readUTF
+ * method of DataInput.
+ *
+ * Bytes
+ * for this operation are read from the contained
+ * input stream.
+ *
+ * @return a Unicode string.
+ * @exception EOFException if this input stream reaches the end before
+ * reading all the bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @exception UTFDataFormatException if the bytes do not represent a valid
+ * modified UTF-8 encoding of a string.
+ * @see java.io.DataInputStream#readUTF(java.io.DataInput)
+ */
+ public final String readUTF() throws IOException {
+ return readUTF(this);
+ }
+
+ /**
+ * Reads from the
+ * stream in a representation
+ * of a Unicode character string encoded in
+ * modified UTF-8 format;
+ * this string of characters is then returned as a String.
+ * The details of the modified UTF-8 representation
+ * are exactly the same as for the readUTF
+ * method of DataInput.
+ *
+ * @param in a data input stream.
+ * @return a Unicode string.
+ * @exception EOFException if the input stream reaches the end
+ * before all the bytes.
+ * @exception IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @exception UTFDataFormatException if the bytes do not represent a
+ * valid modified UTF-8 encoding of a Unicode string.
+ * @see java.io.DataInputStream#readUnsignedShort()
+ */
+ public final static String readUTF(DataInput in) throws IOException {
+ int utflen = in.readUnsignedShort();
+ byte[] bytearr = null;
+ char[] chararr = null;
+ if (in instanceof DataInputStream) {
+ DataInputStream dis = (DataInputStream)in;
+ if (dis.bytearr.length < utflen){
+ dis.bytearr = new byte[utflen*2];
+ dis.chararr = new char[utflen*2];
+ }
+ chararr = dis.chararr;
+ bytearr = dis.bytearr;
+ } else {
+ bytearr = new byte[utflen];
+ chararr = new char[utflen];
+ }
+
+ int c, char2, char3;
+ int count = 0;
+ int chararr_count=0;
+
+ in.readFully(bytearr, 0, utflen);
+
+ while (count < utflen) {
+ c = (int) bytearr[count] & 0xff;
+ if (c > 127) break;
+ count++;
+ chararr[chararr_count++]=(char)c;
+ }
+
+ while (count < utflen) {
+ c = (int) bytearr[count] & 0xff;
+ switch (c >> 4) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ /* 0xxxxxxx*/
+ count++;
+ chararr[chararr_count++]=(char)c;
+ break;
+ case 12: case 13:
+ /* 110x xxxx 10xx xxxx*/
+ count += 2;
+ if (count > utflen)
+ throw new UTFDataFormatException(
+ "malformed input: partial character at end");
+ char2 = (int) bytearr[count-1];
+ if ((char2 & 0xC0) != 0x80)
+ throw new UTFDataFormatException(
+ "malformed input around byte " + count);
+ chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
+ (char2 & 0x3F));
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ count += 3;
+ if (count > utflen)
+ throw new UTFDataFormatException(
+ "malformed input: partial character at end");
+ char2 = (int) bytearr[count-2];
+ char3 = (int) bytearr[count-1];
+ if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+ throw new UTFDataFormatException(
+ "malformed input around byte " + (count-1));
+ chararr[chararr_count++]=(char)(((c & 0x0F) << 12) |
+ ((char2 & 0x3F) << 6) |
+ ((char3 & 0x3F) << 0));
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw new UTFDataFormatException(
+ "malformed input around byte " + count);
+ }
+ }
+ // The number of chars produced may be less than utflen
+ return new String(chararr, 0, chararr_count);
+ }
+ static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) {
+ while (count-- > 0) {
+ dst[dstBegin++] = value[srcBegin++];
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/EOFException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/EOFException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * Signals that an end of file or end of stream has been reached
+ * unexpectedly during input.
+ *
+ * This exception is mainly used by data input streams to signal end of
+ * stream. Note that many other input operations return a special value on
+ * end of stream rather than throwing an exception.
+ *
+ *
+ * @author Frank Yellin
+ * @see java.io.DataInputStream
+ * @see java.io.IOException
+ * @since JDK1.0
+ */
+public
+class EOFException extends IOException {
+ private static final long serialVersionUID = 6433858223774886977L;
+
+ /**
+ * Constructs an EOFException with null
+ * as its error detail message.
+ */
+ public EOFException() {
+ super();
+ }
+
+ /**
+ * Constructs an EOFException with the specified detail
+ * message. The string s may later be retrieved by the
+ * {@link java.lang.Throwable#getMessage} method of class
+ * java.lang.Throwable.
+ *
+ * @param s the detail message.
+ */
+ public EOFException(String s) {
+ super(s);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/FilterInputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/FilterInputStream.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * A FilterInputStream contains
+ * some other input stream, which it uses as
+ * its basic source of data, possibly transforming
+ * the data along the way or providing additional
+ * functionality. The class FilterInputStream
+ * itself simply overrides all methods of
+ * InputStream with versions that
+ * pass all requests to the contained input
+ * stream. Subclasses of FilterInputStream
+ * may further override some of these methods
+ * and may also provide additional methods
+ * and fields.
+ *
+ * @author Jonathan Payne
+ * @since JDK1.0
+ */
+public
+class FilterInputStream extends InputStream {
+ /**
+ * The input stream to be filtered.
+ */
+ protected volatile InputStream in;
+
+ /**
+ * Creates a FilterInputStream
+ * by assigning the argument in
+ * to the field this.in so as
+ * to remember it for later use.
+ *
+ * @param in the underlying input stream, or null if
+ * this instance is to be created without an underlying stream.
+ */
+ protected FilterInputStream(InputStream in) {
+ this.in = in;
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an int in the range
+ * 0 to 255. If no byte is available
+ * because the end of the stream has been reached, the value
+ * -1 is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ *
+ * This method
+ * simply performs in.read() and returns the result.
+ *
+ * @return the next byte of data, or -1 if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public int read() throws IOException {
+ return in.read();
+ }
+
+ /**
+ * Reads up to byte.length bytes of data from this
+ * input stream into an array of bytes. This method blocks until some
+ * input is available.
+ *
+ * This method simply performs the call
+ * read(b, 0, b.length) and returns
+ * the result. It is important that it does
+ * not do in.read(b) instead;
+ * certain subclasses of FilterInputStream
+ * depend on the implementation strategy actually
+ * used.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#read(byte[], int, int)
+ */
+ public int read(byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to len bytes of data from this input stream
+ * into an array of bytes. If len is not zero, the method
+ * blocks until some input is available; otherwise, no
+ * bytes are read and 0 is returned.
+ *
+ * This method simply performs in.read(b, off, len)
+ * and returns the result.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception NullPointerException If b is null.
+ * @exception IndexOutOfBoundsException If off is negative,
+ * len is negative, or len is greater than
+ * b.length - off
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public int read(byte b[], int off, int len) throws IOException {
+ return in.read(b, off, len);
+ }
+
+ /**
+ * Skips over and discards n bytes of data from the
+ * input stream. The skip method may, for a variety of
+ * reasons, end up skipping over some smaller number of bytes,
+ * possibly 0. The actual number of bytes skipped is
+ * returned.
+ *
+ * This method simply performs in.skip(n).
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception IOException if the stream does not support seek,
+ * or if some other I/O error occurs.
+ */
+ public long skip(long n) throws IOException {
+ return in.skip(n);
+ }
+
+ /**
+ * Returns an estimate of the number of bytes that can be read (or
+ * skipped over) from this input stream without blocking by the next
+ * caller of a method for this input stream. The next caller might be
+ * the same thread or another thread. A single read or skip of this
+ * many bytes will not block, but may read or skip fewer bytes.
+ *
+ * This method returns the result of {@link #in in}.available().
+ *
+ * @return an estimate of the number of bytes that can be read (or skipped
+ * over) from this input stream without blocking.
+ * @exception IOException if an I/O error occurs.
+ */
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ /**
+ * Closes this input stream and releases any system resources
+ * associated with the stream.
+ * This
+ * method simply performs in.close().
+ *
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public void close() throws IOException {
+ in.close();
+ }
+
+ /**
+ * Marks the current position in this input stream. A subsequent
+ * call to the reset method repositions this stream at
+ * the last marked position so that subsequent reads re-read the same bytes.
+ *
+ * The readlimit argument tells this input stream to
+ * allow that many bytes to be read before the mark position gets
+ * invalidated.
+ *
+ * This method simply performs in.mark(readlimit).
+ *
+ * @param readlimit the maximum limit of bytes that can be read before
+ * the mark position becomes invalid.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.FilterInputStream#reset()
+ */
+ public synchronized void mark(int readlimit) {
+ in.mark(readlimit);
+ }
+
+ /**
+ * Repositions this stream to the position at the time the
+ * mark method was last called on this input stream.
+ *
+ * Stream marks are intended to be used in
+ * situations where you need to read ahead a little to see what's in
+ * the stream. Often this is most easily done by invoking some
+ * general parser. If the stream is of the type handled by the
+ * parse, it just chugs along happily. If the stream is not of
+ * that type, the parser should toss an exception when it fails.
+ * If this happens within readlimit bytes, it allows the outer
+ * code to reset the stream and try another parser.
+ *
+ * @exception IOException if the stream has not been marked or if the
+ * mark has been invalidated.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.FilterInputStream#mark(int)
+ */
+ public synchronized void reset() throws IOException {
+ in.reset();
+ }
+
+ /**
+ * Tests if this input stream supports the mark
+ * and reset methods.
+ * This method
+ * simply performs in.markSupported().
+ *
+ * @return true if this stream type supports the
+ * mark and reset method;
+ * false otherwise.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.InputStream#reset()
+ */
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/InputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/InputStream.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * This abstract class is the superclass of all classes representing
+ * an input stream of bytes.
+ *
+ *
Applications that need to define a subclass of InputStream
+ * must always provide a method that returns the next byte of input.
+ *
+ * @author Arthur van Hoff
+ * @see java.io.BufferedInputStream
+ * @see java.io.ByteArrayInputStream
+ * @see java.io.DataInputStream
+ * @see java.io.FilterInputStream
+ * @see java.io.InputStream#read()
+ * @see java.io.OutputStream
+ * @see java.io.PushbackInputStream
+ * @since JDK1.0
+ */
+public abstract class InputStream implements Closeable {
+
+ // SKIP_BUFFER_SIZE is used to determine the size of skipBuffer
+ private static final int SKIP_BUFFER_SIZE = 2048;
+ // skipBuffer is initialized in skip(long), if needed.
+ private static byte[] skipBuffer;
+
+ /**
+ * Reads the next byte of data from the input stream. The value byte is
+ * returned as an int in the range 0 to
+ * 255. If no byte is available because the end of the stream
+ * has been reached, the value -1 is returned. This method
+ * blocks until input data is available, the end of the stream is detected,
+ * or an exception is thrown.
+ *
+ *
A subclass must provide an implementation of this method.
+ *
+ * @return the next byte of data, or -1 if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ */
+ public abstract int read() throws IOException;
+
+ /**
+ * Reads some number of bytes from the input stream and stores them into
+ * the buffer array b. The number of bytes actually read is
+ * returned as an integer. This method blocks until input data is
+ * available, end of file is detected, or an exception is thrown.
+ *
+ *
If the length of b is zero, then no bytes are read and
+ * 0 is returned; otherwise, there is an attempt to read at
+ * least one byte. If no byte is available because the stream is at the
+ * end of the file, the value -1 is returned; otherwise, at
+ * least one byte is read and stored into b.
+ *
+ *
The first byte read is stored into element b[0], the
+ * next one into b[1], and so on. The number of bytes read is,
+ * at most, equal to the length of b. Let k be the
+ * number of bytes actually read; these bytes will be stored in elements
+ * b[0] through b[k-1],
+ * leaving elements b[k] through
+ * b[b.length-1] unaffected.
+ *
+ *
The read(b) method for class InputStream
+ * has the same effect as:
read(b, 0, b.length)
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException If the first byte cannot be read for any reason
+ * other than the end of the file, if the input stream has been closed, or
+ * if some other I/O error occurs.
+ * @exception NullPointerException if b is null.
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ public int read(byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to len bytes of data from the input stream into
+ * an array of bytes. An attempt is made to read as many as
+ * len bytes, but a smaller number may be read.
+ * The number of bytes actually read is returned as an integer.
+ *
+ *
This method blocks until input data is available, end of file is
+ * detected, or an exception is thrown.
+ *
+ *
If len is zero, then no bytes are read and
+ * 0 is returned; otherwise, there is an attempt to read at
+ * least one byte. If no byte is available because the stream is at end of
+ * file, the value -1 is returned; otherwise, at least one
+ * byte is read and stored into b.
+ *
+ *
The first byte read is stored into element b[off], the
+ * next one into b[off+1], and so on. The number of bytes read
+ * is, at most, equal to len. Let k be the number of
+ * bytes actually read; these bytes will be stored in elements
+ * b[off] through b[off+k-1],
+ * leaving elements b[off+k] through
+ * b[off+len-1] unaffected.
+ *
+ *
In every case, elements b[0] through
+ * b[off] and elements b[off+len] through
+ * b[b.length-1] are unaffected.
+ *
+ *
The read(b,off,len) method
+ * for class InputStream simply calls the method
+ * read() repeatedly. If the first such call results in an
+ * IOException, that exception is returned from the call to
+ * the read(b,off,len) method. If
+ * any subsequent call to read() results in a
+ * IOException, the exception is caught and treated as if it
+ * were end of file; the bytes read up to that point are stored into
+ * b and the number of bytes read before the exception
+ * occurred is returned. The default implementation of this method blocks
+ * until the requested amount of input data len has been read,
+ * end of file is detected, or an exception is thrown. Subclasses are encouraged
+ * to provide a more efficient implementation of this method.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in array b
+ * at which the data is written.
+ * @param len the maximum number of bytes to read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException If the first byte cannot be read for any reason
+ * other than end of file, or if the input stream has been closed, or if
+ * some other I/O error occurs.
+ * @exception NullPointerException If b is null.
+ * @exception IndexOutOfBoundsException If off is negative,
+ * len is negative, or len is greater than
+ * b.length - off
+ * @see java.io.InputStream#read()
+ */
+ public int read(byte b[], int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ int c = read();
+ if (c == -1) {
+ return -1;
+ }
+ b[off] = (byte)c;
+
+ int i = 1;
+ try {
+ for (; i < len ; i++) {
+ c = read();
+ if (c == -1) {
+ break;
+ }
+ b[off + i] = (byte)c;
+ }
+ } catch (IOException ee) {
+ }
+ return i;
+ }
+
+ /**
+ * Skips over and discards n bytes of data from this input
+ * stream. The skip method may, for a variety of reasons, end
+ * up skipping over some smaller number of bytes, possibly 0.
+ * This may result from any of a number of conditions; reaching end of file
+ * before n bytes have been skipped is only one possibility.
+ * The actual number of bytes skipped is returned. If n is
+ * negative, no bytes are skipped.
+ *
+ *
The skip method of this class creates a
+ * byte array and then repeatedly reads into it until n bytes
+ * have been read or the end of the stream has been reached. Subclasses are
+ * encouraged to provide a more efficient implementation of this method.
+ * For instance, the implementation may depend on the ability to seek.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception IOException if the stream does not support seek,
+ * or if some other I/O error occurs.
+ */
+ public long skip(long n) throws IOException {
+
+ long remaining = n;
+ int nr;
+ if (skipBuffer == null)
+ skipBuffer = new byte[SKIP_BUFFER_SIZE];
+
+ byte[] localSkipBuffer = skipBuffer;
+
+ if (n <= 0) {
+ return 0;
+ }
+
+ while (remaining > 0) {
+ nr = read(localSkipBuffer, 0,
+ (int) Math.min(SKIP_BUFFER_SIZE, remaining));
+ if (nr < 0) {
+ break;
+ }
+ remaining -= nr;
+ }
+
+ return n - remaining;
+ }
+
+ /**
+ * Returns an estimate of the number of bytes that can be read (or
+ * skipped over) from this input stream without blocking by the next
+ * invocation of a method for this input stream. The next invocation
+ * might be the same thread or another thread. A single read or skip of this
+ * many bytes will not block, but may read or skip fewer bytes.
+ *
+ *
Note that while some implementations of {@code InputStream} will return
+ * the total number of bytes in the stream, many will not. It is
+ * never correct to use the return value of this method to allocate
+ * a buffer intended to hold all data in this stream.
+ *
+ *
A subclass' implementation of this method may choose to throw an
+ * {@link IOException} if this input stream has been closed by
+ * invoking the {@link #close()} method.
+ *
+ *
The {@code available} method for class {@code InputStream} always
+ * returns {@code 0}.
+ *
+ *
This method should be overridden by subclasses.
+ *
+ * @return an estimate of the number of bytes that can be read (or skipped
+ * over) from this input stream without blocking or {@code 0} when
+ * it reaches the end of the input stream.
+ * @exception IOException if an I/O error occurs.
+ */
+ public int available() throws IOException {
+ return 0;
+ }
+
+ /**
+ * Closes this input stream and releases any system resources associated
+ * with the stream.
+ *
+ *
The close method of InputStream does
+ * nothing.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ public void close() throws IOException {}
+
+ /**
+ * Marks the current position in this input stream. A subsequent call to
+ * the reset method repositions this stream at the last marked
+ * position so that subsequent reads re-read the same bytes.
+ *
+ *
The readlimit arguments tells this input stream to
+ * allow that many bytes to be read before the mark position gets
+ * invalidated.
+ *
+ *
The general contract of mark is that, if the method
+ * markSupported returns true, the stream somehow
+ * remembers all the bytes read after the call to mark and
+ * stands ready to supply those same bytes again if and whenever the method
+ * reset is called. However, the stream is not required to
+ * remember any data at all if more than readlimit bytes are
+ * read from the stream before reset is called.
+ *
+ *
Marking a closed stream should not have any effect on the stream.
+ *
+ *
The mark method of InputStream does
+ * nothing.
+ *
+ * @param readlimit the maximum limit of bytes that can be read before
+ * the mark position becomes invalid.
+ * @see java.io.InputStream#reset()
+ */
+ public synchronized void mark(int readlimit) {}
+
+ /**
+ * Repositions this stream to the position at the time the
+ * mark method was last called on this input stream.
+ *
+ *
The general contract of reset is:
+ *
+ *
+ *
+ *
If the method markSupported returns
+ * true, then:
+ *
+ *
If the method mark has not been called since
+ * the stream was created, or the number of bytes read from the stream
+ * since mark was last called is larger than the argument
+ * to mark at that last call, then an
+ * IOException might be thrown.
+ *
+ *
If such an IOException is not thrown, then the
+ * stream is reset to a state such that all the bytes read since the
+ * most recent call to mark (or since the start of the
+ * file, if mark has not been called) will be resupplied
+ * to subsequent callers of the read method, followed by
+ * any bytes that otherwise would have been the next input data as of
+ * the time of the call to reset.
+ *
+ *
If the method markSupported returns
+ * false, then:
+ *
+ *
The call to reset may throw an
+ * IOException.
+ *
+ *
If an IOException is not thrown, then the stream
+ * is reset to a fixed state that depends on the particular type of the
+ * input stream and how it was created. The bytes that will be supplied
+ * to subsequent callers of the read method depend on the
+ * particular type of the input stream.
+ *
+ *
The method reset for class InputStream
+ * does nothing except throw an IOException.
+ *
+ * @exception IOException if this stream has not been marked or if the
+ * mark has been invalidated.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.IOException
+ */
+ public synchronized void reset() throws IOException {
+ throw new IOException("mark/reset not supported");
+ }
+
+ /**
+ * Tests if this input stream supports the mark and
+ * reset methods. Whether or not mark and
+ * reset are supported is an invariant property of a
+ * particular input stream instance. The markSupported method
+ * of InputStream returns false.
+ *
+ * @return true if this stream instance supports the mark
+ * and reset methods; false otherwise.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.InputStream#reset()
+ */
+ public boolean markSupported() {
+ return false;
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/PushbackInputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/PushbackInputStream.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * A PushbackInputStream adds
+ * functionality to another input stream, namely
+ * the ability to "push back" or "unread"
+ * one byte. This is useful in situations where
+ * it is convenient for a fragment of code
+ * to read an indefinite number of data bytes
+ * that are delimited by a particular byte
+ * value; after reading the terminating byte,
+ * the code fragment can "unread" it, so that
+ * the next read operation on the input stream
+ * will reread the byte that was pushed back.
+ * For example, bytes representing the characters
+ * constituting an identifier might be terminated
+ * by a byte representing an operator character;
+ * a method whose job is to read just an identifier
+ * can read until it sees the operator and
+ * then push the operator back to be re-read.
+ *
+ * @author David Connelly
+ * @author Jonathan Payne
+ * @since JDK1.0
+ */
+public
+class PushbackInputStream extends FilterInputStream {
+ /**
+ * The pushback buffer.
+ * @since JDK1.1
+ */
+ protected byte[] buf;
+
+ /**
+ * The position within the pushback buffer from which the next byte will
+ * be read. When the buffer is empty, pos is equal to
+ * buf.length; when the buffer is full, pos is
+ * equal to zero.
+ *
+ * @since JDK1.1
+ */
+ protected int pos;
+
+ /**
+ * Check to make sure that this stream has not been closed
+ */
+ private void ensureOpen() throws IOException {
+ if (in == null)
+ throw new IOException("Stream closed");
+ }
+
+ /**
+ * Creates a PushbackInputStream
+ * with a pushback buffer of the specified size,
+ * and saves its argument, the input stream
+ * in, for later use. Initially,
+ * there is no pushed-back byte (the field
+ * pushBack is initialized to
+ * -1).
+ *
+ * @param in the input stream from which bytes will be read.
+ * @param size the size of the pushback buffer.
+ * @exception IllegalArgumentException if size is <= 0
+ * @since JDK1.1
+ */
+ public PushbackInputStream(InputStream in, int size) {
+ super(in);
+ if (size <= 0) {
+ throw new IllegalArgumentException("size <= 0");
+ }
+ this.buf = new byte[size];
+ this.pos = size;
+ }
+
+ /**
+ * Creates a PushbackInputStream
+ * and saves its argument, the input stream
+ * in, for later use. Initially,
+ * there is no pushed-back byte (the field
+ * pushBack is initialized to
+ * -1).
+ *
+ * @param in the input stream from which bytes will be read.
+ */
+ public PushbackInputStream(InputStream in) {
+ this(in, 1);
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an int in the range
+ * 0 to 255. If no byte is available
+ * because the end of the stream has been reached, the value
+ * -1 is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ *
+ *
This method returns the most recently pushed-back byte, if there is
+ * one, and otherwise calls the read method of its underlying
+ * input stream and returns whatever value that method returns.
+ *
+ * @return the next byte of data, or -1 if the end of the
+ * stream has been reached.
+ * @exception IOException if this input stream has been closed by
+ * invoking its {@link #close()} method,
+ * or an I/O error occurs.
+ * @see java.io.InputStream#read()
+ */
+ public int read() throws IOException {
+ ensureOpen();
+ if (pos < buf.length) {
+ return buf[pos++] & 0xff;
+ }
+ return super.read();
+ }
+
+ /**
+ * Reads up to len bytes of data from this input stream into
+ * an array of bytes. This method first reads any pushed-back bytes; after
+ * that, if fewer than len bytes have been read then it
+ * reads from the underlying input stream. If len is not zero, the method
+ * blocks until at least 1 byte of input is available; otherwise, no
+ * bytes are read and 0 is returned.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * -1 if there is no more data because the end of
+ * the stream has been reached.
+ * @exception NullPointerException If b is null.
+ * @exception IndexOutOfBoundsException If off is negative,
+ * len is negative, or len is greater than
+ * b.length - off
+ * @exception IOException if this input stream has been closed by
+ * invoking its {@link #close()} method,
+ * or an I/O error occurs.
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ ensureOpen();
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ int avail = buf.length - pos;
+ if (avail > 0) {
+ if (len < avail) {
+ avail = len;
+ }
+ arraycopy(buf, pos, b, off, avail);
+ pos += avail;
+ off += avail;
+ len -= avail;
+ }
+ if (len > 0) {
+ len = super.read(b, off, len);
+ if (len == -1) {
+ return avail == 0 ? -1 : avail;
+ }
+ return avail + len;
+ }
+ return avail;
+ }
+
+ /**
+ * Pushes back a byte by copying it to the front of the pushback buffer.
+ * After this method returns, the next byte to be read will have the value
+ * (byte)b.
+ *
+ * @param b the int value whose low-order
+ * byte is to be pushed back.
+ * @exception IOException If there is not enough room in the pushback
+ * buffer for the byte, or this input stream has been closed by
+ * invoking its {@link #close()} method.
+ */
+ public void unread(int b) throws IOException {
+ ensureOpen();
+ if (pos == 0) {
+ throw new IOException("Push back buffer is full");
+ }
+ buf[--pos] = (byte)b;
+ }
+
+ /**
+ * Pushes back a portion of an array of bytes by copying it to the front
+ * of the pushback buffer. After this method returns, the next byte to be
+ * read will have the value b[off], the byte after that will
+ * have the value b[off+1], and so forth.
+ *
+ * @param b the byte array to push back.
+ * @param off the start offset of the data.
+ * @param len the number of bytes to push back.
+ * @exception IOException If there is not enough room in the pushback
+ * buffer for the specified number of bytes,
+ * or this input stream has been closed by
+ * invoking its {@link #close()} method.
+ * @since JDK1.1
+ */
+ public void unread(byte[] b, int off, int len) throws IOException {
+ ensureOpen();
+ if (len > pos) {
+ throw new IOException("Push back buffer is full");
+ }
+ pos -= len;
+ arraycopy(b, off, buf, pos, len);
+ }
+
+ /**
+ * Pushes back an array of bytes by copying it to the front of the
+ * pushback buffer. After this method returns, the next byte to be read
+ * will have the value b[0], the byte after that will have the
+ * value b[1], and so forth.
+ *
+ * @param b the byte array to push back
+ * @exception IOException If there is not enough room in the pushback
+ * buffer for the specified number of bytes,
+ * or this input stream has been closed by
+ * invoking its {@link #close()} method.
+ * @since JDK1.1
+ */
+ public void unread(byte[] b) throws IOException {
+ unread(b, 0, b.length);
+ }
+
+ /**
+ * Returns an estimate of the number of bytes that can be read (or
+ * skipped over) from this input stream without blocking by the next
+ * invocation of a method for this input stream. The next invocation might be
+ * the same thread or another thread. A single read or skip of this
+ * many bytes will not block, but may read or skip fewer bytes.
+ *
+ *
The method returns the sum of the number of bytes that have been
+ * pushed back and the value returned by {@link
+ * java.io.FilterInputStream#available available}.
+ *
+ * @return the number of bytes that can be read (or skipped over) from
+ * the input stream without blocking.
+ * @exception IOException if this input stream has been closed by
+ * invoking its {@link #close()} method,
+ * or an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.InputStream#available()
+ */
+ public int available() throws IOException {
+ ensureOpen();
+ int n = buf.length - pos;
+ int avail = super.available();
+ return n > (Integer.MAX_VALUE - avail)
+ ? Integer.MAX_VALUE
+ : n + avail;
+ }
+
+ /**
+ * Skips over and discards n bytes of data from this
+ * input stream. The skip method may, for a variety of
+ * reasons, end up skipping over some smaller number of bytes,
+ * possibly zero. If n is negative, no bytes are skipped.
+ *
+ *
The skip method of PushbackInputStream
+ * first skips over the bytes in the pushback buffer, if any. It then
+ * calls the skip method of the underlying input stream if
+ * more bytes need to be skipped. The actual number of bytes skipped
+ * is returned.
+ *
+ * @param n {@inheritDoc}
+ * @return {@inheritDoc}
+ * @exception IOException if the stream does not support seek,
+ * or the stream has been closed by
+ * invoking its {@link #close()} method,
+ * or an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ * @see java.io.InputStream#skip(long n)
+ * @since 1.2
+ */
+ public long skip(long n) throws IOException {
+ ensureOpen();
+ if (n <= 0) {
+ return 0;
+ }
+
+ long pskip = buf.length - pos;
+ if (pskip > 0) {
+ if (n < pskip) {
+ pskip = n;
+ }
+ pos += pskip;
+ n -= pskip;
+ }
+ if (n > 0) {
+ pskip += super.skip(n);
+ }
+ return pskip;
+ }
+
+ /**
+ * Tests if this input stream supports the mark and
+ * reset methods, which it does not.
+ *
+ * @return false, since this class does not support the
+ * mark and reset methods.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.InputStream#reset()
+ */
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Marks the current position in this input stream.
+ *
+ *
The mark method of PushbackInputStream
+ * does nothing.
+ *
+ * @param readlimit the maximum limit of bytes that can be read before
+ * the mark position becomes invalid.
+ * @see java.io.InputStream#reset()
+ */
+ public synchronized void mark(int readlimit) {
+ }
+
+ /**
+ * Repositions this stream to the position at the time the
+ * mark method was last called on this input stream.
+ *
+ *
The method reset for class
+ * PushbackInputStream does nothing except throw an
+ * IOException.
+ *
+ * @exception IOException if this method is invoked.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.IOException
+ */
+ public synchronized void reset() throws IOException {
+ throw new IOException("mark/reset not supported");
+ }
+
+ /**
+ * Closes this input stream and releases any system resources
+ * associated with the stream.
+ * Once the stream has been closed, further read(), unread(),
+ * available(), reset(), or skip() invocations will throw an IOException.
+ * Closing a previously closed stream has no effect.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ public synchronized void close() throws IOException {
+ if (in == null)
+ return;
+ in.close();
+ in = null;
+ buf = null;
+ }
+ static void arraycopy(byte[] value, int srcBegin, byte[] dst, int dstBegin, int count) {
+ while (count-- > 0) {
+ dst[dstBegin++] = value[srcBegin++];
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/UTFDataFormatException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/io/UTFDataFormatException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.io;
+
+/**
+ * Signals that a malformed string in
+ * modified UTF-8
+ * format has been read in a data
+ * input stream or by any class that implements the data input
+ * interface.
+ * See the
+ * DataInput
+ * class description for the format in
+ * which modified UTF-8 strings are read and written.
+ *
+ * @author Frank Yellin
+ * @see java.io.DataInput
+ * @see java.io.DataInputStream#readUTF(java.io.DataInput)
+ * @see java.io.IOException
+ * @since JDK1.0
+ */
+public
+class UTFDataFormatException extends IOException {
+ private static final long serialVersionUID = 420743449228280612L;
+
+ /**
+ * Constructs a UTFDataFormatException with
+ * null as its error detail message.
+ */
+ public UTFDataFormatException() {
+ super();
+ }
+
+ /**
+ * Constructs a UTFDataFormatException with the
+ * specified detail message. The string s can be
+ * retrieved later by the
+ * {@link java.lang.Throwable#getMessage}
+ * method of class java.lang.Throwable.
+ *
+ * @param s the detail message.
+ */
+ public UTFDataFormatException(String s) {
+ super(s);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/AbstractStringBuilder.java
--- a/emul/src/main/java/java/lang/AbstractStringBuilder.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,8 +25,6 @@
package java.lang;
-import org.apidesign.bck2brwsr.core.JavaScriptBody;
-
/**
* A mutable sequence of characters.
*
@@ -126,7 +124,7 @@
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
- value = String.copyOf(value, newCapacity);
+ value = copyOf(value, newCapacity);
}
/**
@@ -138,7 +136,7 @@
*/
public void trimToSize() {
if (count < value.length) {
- value = String.copyOf(value, count);
+ value = copyOf(value, count);
}
}
@@ -352,7 +350,7 @@
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
- String.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+ arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
/**
@@ -502,7 +500,7 @@
public AbstractStringBuilder append(char[] str) {
int len = str.length;
ensureCapacityInternal(count + len);
- String.arraycopy(str, 0, value, count, len);
+ arraycopy(str, 0, value, count, len);
count += len;
return this;
}
@@ -532,7 +530,7 @@
public AbstractStringBuilder append(char str[], int offset, int len) {
if (len > 0) // let arraycopy report AIOOBE for len < 0
ensureCapacityInternal(count + len);
- String.arraycopy(str, offset, value, count, len);
+ arraycopy(str, offset, value, count, len);
count += len;
return this;
}
@@ -600,22 +598,8 @@
* @param i an {@code int}.
* @return a reference to this object.
*/
- @JavaScriptBody(
- args={ "self", "i" },
- body="return java_lang_AbstractStringBuilder_appendLjava_lang_AbstractStringBuilderLjava_lang_String(self,i.toString());"
- )
public AbstractStringBuilder append(int i) {
- if (i == Integer.MIN_VALUE) {
- append("-2147483648");
- return this;
- }
- int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
- : Integer.stringSize(i);
- int spaceNeeded = count + appendedLength;
- ensureCapacityInternal(spaceNeeded);
- Integer.getChars(i, spaceNeeded, value);
- count = spaceNeeded;
- return this;
+ return append(Integer.toString(i));
}
/**
@@ -657,7 +641,7 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(float f) {
- throw new UnsupportedOperationException();
+ return append(Float.toString(f));
}
/**
@@ -673,7 +657,7 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(double d) {
- throw new UnsupportedOperationException();
+ return append(Double.toString(d));
}
/**
@@ -699,7 +683,7 @@
throw new StringIndexOutOfBoundsException();
int len = end - start;
if (len > 0) {
- String.arraycopy(value, start+len, value, start, count-end);
+ arraycopy(value, start+len, value, start, count-end);
count -= len;
}
return this;
@@ -761,7 +745,7 @@
public AbstractStringBuilder deleteCharAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
- String.arraycopy(value, index+1, value, index, count-index-1);
+ arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
@@ -799,7 +783,7 @@
int newCount = count + len - (end - start);
ensureCapacityInternal(newCount);
- String.arraycopy(value, end, value, start + len, count - end);
+ arraycopy(value, end, value, start + len, count - end);
str.getChars(value, start);
count = newCount;
return this;
@@ -905,8 +889,8 @@
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len);
- String.arraycopy(value, index, value, index + len, count - index);
- String.arraycopy(str, offset, value, index, len);
+ arraycopy(value, index, value, index + len, count - index);
+ arraycopy(str, offset, value, index, len);
count += len;
return this;
}
@@ -972,7 +956,7 @@
str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
- String.arraycopy(value, offset, value, offset + len, count - offset);
+ arraycopy(value, offset, value, offset + len, count - offset);
str.getChars(value, offset);
count += len;
return this;
@@ -1007,8 +991,8 @@
throw new StringIndexOutOfBoundsException(offset);
int len = str.length;
ensureCapacityInternal(count + len);
- String.arraycopy(value, offset, value, offset + len, count - offset);
- String.arraycopy(str, 0, value, offset, len);
+ arraycopy(value, offset, value, offset + len, count - offset);
+ arraycopy(str, 0, value, offset, len);
count += len;
return this;
}
@@ -1098,7 +1082,7 @@
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
- String.arraycopy(value, dstOffset, value, dstOffset + len,
+ arraycopy(value, dstOffset, value, dstOffset + len,
count - dstOffset);
for (int i=start; inull.
*/
public int indexOf(String str, int fromIndex) {
- return String.indexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return toString().indexOf(str, fromIndex);
}
/**
@@ -1405,4 +1388,37 @@
return value;
}
+ static char[] copyOfRange(char[] original, int from, int to) {
+ int newLength = to - from;
+ if (newLength < 0) {
+ throw new IllegalArgumentException(from + " > " + to);
+ }
+ char[] copy = new char[newLength];
+ arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
+ return copy;
+ }
+
+ static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) {
+ if (srcBegin < dstBegin) {
+ while (count-- > 0) {
+ dst[dstBegin + count] = value[srcBegin + count];
+ }
+ } else {
+ while (count-- > 0) {
+ dst[dstBegin++] = value[srcBegin++];
+ }
+ }
+ }
+
+ // access system property
+ static String getProperty(String nm) {
+ return null;
+ }
+
+ static char[] copyOf(char[] original, int newLength) {
+ char[] copy = new char[newLength];
+ arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
+ return copy;
+ }
+
}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/AutoCloseable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/AutoCloseable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * A resource that must be closed when it is no longer needed.
+ *
+ * @author Josh Bloch
+ * @since 1.7
+ */
+public interface AutoCloseable {
+ /**
+ * Closes this resource, relinquishing any underlying resources.
+ * This method is invoked automatically on objects managed by the
+ * {@code try}-with-resources statement.
+ *
+ *
While this interface method is declared to throw {@code
+ * Exception}, implementers are strongly encouraged to
+ * declare concrete implementations of the {@code close} method to
+ * throw more specific exceptions, or to throw no exception at all
+ * if the close operation cannot fail.
+ *
+ *
Implementers of this interface are also strongly advised
+ * to not have the {@code close} method throw {@link
+ * InterruptedException}.
+ *
+ * This exception interacts with a thread's interrupted status,
+ * and runtime misbehavior is likely to occur if an {@code
+ * InterruptedException} is {@linkplain Throwable#addSuppressed
+ * suppressed}.
+ *
+ * More generally, if it would cause problems for an
+ * exception to be suppressed, the {@code AutoCloseable.close}
+ * method should not throw it.
+ *
+ *
Note that unlike the {@link java.io.Closeable#close close}
+ * method of {@link java.io.Closeable}, this {@code close} method
+ * is not required to be idempotent. In other words,
+ * calling this {@code close} method more than once may have some
+ * visible side effect, unlike {@code Closeable.close} which is
+ * required to have no effect if called more than once.
+ *
+ * However, implementers of this interface are strongly encouraged
+ * to make their {@code close} methods idempotent.
+ *
+ * @throws Exception if this resource cannot be closed
+ */
+ void close() throws Exception;
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Boolean.java
--- a/emul/src/main/java/java/lang/Boolean.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Boolean.java Wed Jan 23 20:16:48 2013 +0100
@@ -235,7 +235,7 @@
public static boolean getBoolean(String name) {
boolean result = false;
try {
- result = toBoolean(String.getProperty(name));
+ result = toBoolean(AbstractStringBuilder.getProperty(name));
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Character.java
--- a/emul/src/main/java/java/lang/Character.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Character.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The {@code Character} class wraps a value of the primitive
* type {@code char} in an object. An object of type
@@ -1525,7 +1527,7 @@
* @see Character#getType(char)
*/
public static boolean isLowerCase(char ch) {
- throw new UnsupportedOperationException();
+ return ch == toLowerCase(ch);
}
/**
@@ -1560,7 +1562,7 @@
* @since 1.0
*/
public static boolean isUpperCase(char ch) {
- throw new UnsupportedOperationException();
+ return ch == toUpperCase(ch);
}
/**
@@ -1676,7 +1678,7 @@
* @see Character#getType(char)
*/
public static boolean isDigit(char ch) {
- return isDigit((int)ch);
+ return String.valueOf(ch).matches("\\d");
}
/**
@@ -1710,8 +1712,11 @@
* @since 1.5
*/
public static boolean isDigit(int codePoint) {
- return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
+ return fromCodeChars(codePoint).matches("\\d");
}
+
+ @JavaScriptBody(args = "c", body = "return String.fromCharCode(c);")
+ private native static String fromCodeChars(int codePoint);
/**
* Determines if a character is defined in Unicode.
@@ -1802,7 +1807,7 @@
* @see Character#isUpperCase(char)
*/
public static boolean isLetter(char ch) {
- return isLetter((int)ch);
+ return String.valueOf(ch).matches("\\w") && !isDigit(ch);
}
/**
@@ -1835,12 +1840,7 @@
* @since 1.5
*/
public static boolean isLetter(int codePoint) {
- return ((((1 << Character.UPPERCASE_LETTER) |
- (1 << Character.LOWERCASE_LETTER) |
- (1 << Character.TITLECASE_LETTER) |
- (1 << Character.MODIFIER_LETTER) |
- (1 << Character.OTHER_LETTER)) >> getType(codePoint)) & 1)
- != 0;
+ return fromCodeChars(codePoint).matches("\\w") && !isDigit(codePoint);
}
/**
@@ -1868,7 +1868,7 @@
* @since 1.0.2
*/
public static boolean isLetterOrDigit(char ch) {
- return isLetterOrDigit((int)ch);
+ return String.valueOf(ch).matches("\\w");
}
/**
@@ -1889,13 +1889,7 @@
* @since 1.5
*/
public static boolean isLetterOrDigit(int codePoint) {
- return ((((1 << Character.UPPERCASE_LETTER) |
- (1 << Character.LOWERCASE_LETTER) |
- (1 << Character.TITLECASE_LETTER) |
- (1 << Character.MODIFIER_LETTER) |
- (1 << Character.OTHER_LETTER) |
- (1 << Character.DECIMAL_DIGIT_NUMBER)) >> getType(codePoint)) & 1)
- != 0;
+ return fromCodeChars(codePoint).matches("\\w");
}
static int getType(int x) {
@@ -1930,7 +1924,7 @@
* @see String#toLowerCase()
*/
public static char toLowerCase(char ch) {
- throw new UnsupportedOperationException();
+ return String.valueOf(ch).toLowerCase().charAt(0);
}
/**
@@ -1961,7 +1955,7 @@
* @see String#toUpperCase()
*/
public static char toUpperCase(char ch) {
- throw new UnsupportedOperationException();
+ return String.valueOf(ch).toUpperCase().charAt(0);
}
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Class.java
--- a/emul/src/main/java/java/lang/Class.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Class.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,7 +25,15 @@
package java.lang;
+import java.io.ByteArrayInputStream;
+import org.apidesign.bck2brwsr.emul.AnnotationImpl;
+import java.io.InputStream;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.TypeVariable;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.emul.MethodImpl;
/**
* Instances of the class {@code Class} represent classes and
@@ -73,10 +81,10 @@
* @since JDK1.0
*/
public final
- class Class implements java.io.Serializable {
-// java.lang.reflect.GenericDeclaration,
-// java.lang.reflect.Type,
-// java.lang.reflect.AnnotatedElement {
+ class Class implements java.io.Serializable,
+ java.lang.reflect.GenericDeclaration,
+ java.lang.reflect.Type,
+ java.lang.reflect.AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
@@ -137,9 +145,31 @@
* @exception ClassNotFoundException if the class cannot be located
*/
public static Class> forName(String className)
- throws ClassNotFoundException {
- throw new UnsupportedOperationException();
+ throws ClassNotFoundException {
+ if (className.startsWith("[")) {
+ Class> arrType = defineArray(className);
+ Class> c = arrType;
+ while (c != null && c.isArray()) {
+ c = c.getComponentType0(); // verify component type is sane
+ }
+ return arrType;
+ }
+ Class> c = loadCls(className, className.replace('.', '_'));
+ if (c == null) {
+ throw new ClassNotFoundException(className);
+ }
+ return c;
}
+
+ @JavaScriptBody(args = {"n", "c" }, body =
+ "if (vm[c]) return vm[c].$class;\n"
+ + "if (vm.loadClass) {\n"
+ + " vm.loadClass(n);\n"
+ + " if (vm[c]) return vm[c].$class;\n"
+ + "}\n"
+ + "return null;"
+ )
+ private static native Class> loadCls(String n, String c);
/**
@@ -189,10 +219,32 @@
*
*
*/
+ @JavaScriptBody(args = { "self", "illegal" }, body =
+ "\nvar c = self.cnstr;"
+ + "\nif (c['cons__V']) {"
+ + "\n if ((c.cons__V.access & 0x1) != 0) {"
+ + "\n var inst = c();"
+ + "\n c.cons__V.call(inst);"
+ + "\n return inst;"
+ + "\n }"
+ + "\n return illegal;"
+ + "\n}"
+ + "\nreturn null;"
+ )
+ private static native Object newInstance0(Class> self, Object illegal);
+
public T newInstance()
throws InstantiationException, IllegalAccessException
{
- throw new UnsupportedOperationException("Should be somehow supported");
+ Object illegal = new Object();
+ Object inst = newInstance0(this, illegal);
+ if (inst == null) {
+ throw new InstantiationException(getName());
+ }
+ if (inst == illegal) {
+ throw new IllegalAccessException();
+ }
+ return (T)inst;
}
/**
@@ -225,7 +277,15 @@
*
* @since JDK1.1
*/
- public native boolean isInstance(Object obj);
+ public boolean isInstance(Object obj) {
+ String prop = "$instOf_" + getName().replace('.', '_');
+ return hasProperty(obj, prop);
+ }
+
+ @JavaScriptBody(args = { "who", "prop" }, body =
+ "if (who[prop]) return true; else return false;"
+ )
+ private static native boolean hasProperty(Object who, String prop);
/**
@@ -262,7 +322,12 @@
* @return {@code true} if this object represents an interface;
* {@code false} otherwise.
*/
- public native boolean isInterface();
+ public boolean isInterface() {
+ return (getAccess() & 0x200) != 0;
+ }
+
+ @JavaScriptBody(args = {}, body = "return this.access;")
+ private native int getAccess();
/**
@@ -272,7 +337,9 @@
* {@code false} otherwise.
* @since JDK1.1
*/
- public native boolean isArray();
+ public boolean isArray() {
+ return hasProperty(this, "array"); // NOI18N
+ }
/**
@@ -303,6 +370,10 @@
* @see java.lang.Void#TYPE
* @since JDK1.1
*/
+ @JavaScriptBody(args = {}, body =
+ "if (this.primitive) return true;"
+ + "else return false;"
+ )
public native boolean isPrimitive();
/**
@@ -381,13 +452,32 @@
* represented by this object.
*/
public String getName() {
- throw new UnsupportedOperationException();
-// String name = this.name;
-// if (name == null)
-// this.name = name = getName0();
-// return name;
+ return jvmName().replace('/', '.');
}
+ @JavaScriptBody(args = {}, body = "return this.jvmName;")
+ private native String jvmName();
+
+
+ /**
+ * Returns an array of {@code TypeVariable} objects that represent the
+ * type variables declared by the generic declaration represented by this
+ * {@code GenericDeclaration} object, in declaration order. Returns an
+ * array of length 0 if the underlying generic declaration declares no type
+ * variables.
+ *
+ * @return an array of {@code TypeVariable} objects that represent
+ * the type variables declared by this generic declaration
+ * @throws java.lang.reflect.GenericSignatureFormatError if the generic
+ * signature of this generic declaration does not conform to
+ * the format specified in
+ * The Java™ Virtual Machine Specification
+ * @since 1.5
+ */
+ public TypeVariable>[] getTypeParameters() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Returns the {@code Class} representing the superclass of the entity
* (class, interface, primitive type or void) represented by this
@@ -399,6 +489,7 @@
*
* @return the superclass of the class represented by this object.
*/
+ @JavaScriptBody(args = {}, body = "return this.superclass;")
public native Class super T> getSuperclass();
/**
@@ -444,37 +535,290 @@
* @since 1.5
*/
public String getSimpleName() {
- throw new UnsupportedOperationException();
-//// if (isArray())
-//// return getComponentType().getSimpleName()+"[]";
-////
-//// String simpleName = getSimpleBinaryName();
-//// if (simpleName == null) { // top level class
-//// simpleName = getName();
-//// return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
-//// }
-//// // According to JLS3 "Binary Compatibility" (13.1) the binary
-//// // name of non-package classes (not top level) is the binary
-//// // name of the immediately enclosing class followed by a '$' followed by:
-//// // (for nested and inner classes): the simple name.
-//// // (for local classes): 1 or more digits followed by the simple name.
-//// // (for anonymous classes): 1 or more digits.
-////
-//// // Since getSimpleBinaryName() will strip the binary name of
-//// // the immediatly enclosing class, we are now looking at a
-//// // string that matches the regular expression "\$[0-9]*"
-//// // followed by a simple name (considering the simple of an
-//// // anonymous class to be the empty string).
-////
-//// // Remove leading "\$[0-9]*" from the name
-//// int length = simpleName.length();
-//// if (length < 1 || simpleName.charAt(0) != '$')
-//// throw new InternalError("Malformed class name");
-//// int index = 1;
-//// while (index < length && isAsciiDigit(simpleName.charAt(index)))
-//// index++;
-//// // Eventually, this is the empty string iff this is an anonymous class
-//// return simpleName.substring(index);
+ if (isArray())
+ return getComponentType().getSimpleName()+"[]";
+
+ String simpleName = getSimpleBinaryName();
+ if (simpleName == null) { // top level class
+ simpleName = getName();
+ return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
+ }
+ // According to JLS3 "Binary Compatibility" (13.1) the binary
+ // name of non-package classes (not top level) is the binary
+ // name of the immediately enclosing class followed by a '$' followed by:
+ // (for nested and inner classes): the simple name.
+ // (for local classes): 1 or more digits followed by the simple name.
+ // (for anonymous classes): 1 or more digits.
+
+ // Since getSimpleBinaryName() will strip the binary name of
+ // the immediatly enclosing class, we are now looking at a
+ // string that matches the regular expression "\$[0-9]*"
+ // followed by a simple name (considering the simple of an
+ // anonymous class to be the empty string).
+
+ // Remove leading "\$[0-9]*" from the name
+ int length = simpleName.length();
+ if (length < 1 || simpleName.charAt(0) != '$')
+ throw new IllegalStateException("Malformed class name");
+ int index = 1;
+ while (index < length && isAsciiDigit(simpleName.charAt(index)))
+ index++;
+ // Eventually, this is the empty string iff this is an anonymous class
+ return simpleName.substring(index);
+ }
+
+ /**
+ * Returns the "simple binary name" of the underlying class, i.e.,
+ * the binary name without the leading enclosing class name.
+ * Returns {@code null} if the underlying class is a top level
+ * class.
+ */
+ private String getSimpleBinaryName() {
+ Class> enclosingClass = null; // XXX getEnclosingClass();
+ if (enclosingClass == null) // top level class
+ return null;
+ // Otherwise, strip the enclosing class' name
+ try {
+ return getName().substring(enclosingClass.getName().length());
+ } catch (IndexOutOfBoundsException ex) {
+ throw new IllegalStateException("Malformed class name");
+ }
+ }
+
+ /**
+ * Returns an array containing {@code Field} objects reflecting all
+ * the accessible public fields of the class or interface represented by
+ * this {@code Class} object. The elements in the array returned are
+ * not sorted and are not in any particular order. This method returns an
+ * array of length 0 if the class or interface has no accessible public
+ * fields, or if it represents an array class, a primitive type, or void.
+ *
+ *
Specifically, if this {@code Class} object represents a class,
+ * this method returns the public fields of this class and of all its
+ * superclasses. If this {@code Class} object represents an
+ * interface, this method returns the fields of this interface and of all
+ * its superinterfaces.
+ *
+ *
The implicit length field for array class is not reflected by this
+ * method. User code should use the methods of class {@code Array} to
+ * manipulate arrays.
+ *
+ *
See The Java Language Specification, sections 8.2 and 8.3.
+ *
+ * @return the array of {@code Field} objects representing the
+ * public fields
+ * @exception SecurityException
+ * If a security manager, s, is present and any of the
+ * following conditions is met:
+ *
+ *
+ *
+ *
invocation of
+ * {@link SecurityManager#checkMemberAccess
+ * s.checkMemberAccess(this, Member.PUBLIC)} denies
+ * access to the fields within this class
+ *
+ *
the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to the package
+ * of this class
+ *
+ *
+ *
+ * @since JDK1.1
+ */
+ public Field[] getFields() throws SecurityException {
+ throw new SecurityException();
+ }
+
+ /**
+ * Returns an array containing {@code Method} objects reflecting all
+ * the public member methods of the class or interface represented
+ * by this {@code Class} object, including those declared by the class
+ * or interface and those inherited from superclasses and
+ * superinterfaces. Array classes return all the (public) member methods
+ * inherited from the {@code Object} class. The elements in the array
+ * returned are not sorted and are not in any particular order. This
+ * method returns an array of length 0 if this {@code Class} object
+ * represents a class or interface that has no public member methods, or if
+ * this {@code Class} object represents a primitive type or void.
+ *
+ *
The class initialization method {@code } is not
+ * included in the returned array. If the class declares multiple public
+ * member methods with the same parameter types, they are all included in
+ * the returned array.
+ *
+ *
See The Java Language Specification, sections 8.2 and 8.4.
+ *
+ * @return the array of {@code Method} objects representing the
+ * public methods of this class
+ * @exception SecurityException
+ * If a security manager, s, is present and any of the
+ * following conditions is met:
+ *
+ *
+ *
+ *
invocation of
+ * {@link SecurityManager#checkMemberAccess
+ * s.checkMemberAccess(this, Member.PUBLIC)} denies
+ * access to the methods within this class
+ *
+ *
the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to the package
+ * of this class
+ *
+ *
+ *
+ * @since JDK1.1
+ */
+ public Method[] getMethods() throws SecurityException {
+ return MethodImpl.findMethods(this, 0x01);
+ }
+
+ /**
+ * Returns a {@code Field} object that reflects the specified public
+ * member field of the class or interface represented by this
+ * {@code Class} object. The {@code name} parameter is a
+ * {@code String} specifying the simple name of the desired field.
+ *
+ *
The field to be reflected is determined by the algorithm that
+ * follows. Let C be the class represented by this object:
+ *
+ *
If C declares a public field with the name specified, that is the
+ * field to be reflected.
+ *
If no field was found in step 1 above, this algorithm is applied
+ * recursively to each direct superinterface of C. The direct
+ * superinterfaces are searched in the order they were declared.
+ *
If no field was found in steps 1 and 2 above, and C has a
+ * superclass S, then this algorithm is invoked recursively upon S.
+ * If C has no superclass, then a {@code NoSuchFieldException}
+ * is thrown.
+ *
+ *
+ *
See The Java Language Specification, sections 8.2 and 8.3.
+ *
+ * @param name the field name
+ * @return the {@code Field} object of this class specified by
+ * {@code name}
+ * @exception NoSuchFieldException if a field with the specified name is
+ * not found.
+ * @exception NullPointerException if {@code name} is {@code null}
+ * @exception SecurityException
+ * If a security manager, s, is present and any of the
+ * following conditions is met:
+ *
+ *
+ *
+ *
invocation of
+ * {@link SecurityManager#checkMemberAccess
+ * s.checkMemberAccess(this, Member.PUBLIC)} denies
+ * access to the field
+ *
+ *
the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to the package
+ * of this class
+ *
+ *
+ *
+ * @since JDK1.1
+ */
+ public Field getField(String name)
+ throws SecurityException {
+ throw new SecurityException();
+ }
+
+
+ /**
+ * Returns a {@code Method} object that reflects the specified public
+ * member method of the class or interface represented by this
+ * {@code Class} object. The {@code name} parameter is a
+ * {@code String} specifying the simple name of the desired method. The
+ * {@code parameterTypes} parameter is an array of {@code Class}
+ * objects that identify the method's formal parameter types, in declared
+ * order. If {@code parameterTypes} is {@code null}, it is
+ * treated as if it were an empty array.
+ *
+ *
If the {@code name} is "{@code };"or "{@code }" a
+ * {@code NoSuchMethodException} is raised. Otherwise, the method to
+ * be reflected is determined by the algorithm that follows. Let C be the
+ * class represented by this object:
+ *
+ *
C is searched for any matching methods. If no matching
+ * method is found, the algorithm of step 1 is invoked recursively on
+ * the superclass of C.
+ *
If no method was found in step 1 above, the superinterfaces of C
+ * are searched for a matching method. If any such method is found, it
+ * is reflected.
+ *
+ *
+ * To find a matching method in a class C: If C declares exactly one
+ * public method with the specified name and exactly the same formal
+ * parameter types, that is the method reflected. If more than one such
+ * method is found in C, and one of these methods has a return type that is
+ * more specific than any of the others, that method is reflected;
+ * otherwise one of the methods is chosen arbitrarily.
+ *
+ *
Note that there may be more than one matching method in a
+ * class because while the Java language forbids a class to
+ * declare multiple methods with the same signature but different
+ * return types, the Java virtual machine does not. This
+ * increased flexibility in the virtual machine can be used to
+ * implement various language features. For example, covariant
+ * returns can be implemented with {@linkplain
+ * java.lang.reflect.Method#isBridge bridge methods}; the bridge
+ * method and the method being overridden would have the same
+ * signature but different return types.
+ *
+ *
See The Java Language Specification, sections 8.2 and 8.4.
+ *
+ * @param name the name of the method
+ * @param parameterTypes the list of parameters
+ * @return the {@code Method} object that matches the specified
+ * {@code name} and {@code parameterTypes}
+ * @exception NoSuchMethodException if a matching method is not found
+ * or if the name is "<init>"or "<clinit>".
+ * @exception NullPointerException if {@code name} is {@code null}
+ * @exception SecurityException
+ * If a security manager, s, is present and any of the
+ * following conditions is met:
+ *
+ *
+ *
+ *
invocation of
+ * {@link SecurityManager#checkMemberAccess
+ * s.checkMemberAccess(this, Member.PUBLIC)} denies
+ * access to the method
+ *
+ *
the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to the package
+ * of this class
+ *
+ *
+ *
+ * @since JDK1.1
+ */
+ public Method getMethod(String name, Class>... parameterTypes)
+ throws SecurityException, NoSuchMethodException {
+ Method m = MethodImpl.findMethod(this, name, parameterTypes);
+ if (m == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getName()).append('.').append(name).append('(');
+ String sep = "";
+ for (int i = 0; i < parameterTypes.length; i++) {
+ sb.append(sep).append(parameterTypes[i].getName());
+ sep = ", ";
+ }
+ sb.append(')');
+ throw new NoSuchMethodException(sb.toString());
+ }
+ return m;
}
/**
@@ -496,25 +840,25 @@
* @since 1.5
*/
public String getCanonicalName() {
- throw new UnsupportedOperationException();
-// if (isArray()) {
-// String canonicalName = getComponentType().getCanonicalName();
-// if (canonicalName != null)
-// return canonicalName + "[]";
-// else
-// return null;
-// }
+ if (isArray()) {
+ String canonicalName = getComponentType().getCanonicalName();
+ if (canonicalName != null)
+ return canonicalName + "[]";
+ else
+ return null;
+ }
// if (isLocalOrAnonymousClass())
// return null;
// Class> enclosingClass = getEnclosingClass();
-// if (enclosingClass == null) { // top level class
-// return getName();
-// } else {
-// String enclosingName = enclosingClass.getCanonicalName();
-// if (enclosingName == null)
-// return null;
-// return enclosingName + "." + getSimpleName();
-// }
+ Class> enclosingClass = null;
+ if (enclosingClass == null) { // top level class
+ return getName();
+ } else {
+ String enclosingName = enclosingClass.getCanonicalName();
+ if (enclosingName == null)
+ return null;
+ return enclosingName + "." + getSimpleName();
+ }
}
/**
@@ -552,15 +896,16 @@
* @throws NullPointerException If {@code name} is {@code null}
* @since JDK1.1
*/
-// public InputStream getResourceAsStream(String name) {
-// name = resolveName(name);
-// ClassLoader cl = getClassLoader0();
-// if (cl==null) {
-// // A system class.
-// return ClassLoader.getSystemResourceAsStream(name);
-// }
-// return cl.getResourceAsStream(name);
-// }
+ public InputStream getResourceAsStream(String name) {
+ name = resolveName(name);
+ byte[] arr = getResourceAsStream0(name);
+ return arr == null ? null : new ByteArrayInputStream(arr);
+ }
+
+ @JavaScriptBody(args = "name", body =
+ "return (vm.loadBytes) ? vm.loadBytes(name) : null;"
+ )
+ private static native byte[] getResourceAsStream0(String name);
/**
* Finds a resource with a given name. The rules for searching resources
@@ -596,19 +941,136 @@
* resource with this name is found
* @since JDK1.1
*/
-// public java.net.URL getResource(String name) {
-// name = resolveName(name);
-// ClassLoader cl = getClassLoader0();
-// if (cl==null) {
-// // A system class.
-// return ClassLoader.getSystemResource(name);
-// }
-// return cl.getResource(name);
-// }
+ public java.net.URL getResource(String name) {
+ name = resolveName(name);
+ ClassLoader cl = null;
+ if (cl==null) {
+ // A system class.
+ return ClassLoader.getSystemResource(name);
+ }
+ return cl.getResource(name);
+ }
+ /**
+ * Add a package name prefix if the name is not absolute Remove leading "/"
+ * if name is absolute
+ */
+ private String resolveName(String name) {
+ if (name == null) {
+ return name;
+ }
+ if (!name.startsWith("/")) {
+ Class> c = this;
+ while (c.isArray()) {
+ c = c.getComponentType();
+ }
+ String baseName = c.getName();
+ int index = baseName.lastIndexOf('.');
+ if (index != -1) {
+ name = baseName.substring(0, index).replace('.', '/')
+ +"/"+name;
+ }
+ } else {
+ name = name.substring(1);
+ }
+ return name;
+ }
+
+ /**
+ * Returns the class loader for the class. Some implementations may use
+ * null to represent the bootstrap class loader. This method will return
+ * null in such implementations if this class was loaded by the bootstrap
+ * class loader.
+ *
+ *
If a security manager is present, and the caller's class loader is
+ * not null and the caller's class loader is not the same as or an ancestor of
+ * the class loader for the class whose class loader is requested, then
+ * this method calls the security manager's {@code checkPermission}
+ * method with a {@code RuntimePermission("getClassLoader")}
+ * permission to ensure it's ok to access the class loader for the class.
+ *
+ *
Every {@link Class Class} object contains a {@link
+ * Class#getClassLoader() reference} to the ClassLoader that defined
+ * it.
+ *
+ *
Class objects for array classes are not created by class
+ * loaders, but are created automatically as required by the Java runtime.
+ * The class loader for an array class, as returned by {@link
+ * Class#getClassLoader()} is the same as the class loader for its element
+ * type; if the element type is a primitive type, then the array class has no
+ * class loader.
+ *
+ *
Applications implement subclasses of ClassLoader in order to
+ * extend the manner in which the Java virtual machine dynamically loads
+ * classes.
+ *
+ *
Class loaders may typically be used by security managers to indicate
+ * security domains.
+ *
+ *
The ClassLoader class uses a delegation model to search for
+ * classes and resources. Each instance of ClassLoader has an
+ * associated parent class loader. When requested to find a class or
+ * resource, a ClassLoader instance will delegate the search for the
+ * class or resource to its parent class loader before attempting to find the
+ * class or resource itself. The virtual machine's built-in class loader,
+ * called the "bootstrap class loader", does not itself have a parent but may
+ * serve as the parent of a ClassLoader instance.
+ *
+ *
Class loaders that support concurrent loading of classes are known as
+ * parallel capable class loaders and are required to register
+ * themselves at their class initialization time by invoking the
+ * {@link
+ * #registerAsParallelCapable ClassLoader.registerAsParallelCapable}
+ * method. Note that the ClassLoader class is registered as parallel
+ * capable by default. However, its subclasses still need to register themselves
+ * if they are parallel capable.
+ * In environments in which the delegation model is not strictly
+ * hierarchical, class loaders need to be parallel capable, otherwise class
+ * loading can lead to deadlocks because the loader lock is held for the
+ * duration of the class loading process (see {@link #loadClass
+ * loadClass} methods).
+ *
+ *
Normally, the Java virtual machine loads classes from the local file
+ * system in a platform-dependent manner. For example, on UNIX systems, the
+ * virtual machine loads classes from the directory defined by the
+ * CLASSPATH environment variable.
+ *
+ *
However, some classes may not originate from a file; they may originate
+ * from other sources, such as the network, or they could be constructed by an
+ * application. The method {@link #defineClass(String, byte[], int, int)
+ * defineClass} converts an array of bytes into an instance of class
+ * Class. Instances of this newly defined class can be created using
+ * {@link Class#newInstance Class.newInstance}.
+ *
+ *
The methods and constructors of objects created by a class loader may
+ * reference other classes. To determine the class(es) referred to, the Java
+ * virtual machine invokes the {@link #loadClass loadClass} method of
+ * the class loader that originally created the class.
+ *
+ *
For example, an application could create a network class loader to
+ * download class files from a server. Sample code might look like:
+ *
+ *
The network class loader subclass must define the methods {@link
+ * #findClass findClass} and loadClassData to load a class
+ * from the network. Once it has downloaded the bytes that make up the class,
+ * it should use the method {@link #defineClass defineClass} to
+ * create a class instance. A sample implementation is:
+ *
+ *
+ * class NetworkClassLoader extends ClassLoader {
+ * String host;
+ * int port;
+ *
+ * public Class findClass(String name) {
+ * byte[] b = loadClassData(name);
+ * return defineClass(name, b, 0, b.length);
+ * }
+ *
+ * private byte[] loadClassData(String name) {
+ * // load the class data from the connection
+ * . . .
+ * }
+ * }
+ *
Any class name provided as a {@link String} parameter to methods in
+ * ClassLoader must be a binary name as defined by
+ * The Java™ Language Specification.
+ *
+ *
+ *
+ * @see #resolveClass(Class)
+ * @since 1.0
+ */
+public abstract class ClassLoader {
+
+ @JavaScriptBody(args = {}, body = "")
+ private static native void registerNatives();
+ static {
+ registerNatives();
+ }
+
+ // The parent class loader for delegation
+ // Note: VM hardcoded the offset of this field, thus all new fields
+ // must be added *after* it.
+ private final ClassLoader parent;
+
+
+ /**
+ * Creates a new class loader using the specified parent class loader for
+ * delegation.
+ *
+ *
If there is a security manager, its {@link
+ * SecurityManager#checkCreateClassLoader()
+ * checkCreateClassLoader} method is invoked. This may result in
+ * a security exception.
+ *
+ * @param parent
+ * The parent class loader
+ *
+ * @throws SecurityException
+ * If a security manager exists and its
+ * checkCreateClassLoader method doesn't allow creation
+ * of a new class loader.
+ *
+ * @since 1.2
+ */
+ protected ClassLoader(ClassLoader parent) {
+ throw new SecurityException();
+ }
+
+ /**
+ * Creates a new class loader using the ClassLoader returned by
+ * the method {@link #getSystemClassLoader()
+ * getSystemClassLoader()} as the parent class loader.
+ *
+ *
If there is a security manager, its {@link
+ * SecurityManager#checkCreateClassLoader()
+ * checkCreateClassLoader} method is invoked. This may result in
+ * a security exception.
+ *
+ * @throws SecurityException
+ * If a security manager exists and its
+ * checkCreateClassLoader method doesn't allow creation
+ * of a new class loader.
+ */
+ protected ClassLoader() {
+ throw new SecurityException();
+ }
+
+ // -- Class --
+
+ /**
+ * Loads the class with the specified binary name.
+ * This method searches for classes in the same manner as the {@link
+ * #loadClass(String, boolean)} method. It is invoked by the Java virtual
+ * machine to resolve class references. Invoking this method is equivalent
+ * to invoking {@link #loadClass(String, boolean) loadClass(name,
+ * false)}.
+ *
+ * @param name
+ * The binary name of the class
+ *
+ * @return The resulting Class object
+ *
+ * @throws ClassNotFoundException
+ * If the class was not found
+ */
+ public Class> loadClass(String name) throws ClassNotFoundException {
+ return loadClass(name, false);
+ }
+
+ /**
+ * Loads the class with the specified binary name. The
+ * default implementation of this method searches for classes in the
+ * following order:
+ *
+ *
+ *
+ *
Invoke {@link #findLoadedClass(String)} to check if the class
+ * has already been loaded.
+ *
+ *
Invoke the {@link #loadClass(String) loadClass} method
+ * on the parent class loader. If the parent is null the class
+ * loader built-in to the virtual machine is used, instead.
+ *
+ *
Invoke the {@link #findClass(String)} method to find the
+ * class.
+ *
+ *
+ *
+ *
If the class was found using the above steps, and the
+ * resolve flag is true, this method will then invoke the {@link
+ * #resolveClass(Class)} method on the resulting Class object.
+ *
+ *
Subclasses of ClassLoader are encouraged to override {@link
+ * #findClass(String)}, rather than this method.
+ *
+ *
Unless overridden, this method synchronizes on the result of
+ * {@link #getClassLoadingLock getClassLoadingLock} method
+ * during the entire class loading process.
+ *
+ * @param name
+ * The binary name of the class
+ *
+ * @param resolve
+ * If true then resolve the class
+ *
+ * @return The resulting Class object
+ *
+ * @throws ClassNotFoundException
+ * If the class could not be found
+ */
+ protected Class> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ synchronized (getClassLoadingLock(name)) {
+ // First, check if the class has already been loaded
+ Class c = findLoadedClass(name);
+ if (c == null) {
+ try {
+ if (parent != null) {
+ c = parent.loadClass(name, false);
+ } else {
+ c = findBootstrapClassOrNull(name);
+ }
+ } catch (ClassNotFoundException e) {
+ // ClassNotFoundException thrown if class not found
+ // from the non-null parent class loader
+ }
+
+ if (c == null) {
+ // If still not found, then invoke findClass in order
+ // to find the class.
+ c = findClass(name);
+
+// // this is the defining class loader; record the stats
+// sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+// sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+// sun.misc.PerfCounter.getFindClasses().increment();
+ }
+ }
+ if (resolve) {
+ resolveClass(c);
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Returns the lock object for class loading operations.
+ * For backward compatibility, the default implementation of this method
+ * behaves as follows. If this ClassLoader object is registered as
+ * parallel capable, the method returns a dedicated object associated
+ * with the specified class name. Otherwise, the method returns this
+ * ClassLoader object.
+ *
+ * @param className
+ * The name of the to-be-loaded class
+ *
+ * @return the lock for class loading operations
+ *
+ * @throws NullPointerException
+ * If registered as parallel capable and className is null
+ *
+ * @see #loadClass(String, boolean)
+ *
+ * @since 1.7
+ */
+ protected Object getClassLoadingLock(String className) {
+ Object lock = this;
+ return lock;
+ }
+
+ /**
+ * Finds the class with the specified binary name.
+ * This method should be overridden by class loader implementations that
+ * follow the delegation model for loading classes, and will be invoked by
+ * the {@link #loadClass loadClass} method after checking the
+ * parent class loader for the requested class. The default implementation
+ * throws a ClassNotFoundException.
+ *
+ * @param name
+ * The binary name of the class
+ *
+ * @return The resulting Class object
+ *
+ * @throws ClassNotFoundException
+ * If the class could not be found
+ *
+ * @since 1.2
+ */
+ protected Class> findClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException(name);
+ }
+
+ /**
+ * Converts an array of bytes into an instance of class Class.
+ * Before the Class can be used it must be resolved. This method
+ * is deprecated in favor of the version that takes a binary name as its first argument, and is more secure.
+ *
+ * @param b
+ * The bytes that make up the class data. The bytes in positions
+ * off through off+len-1 should have the format
+ * of a valid class file as defined by
+ * The Java™ Virtual Machine Specification.
+ *
+ * @param off
+ * The start offset in b of the class data
+ *
+ * @param len
+ * The length of the class data
+ *
+ * @return The Class object that was created from the specified
+ * class data
+ *
+ * @throws ClassFormatError
+ * If the data did not contain a valid class
+ *
+ * @throws IndexOutOfBoundsException
+ * If either off or len is negative, or if
+ * off+len is greater than b.length.
+ *
+ * @throws SecurityException
+ * If an attempt is made to add this class to a package that
+ * contains classes that were signed by a different set of
+ * certificates than this class, or if an attempt is made
+ * to define a class in a package with a fully-qualified name
+ * that starts with "{@code java.}".
+ *
+ * @see #loadClass(String, boolean)
+ * @see #resolveClass(Class)
+ *
+ * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
+ * defineClass(String, byte[], int, int)}
+ */
+ @Deprecated
+ protected final Class> defineClass(byte[] b, int off, int len)
+ throws ClassFormatError
+ {
+ throw new SecurityException();
+ }
+
+ /**
+ * Converts an array of bytes into an instance of class Class.
+ * Before the Class can be used it must be resolved.
+ *
+ *
This method assigns a default {@link java.security.ProtectionDomain
+ * ProtectionDomain} to the newly defined class. The
+ * ProtectionDomain is effectively granted the same set of
+ * permissions returned when {@link
+ * java.security.Policy#getPermissions(java.security.CodeSource)
+ * Policy.getPolicy().getPermissions(new CodeSource(null, null))}
+ * is invoked. The default domain is created on the first invocation of
+ * {@link #defineClass(String, byte[], int, int) defineClass},
+ * and re-used on subsequent invocations.
+ *
+ *
To assign a specific ProtectionDomain to the class, use
+ * the {@link #defineClass(String, byte[], int, int,
+ * java.security.ProtectionDomain) defineClass} method that takes a
+ * ProtectionDomain as one of its arguments.
+ *
+ * @param name
+ * The expected binary name of the class, or
+ * null if not known
+ *
+ * @param b
+ * The bytes that make up the class data. The bytes in positions
+ * off through off+len-1 should have the format
+ * of a valid class file as defined by
+ * The Java™ Virtual Machine Specification.
+ *
+ * @param off
+ * The start offset in b of the class data
+ *
+ * @param len
+ * The length of the class data
+ *
+ * @return The Class object that was created from the specified
+ * class data.
+ *
+ * @throws ClassFormatError
+ * If the data did not contain a valid class
+ *
+ * @throws IndexOutOfBoundsException
+ * If either off or len is negative, or if
+ * off+len is greater than b.length.
+ *
+ * @throws SecurityException
+ * If an attempt is made to add this class to a package that
+ * contains classes that were signed by a different set of
+ * certificates than this class (which is unsigned), or if
+ * name begins with "java.".
+ *
+ * @see #loadClass(String, boolean)
+ * @see #resolveClass(Class)
+ * @see java.security.CodeSource
+ * @see java.security.SecureClassLoader
+ *
+ * @since 1.1
+ */
+ protected final Class> defineClass(String name, byte[] b, int off, int len)
+ throws ClassFormatError
+ {
+ throw new SecurityException();
+ }
+
+ /**
+ * Links the specified class. This (misleadingly named) method may be
+ * used by a class loader to link a class. If the class c has
+ * already been linked, then this method simply returns. Otherwise, the
+ * class is linked as described in the "Execution" chapter of
+ * The Java™ Language Specification.
+ *
+ *
+ * @param c
+ * The class to link
+ *
+ * @throws NullPointerException
+ * If c is null.
+ *
+ * @see #defineClass(String, byte[], int, int)
+ */
+ protected final void resolveClass(Class> c) {
+ resolveClass0(c);
+ }
+
+ private native void resolveClass0(Class c);
+
+
+ /**
+ * Returns the class with the given binary name if this
+ * loader has been recorded by the Java virtual machine as an initiating
+ * loader of a class with that binary name. Otherwise
+ * null is returned.
+ *
+ * @param name
+ * The binary name of the class
+ *
+ * @return The Class object, or null if the class has
+ * not been loaded
+ *
+ * @since 1.1
+ */
+ protected final Class> findLoadedClass(String name) {
+ if (!checkName(name))
+ return null;
+ return findLoadedClass0(name);
+ }
+
+ private native final Class findLoadedClass0(String name);
+
+ /**
+ * Sets the signers of a class. This should be invoked after defining a
+ * class.
+ *
+ * @param c
+ * The Class object
+ *
+ * @param signers
+ * The signers for the class
+ *
+ * @since 1.1
+ */
+ protected final void setSigners(Class> c, Object[] signers) {
+ //c.setSigners(signers);
+ throw new UnsupportedOperationException();
+ }
+
+
+ // -- Resource --
+
+ /**
+ * Finds the resource with the given name. A resource is some data
+ * (images, audio, text, etc) that can be accessed by class code in a way
+ * that is independent of the location of the code.
+ *
+ *
The name of a resource is a '/'-separated path name that
+ * identifies the resource.
+ *
+ *
This method will first search the parent class loader for the
+ * resource; if the parent is null the path of the class loader
+ * built-in to the virtual machine is searched. That failing, this method
+ * will invoke {@link #findResource(String)} to find the resource.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return A URL object for reading the resource, or
+ * null if the resource could not be found or the invoker
+ * doesn't have adequate privileges to get the resource.
+ *
+ * @since 1.1
+ */
+ public URL getResource(String name) {
+ URL url;
+ if (parent != null) {
+ url = parent.getResource(name);
+ } else {
+ url = getBootstrapResource(name);
+ }
+ if (url == null) {
+ url = findResource(name);
+ }
+ return url;
+ }
+
+ /**
+ * Finds all the resources with the given name. A resource is some data
+ * (images, audio, text, etc) that can be accessed by class code in a way
+ * that is independent of the location of the code.
+ *
+ *
The name of a resource is a /-separated path name that
+ * identifies the resource.
+ *
+ *
The search order is described in the documentation for {@link
+ * #getResource(String)}.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An enumeration of {@link java.net.URL URL} objects for
+ * the resource. If no resources could be found, the enumeration
+ * will be empty. Resources that the class loader doesn't have
+ * access to will not be in the enumeration.
+ *
+ * @throws IOException
+ * If I/O errors occur
+ *
+ * @see #findResources(String)
+ *
+ * @since 1.2
+ */
+ public Enumeration getResources(String name) throws IOException {
+ Enumeration[] tmp = new Enumeration[2];
+ if (parent != null) {
+ tmp[0] = parent.getResources(name);
+ } else {
+ tmp[0] = getBootstrapResources(name);
+ }
+ tmp[1] = findResources(name);
+
+ return new CompoundEnumeration(tmp);
+ }
+
+ /**
+ * Finds the resource with the given name. Class loader implementations
+ * should override this method to specify where to find resources.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return A URL object for reading the resource, or
+ * null if the resource could not be found
+ *
+ * @since 1.2
+ */
+ protected URL findResource(String name) {
+ return null;
+ }
+
+ /**
+ * Returns an enumeration of {@link java.net.URL URL} objects
+ * representing all the resources with the given name. Class loader
+ * implementations should override this method to specify where to load
+ * resources from.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An enumeration of {@link java.net.URL URL} objects for
+ * the resources
+ *
+ * @throws IOException
+ * If I/O errors occur
+ *
+ * @since 1.2
+ */
+ protected Enumeration findResources(String name) throws IOException {
+ return new CompoundEnumeration(new Enumeration[0]);
+ }
+
+ // index 0: java.lang.ClassLoader.class
+ // index 1: the immediate caller of index 0.
+ // index 2: the immediate caller of index 1.
+ private static native Class extends ClassLoader> getCaller(int index);
+
+ /**
+ * Registers the caller as parallel capable.
+ * The registration succeeds if and only if all of the following
+ * conditions are met:
+ * 1. no instance of the caller has been created
+ * 2. all of the super classes (except class Object) of the caller are
+ * registered as parallel capable
+ * Note that once a class loader is registered as parallel capable, there
+ * is no way to change it back.
+ *
+ * @return true if the caller is successfully registered as
+ * parallel capable and false if otherwise.
+ *
+ * @since 1.7
+ */
+// protected static boolean registerAsParallelCapable() {
+// return false;
+// }
+
+ /**
+ * Find a resource of the specified name from the search path used to load
+ * classes. This method locates the resource through the system class
+ * loader (see {@link #getSystemClassLoader()}).
+ *
+ * @param name
+ * The resource name
+ *
+ * @return A {@link java.net.URL URL} object for reading the
+ * resource, or null if the resource could not be found
+ *
+ * @since 1.1
+ */
+ public static URL getSystemResource(String name) {
+ ClassLoader system = getSystemClassLoader();
+ if (system == null) {
+ return getBootstrapResource(name);
+ }
+ return system.getResource(name);
+ }
+
+ /**
+ * Finds all resources of the specified name from the search path used to
+ * load classes. The resources thus found are returned as an
+ * {@link java.util.Enumeration Enumeration} of {@link
+ * java.net.URL URL} objects.
+ *
+ *
The search order is described in the documentation for {@link
+ * #getSystemResource(String)}.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An enumeration of resource {@link java.net.URL URL}
+ * objects
+ *
+ * @throws IOException
+ * If I/O errors occur
+
+ * @since 1.2
+ */
+ public static Enumeration getSystemResources(String name)
+ throws IOException
+ {
+ ClassLoader system = getSystemClassLoader();
+ if (system == null) {
+ return getBootstrapResources(name);
+ }
+ return system.getResources(name);
+ }
+
+
+
+ /**
+ * Returns an input stream for reading the specified resource.
+ *
+ *
The search order is described in the documentation for {@link
+ * #getResource(String)}.
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An input stream for reading the resource, or null
+ * if the resource could not be found
+ *
+ * @since 1.1
+ */
+ public InputStream getResourceAsStream(String name) {
+ URL url = getResource(name);
+ try {
+ return url != null ? url.openStream() : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Open for reading, a resource of the specified name from the search path
+ * used to load classes. This method locates the resource through the
+ * system class loader (see {@link #getSystemClassLoader()}).
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An input stream for reading the resource, or null
+ * if the resource could not be found
+ *
+ * @since 1.1
+ */
+ public static InputStream getSystemResourceAsStream(String name) {
+ URL url = getSystemResource(name);
+ try {
+ return url != null ? url.openStream() : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+
+ // -- Hierarchy --
+
+ /**
+ * Returns the parent class loader for delegation. Some implementations may
+ * use null to represent the bootstrap class loader. This method
+ * will return null in such implementations if this class loader's
+ * parent is the bootstrap class loader.
+ *
+ *
If a security manager is present, and the invoker's class loader is
+ * not null and is not an ancestor of this class loader, then this
+ * method invokes the security manager's {@link
+ * SecurityManager#checkPermission(java.security.Permission)
+ * checkPermission} method with a {@link
+ * RuntimePermission#RuntimePermission(String)
+ * RuntimePermission("getClassLoader")} permission to verify
+ * access to the parent class loader is permitted. If not, a
+ * SecurityException will be thrown.
+ *
+ * @return The parent ClassLoader
+ *
+ * @throws SecurityException
+ * If a security manager exists and its checkPermission
+ * method doesn't allow access to this class loader's parent class
+ * loader.
+ *
+ * @since 1.2
+ */
+ public final ClassLoader getParent() {
+ throw new SecurityException();
+ }
+
+ /**
+ * Returns the system class loader for delegation. This is the default
+ * delegation parent for new ClassLoader instances, and is
+ * typically the class loader used to start the application.
+ *
+ *
This method is first invoked early in the runtime's startup
+ * sequence, at which point it creates the system class loader and sets it
+ * as the context class loader of the invoking Thread.
+ *
+ *
The default system class loader is an implementation-dependent
+ * instance of this class.
+ *
+ *
If the system property "java.system.class.loader" is defined
+ * when this method is first invoked then the value of that property is
+ * taken to be the name of a class that will be returned as the system
+ * class loader. The class is loaded using the default system class loader
+ * and must define a public constructor that takes a single parameter of
+ * type ClassLoader which is used as the delegation parent. An
+ * instance is then created using this constructor with the default system
+ * class loader as the parameter. The resulting class loader is defined
+ * to be the system class loader.
+ *
+ *
If a security manager is present, and the invoker's class loader is
+ * not null and the invoker's class loader is not the same as or
+ * an ancestor of the system class loader, then this method invokes the
+ * security manager's {@link
+ * SecurityManager#checkPermission(java.security.Permission)
+ * checkPermission} method with a {@link
+ * RuntimePermission#RuntimePermission(String)
+ * RuntimePermission("getClassLoader")} permission to verify
+ * access to the system class loader. If not, a
+ * SecurityException will be thrown.
+ *
+ * @return The system ClassLoader for delegation, or
+ * null if none
+ *
+ * @throws SecurityException
+ * If a security manager exists and its checkPermission
+ * method doesn't allow access to the system class loader.
+ *
+ * @throws IllegalStateException
+ * If invoked recursively during the construction of the class
+ * loader specified by the "java.system.class.loader"
+ * property.
+ *
+ * @throws Error
+ * If the system property "java.system.class.loader"
+ * is defined but the named class could not be loaded, the
+ * provider class does not define the required constructor, or an
+ * exception is thrown by that constructor when it is invoked. The
+ * underlying cause of the error can be retrieved via the
+ * {@link Throwable#getCause()} method.
+ *
+ * @revised 1.4
+ */
+ public static ClassLoader getSystemClassLoader() {
+ throw new SecurityException();
+ }
+
+ // Returns true if the specified class loader can be found in this class
+ // loader's delegation chain.
+ boolean isAncestor(ClassLoader cl) {
+ ClassLoader acl = this;
+ do {
+ acl = acl.parent;
+ if (cl == acl) {
+ return true;
+ }
+ } while (acl != null);
+ return false;
+ }
+
+ private boolean checkName(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ private Class findBootstrapClassOrNull(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static URL getBootstrapResource(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static Enumeration getBootstrapResources(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static class CompoundEnumeration implements Enumeration {
+ private URL next;
+ private int index;
+ private final Enumeration[] arr;
+
+ public CompoundEnumeration(Enumeration[] arr) {
+ this.arr = arr;
+ this.index = 0;
+ }
+
+ public boolean hasMoreElements() {
+ if (next == null) {
+ if (arr[index].hasMoreElements()) {
+ next = (URL) arr[index].nextElement();
+ } else {
+ if (index < arr.length) {
+ index++;
+ return hasMoreElements();
+ }
+ }
+ }
+ return next != null;
+ }
+
+ public URL nextElement() {
+ if (!hasMoreElements()) {
+ throw new NoSuchElementException();
+ }
+ URL r = next;
+ next = null;
+ return r;
+ }
+
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Double.java
--- a/emul/src/main/java/java/lang/Double.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Double.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The {@code Double} class wraps a value of the primitive type
* {@code double} in an object. An object of type
@@ -188,6 +190,9 @@
* @param d the {@code double} to be converted.
* @return a string representation of the argument.
*/
+ @JavaScriptBody(args="d", body="var r = d.toString();"
+ + "if (r.indexOf('.') === -1) r = r + '.0';"
+ + "return r;")
public static String toString(double d) {
throw new UnsupportedOperationException();
}
@@ -497,6 +502,7 @@
* @throws NumberFormatException if the string does not contain a
* parsable number.
*/
+ @JavaScriptBody(args="s", body="return parseFloat(s);")
public static Double valueOf(String s) throws NumberFormatException {
throw new UnsupportedOperationException();
// return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
@@ -534,6 +540,7 @@
* @see java.lang.Double#valueOf(String)
* @since 1.2
*/
+ @JavaScriptBody(args="s", body="return parseFloat(s);")
public static double parseDouble(String s) throws NumberFormatException {
throw new UnsupportedOperationException();
// return FloatingDecimal.readJavaFormatString(s).doubleValue();
@@ -767,8 +774,7 @@
*/
public boolean equals(Object obj) {
return (obj instanceof Double)
- && (doubleToLongBits(((Double)obj).value) ==
- doubleToLongBits(value));
+ && (((Double)obj).value) == value;
}
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Float.java
--- a/emul/src/main/java/java/lang/Float.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Float.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The {@code Float} class wraps a value of primitive type
* {@code float} in an object. An object of type
@@ -191,8 +193,7 @@
* @return a string representation of the argument.
*/
public static String toString(float f) {
- throw new UnsupportedOperationException();
-// return new FloatingDecimal(f).toJavaFormatString();
+ return Double.toString(f);
}
/**
@@ -816,6 +817,18 @@
* @return the {@code float} floating-point value with the same bit
* pattern.
*/
+ @JavaScriptBody(args = "bits",
+ body =
+ "if (bits === 0x7f800000) return Number.POSITIVE_INFINITY;\n"
+ + "if (bits === 0xff800000) return Number.NEGATIVE_INFINITY;\n"
+ + "if (bits >= 0x7f800001 && bits <= 0xffffffff) return Number.NaN;\n"
+ + "var s = ((bits >> 31) == 0) ? 1 : -1;\n"
+ + "var e = ((bits >> 23) & 0xff);\n"
+ + "var m = (e == 0) ?\n"
+ + " (bits & 0x7fffff) << 1 :\n"
+ + " (bits & 0x7fffff) | 0x800000;\n"
+ + "return s * m * Math.pow(2.0, e - 150);\n"
+ )
public static native float intBitsToFloat(int bits);
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Integer.java
--- a/emul/src/main/java/java/lang/Integer.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Integer.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The {@code Integer} class wraps a value of the primitive type
* {@code int} in an object. An object of type {@code Integer}
@@ -322,13 +324,14 @@
* @param i an integer to be converted.
* @return a string representation of the argument in base 10.
*/
+ @JavaScriptBody(args = "i", body = "return i.toString();")
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
- return new String(0, size, buf);
+ return new String(buf, 0, size);
}
/**
@@ -439,6 +442,7 @@
* @exception NumberFormatException if the {@code String}
* does not contain a parsable {@code int}.
*/
+ @JavaScriptBody(args={"s", "radix"}, body="return parseInt(s,radix);")
public static int parseInt(String s, int radix)
throws NumberFormatException
{
@@ -600,7 +604,7 @@
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
- String.getProperty("java.lang.Integer.IntegerCache.high");
+ AbstractStringBuilder.getProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
@@ -882,7 +886,7 @@
public static Integer getInteger(String nm, Integer val) {
String v = null;
try {
- v = String.getProperty(nm);
+ v = AbstractStringBuilder.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/LinkageError.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/LinkageError.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Subclasses of {@code LinkageError} indicate that a class has
+ * some dependency on another class; however, the latter class has
+ * incompatibly changed after the compilation of the former class.
+ *
+ *
+ * @author Frank Yellin
+ * @since JDK1.0
+ */
+public
+class LinkageError extends Error {
+ private static final long serialVersionUID = 3579600108157160122L;
+
+ /**
+ * Constructs a {@code LinkageError} with no detail message.
+ */
+ public LinkageError() {
+ super();
+ }
+
+ /**
+ * Constructs a {@code LinkageError} with the specified detail
+ * message.
+ *
+ * @param s the detail message.
+ */
+ public LinkageError(String s) {
+ super(s);
+ }
+
+ /**
+ * Constructs a {@code LinkageError} with the specified detail
+ * message and cause.
+ *
+ * @param s the detail message.
+ * @param cause the cause, may be {@code null}
+ * @since 1.7
+ */
+ public LinkageError(String s, Throwable cause) {
+ super(s, cause);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Long.java
--- a/emul/src/main/java/java/lang/Long.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Long.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The {@code Long} class wraps a value of the primitive type {@code
* long} in an object. An object of type {@code Long} contains a
@@ -260,13 +262,14 @@
* @param i a {@code long} to be converted.
* @return a string representation of the argument in base 10.
*/
+ @JavaScriptBody(args = "i", body = "return i.toString();")
public static String toString(long i) {
if (i == Long.MIN_VALUE)
return "-9223372036854775808";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
- return new String(0, size, buf);
+ return new String(buf, 0, size);
}
/**
@@ -923,7 +926,7 @@
public static Long getLong(String nm, Long val) {
String v = null;
try {
- v = String.getProperty(nm);
+ v = AbstractStringBuilder.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Math.java
--- a/emul/src/main/java/java/lang/Math.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Math.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
/**
* The class {@code Math} contains methods for performing basic
@@ -116,8 +118,9 @@
* @param a an angle, in radians.
* @return the sine of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.sin(a);")
public static double sin(double a) {
- return StrictMath.sin(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -131,8 +134,9 @@
* @param a an angle, in radians.
* @return the cosine of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.cos(a);")
public static double cos(double a) {
- return StrictMath.cos(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -148,8 +152,9 @@
* @param a an angle, in radians.
* @return the tangent of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.tan(a);")
public static double tan(double a) {
- return StrictMath.tan(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -166,8 +171,9 @@
* @param a the value whose arc sine is to be returned.
* @return the arc sine of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.asin(a);")
public static double asin(double a) {
- return StrictMath.asin(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -182,8 +188,9 @@
* @param a the value whose arc cosine is to be returned.
* @return the arc cosine of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.acos(a);")
public static double acos(double a) {
- return StrictMath.acos(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -199,8 +206,9 @@
* @param a the value whose arc tangent is to be returned.
* @return the arc tangent of the argument.
*/
+ @JavaScriptBody(args="a", body="return Math.atan(a);")
public static double atan(double a) {
- return StrictMath.atan(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -249,8 +257,9 @@
* @return the value e{@code a},
* where e is the base of the natural logarithms.
*/
+ @JavaScriptBody(args="a", body="return Math.exp(a);")
public static double exp(double a) {
- return StrictMath.exp(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -270,8 +279,9 @@
* @return the value ln {@code a}, the natural logarithm of
* {@code a}.
*/
+ @JavaScriptBody(args="a", body="return Math.log(a);")
public static double log(double a) {
- return StrictMath.log(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -295,8 +305,9 @@
* @return the base 10 logarithm of {@code a}.
* @since 1.5
*/
+ @JavaScriptBody(args="a", body="return Math.log(a) / Math.LN10;")
public static double log10(double a) {
- return StrictMath.log10(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -316,69 +327,9 @@
* @return the positive square root of {@code a}.
* If the argument is NaN or less than zero, the result is NaN.
*/
+ @JavaScriptBody(args="a", body="return Math.sqrt(a);")
public static double sqrt(double a) {
- return StrictMath.sqrt(a); // default impl. delegates to StrictMath
- // Note that hardware sqrt instructions
- // frequently can be directly used by JITs
- // and should be much faster than doing
- // Math.sqrt in software.
- }
-
-
- /**
- * Returns the cube root of a {@code double} value. For
- * positive finite {@code x}, {@code cbrt(-x) ==
- * -cbrt(x)}; that is, the cube root of a negative value is
- * the negative of the cube root of that value's magnitude.
- *
- * Special cases:
- *
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is an infinity
- * with the same sign as the argument.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- *
The computed result must be within 1 ulp of the exact result.
- *
- * @param a a value.
- * @return the cube root of {@code a}.
- * @since 1.5
- */
- public static double cbrt(double a) {
- return StrictMath.cbrt(a);
- }
-
- /**
- * Computes the remainder operation on two arguments as prescribed
- * by the IEEE 754 standard.
- * The remainder value is mathematically equal to
- * f1 - f2 × n,
- * where n is the mathematical integer closest to the exact
- * mathematical value of the quotient {@code f1/f2}, and if two
- * mathematical integers are equally close to {@code f1/f2},
- * then n is the integer that is even. If the remainder is
- * zero, its sign is the same as the sign of the first argument.
- * Special cases:
- *
If either argument is NaN, or the first argument is infinite,
- * or the second argument is positive zero or negative zero, then the
- * result is NaN.
- *
If the first argument is finite and the second argument is
- * infinite, then the result is the same as the first argument.
- *
- * @param f1 the dividend.
- * @param f2 the divisor.
- * @return the remainder when {@code f1} is divided by
- * {@code f2}.
- */
- public static double IEEEremainder(double f1, double f2) {
- return StrictMath.IEEEremainder(f1, f2); // delegate to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -400,8 +351,9 @@
* floating-point value that is greater than or equal to
* the argument and is equal to a mathematical integer.
*/
+ @JavaScriptBody(args="a", body="return Math.ceil(a);")
public static double ceil(double a) {
- return StrictMath.ceil(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -419,27 +371,9 @@
* floating-point value that less than or equal to the argument
* and is equal to a mathematical integer.
*/
+ @JavaScriptBody(args="a", body="return Math.floor(a);")
public static double floor(double a) {
- return StrictMath.floor(a); // default impl. delegates to StrictMath
- }
-
- /**
- * Returns the {@code double} value that is closest in value
- * to the argument and is equal to a mathematical integer. If two
- * {@code double} values that are mathematical integers are
- * equally close, the result is the integer value that is
- * even. Special cases:
- *
If the argument value is already equal to a mathematical
- * integer, then the result is the same as the argument.
- *
If the argument is NaN or an infinity or positive zero or negative
- * zero, then the result is the same as the argument.
- *
- * @param a a {@code double} value.
- * @return the closest floating-point value to {@code a} that is
- * equal to a mathematical integer.
- */
- public static double rint(double a) {
- return StrictMath.rint(a); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -494,8 +428,9 @@
* in polar coordinates that corresponds to the point
* (x, y) in Cartesian coordinates.
*/
+ @JavaScriptBody(args={"y", "x"}, body="return Math.atan2(y, x);")
public static double atan2(double y, double x) {
- return StrictMath.atan2(y, x); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -621,8 +556,9 @@
* @param b the exponent.
* @return the value {@code a}{@code b}.
*/
+ @JavaScriptBody(args={"a", "b"}, body="return Math.pow(a, b);")
public static double pow(double a, double b) {
- return StrictMath.pow(a, b); // default impl. delegates to StrictMath
+ throw new UnsupportedOperationException();
}
/**
@@ -645,11 +581,9 @@
* @see java.lang.Integer#MAX_VALUE
* @see java.lang.Integer#MIN_VALUE
*/
+ @JavaScriptBody(args="a", body="return Math.round(a);")
public static int round(float a) {
- if (a != 0x1.fffffep-2f) // greatest float value less than 0.5
- return (int)floor(a + 0.5f);
- else
- return 0;
+ throw new UnsupportedOperationException();
}
/**
@@ -672,11 +606,9 @@
* @see java.lang.Long#MAX_VALUE
* @see java.lang.Long#MIN_VALUE
*/
+ @JavaScriptBody(args="a", body="return Math.round(a);")
public static long round(double a) {
- if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5
- return (long)floor(a + 0.5d);
- else
- return 0;
+ throw new UnsupportedOperationException();
}
// private static Random randomNumberGenerator;
@@ -709,6 +641,7 @@
* to {@code 0.0} and less than {@code 1.0}.
* @see Random#nextDouble()
*/
+ @JavaScriptBody(args={}, body="return Math.random();")
public static double random() {
throw new UnsupportedOperationException();
}
@@ -813,9 +746,6 @@
return (a >= b) ? a : b;
}
- private static long negativeZeroFloatBits = Float.floatToIntBits(-0.0f);
- private static long negativeZeroDoubleBits = Double.doubleToLongBits(-0.0d);
-
/**
* Returns the greater of two {@code float} values. That is,
* the result is the argument closer to positive infinity. If the
@@ -830,13 +760,11 @@
* @param b another argument.
* @return the larger of {@code a} and {@code b}.
*/
+ @JavaScriptBody(args={"a", "b"},
+ body="return Math.max(a,b);"
+ )
public static float max(float a, float b) {
- if (a != a) return a; // a is NaN
- if ((a == 0.0f) && (b == 0.0f)
- && (Float.floatToIntBits(a) == negativeZeroFloatBits)) {
- return b;
- }
- return (a >= b) ? a : b;
+ throw new UnsupportedOperationException();
}
/**
@@ -853,13 +781,11 @@
* @param b another argument.
* @return the larger of {@code a} and {@code b}.
*/
+ @JavaScriptBody(args={"a", "b"},
+ body="return Math.max(a,b);"
+ )
public static double max(double a, double b) {
- if (a != a) return a; // a is NaN
- if ((a == 0.0d) && (b == 0.0d)
- && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)) {
- return b;
- }
- return (a >= b) ? a : b;
+ throw new UnsupportedOperationException();
}
/**
@@ -904,13 +830,11 @@
* @param b another argument.
* @return the smaller of {@code a} and {@code b}.
*/
+ @JavaScriptBody(args={"a", "b"},
+ body="return Math.min(a,b);"
+ )
public static float min(float a, float b) {
- if (a != a) return a; // a is NaN
- if ((a == 0.0f) && (b == 0.0f)
- && (Float.floatToIntBits(b) == negativeZeroFloatBits)) {
- return b;
- }
- return (a <= b) ? a : b;
+ throw new UnsupportedOperationException();
}
/**
@@ -927,13 +851,11 @@
* @param b another argument.
* @return the smaller of {@code a} and {@code b}.
*/
+ @JavaScriptBody(args={"a", "b"},
+ body="return Math.min(a,b);"
+ )
public static double min(double a, double b) {
- if (a != a) return a; // a is NaN
- if ((a == 0.0d) && (b == 0.0d)
- && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) {
- return b;
- }
- return (a <= b) ? a : b;
+ throw new UnsupportedOperationException();
}
/**
@@ -1033,207 +955,6 @@
// }
/**
- * Returns the hyperbolic sine of a {@code double} value.
- * The hyperbolic sine of x is defined to be
- * (ex - e-x)/2
- * where e is {@linkplain Math#E Euler's number}.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is an infinity
- * with the same sign as the argument.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- *
The computed result must be within 2.5 ulps of the exact result.
- *
- * @param x The number whose hyperbolic sine is to be returned.
- * @return The hyperbolic sine of {@code x}.
- * @since 1.5
- */
- public static double sinh(double x) {
- return StrictMath.sinh(x);
- }
-
- /**
- * Returns the hyperbolic cosine of a {@code double} value.
- * The hyperbolic cosine of x is defined to be
- * (ex + e-x)/2
- * where e is {@linkplain Math#E Euler's number}.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is positive
- * infinity.
- *
- *
If the argument is zero, then the result is {@code 1.0}.
- *
- *
- *
- *
The computed result must be within 2.5 ulps of the exact result.
- *
- * @param x The number whose hyperbolic cosine is to be returned.
- * @return The hyperbolic cosine of {@code x}.
- * @since 1.5
- */
- public static double cosh(double x) {
- return StrictMath.cosh(x);
- }
-
- /**
- * Returns the hyperbolic tangent of a {@code double} value.
- * The hyperbolic tangent of x is defined to be
- * (ex - e-x)/(ex + e-x),
- * in other words, {@linkplain Math#sinh
- * sinh(x)}/{@linkplain Math#cosh cosh(x)}. Note
- * that the absolute value of the exact tanh is always less than
- * 1.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
If the argument is positive infinity, then the result is
- * {@code +1.0}.
- *
- *
If the argument is negative infinity, then the result is
- * {@code -1.0}.
- *
- *
- *
- *
The computed result must be within 2.5 ulps of the exact result.
- * The result of {@code tanh} for any finite input must have
- * an absolute value less than or equal to 1. Note that once the
- * exact result of tanh is within 1/2 of an ulp of the limit value
- * of ±1, correctly signed ±{@code 1.0} should
- * be returned.
- *
- * @param x The number whose hyperbolic tangent is to be returned.
- * @return The hyperbolic tangent of {@code x}.
- * @since 1.5
- */
- public static double tanh(double x) {
- return StrictMath.tanh(x);
- }
-
- /**
- * Returns sqrt(x2 +y2)
- * without intermediate overflow or underflow.
- *
- *
Special cases:
- *
- *
- *
If either argument is infinite, then the result
- * is positive infinity.
- *
- *
If either argument is NaN and neither argument is infinite,
- * then the result is NaN.
- *
- *
- *
- *
The computed result must be within 1 ulp of the exact
- * result. If one parameter is held constant, the results must be
- * semi-monotonic in the other parameter.
- *
- * @param x a value
- * @param y a value
- * @return sqrt(x2 +y2)
- * without intermediate overflow or underflow
- * @since 1.5
- */
- public static double hypot(double x, double y) {
- return StrictMath.hypot(x, y);
- }
-
- /**
- * Returns ex -1. Note that for values of
- * x near 0, the exact sum of
- * {@code expm1(x)} + 1 is much closer to the true
- * result of ex than {@code exp(x)}.
- *
- *
Special cases:
- *
- *
If the argument is NaN, the result is NaN.
- *
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
- *
If the argument is negative infinity, then the result is
- * -1.0.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- *
The computed result must be within 1 ulp of the exact result.
- * Results must be semi-monotonic. The result of
- * {@code expm1} for any finite input must be greater than or
- * equal to {@code -1.0}. Note that once the exact result of
- * e{@code x} - 1 is within 1/2
- * ulp of the limit value -1, {@code -1.0} should be
- * returned.
- *
- * @param x the exponent to raise e to in the computation of
- * e{@code x} -1.
- * @return the value e{@code x} - 1.
- * @since 1.5
- */
- public static double expm1(double x) {
- return StrictMath.expm1(x);
- }
-
- /**
- * Returns the natural logarithm of the sum of the argument and 1.
- * Note that for small values {@code x}, the result of
- * {@code log1p(x)} is much closer to the true result of ln(1
- * + {@code x}) than the floating-point evaluation of
- * {@code log(1.0+x)}.
- *
- *
Special cases:
- *
- *
- *
- *
If the argument is NaN or less than -1, then the result is
- * NaN.
- *
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
- *
If the argument is negative one, then the result is
- * negative infinity.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- *
The computed result must be within 1 ulp of the exact result.
- * Results must be semi-monotonic.
- *
- * @param x a value
- * @return the value ln({@code x} + 1), the natural
- * log of {@code x} + 1
- * @since 1.5
- */
- public static double log1p(double x) {
- return StrictMath.log1p(x);
- }
-
- /**
* Returns the first floating-point argument with the sign of the
* second floating-point argument. Note that unlike the {@link
* StrictMath#copySign(double, double) StrictMath.copySign}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/NegativeArraySizeException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/NegativeArraySizeException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Thrown if an application tries to create an array with negative size.
+ *
+ * @author unascribed
+ * @since JDK1.0
+ */
+public
+class NegativeArraySizeException extends RuntimeException {
+ private static final long serialVersionUID = -8960118058596991861L;
+
+ /**
+ * Constructs a NegativeArraySizeException with no
+ * detail message.
+ */
+ public NegativeArraySizeException() {
+ super();
+ }
+
+ /**
+ * Constructs a NegativeArraySizeException with the
+ * specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public NegativeArraySizeException(String s) {
+ super(s);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/NoSuchMethodException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/NoSuchMethodException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Thrown when a particular method cannot be found.
+ *
+ * @author unascribed
+ * @since JDK1.0
+ */
+public
+class NoSuchMethodException extends ReflectiveOperationException {
+ private static final long serialVersionUID = 5034388446362600923L;
+
+ /**
+ * Constructs a NoSuchMethodException without a detail message.
+ */
+ public NoSuchMethodException() {
+ super();
+ }
+
+ /**
+ * Constructs a NoSuchMethodException with a detail message.
+ *
+ * @param s the detail message.
+ */
+ public NoSuchMethodException(String s) {
+ super(s);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Number.java
--- a/emul/src/main/java/java/lang/Number.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Number.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
+import org.apidesign.bck2brwsr.core.ExtraJavaScript;
+
/**
* The abstract class Number is the superclass of classes
* BigDecimal, BigInteger,
@@ -46,6 +48,10 @@
* @see java.lang.Short
* @since JDK1.0
*/
+@ExtraJavaScript(
+ resource="/org/apidesign/vm4brwsr/emul/java_lang_Number.js",
+ processByteCode=true
+)
public abstract class Number implements java.io.Serializable {
/**
* Returns the value of the specified number as an int.
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Object.java
--- a/emul/src/main/java/java/lang/Object.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Object.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,10 @@
package java.lang;
+import java.lang.reflect.Array;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
+
/**
* Class {@code Object} is the root of the class hierarchy.
* Every class has {@code Object} as a superclass. All objects,
@@ -34,9 +38,16 @@
* @see java.lang.Class
* @since JDK1.0
*/
+@JavaScriptPrototype(container = "Object.prototype", prototype = "new Object")
public class Object {
- private static native void registerNatives();
+ private static void registerNatives() {
+ try {
+ Array.get(null, 0);
+ } catch (Throwable ex) {
+ // ignore
+ }
+ }
static {
registerNatives();
}
@@ -61,6 +72,7 @@
* @see Class Literals, section 15.8.2 of
* The Java™ Language Specification.
*/
+ @JavaScriptBody(args={}, body="return this.constructor.$class;")
public final native Class> getClass();
/**
@@ -98,8 +110,16 @@
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
+ @JavaScriptBody(args = {}, body =
+ "if (this.$hashCode) return this.$hashCode;\n"
+ + "var h = this.computeHashCode__I();\n"
+ + "return this.$hashCode = h & h;"
+ )
public native int hashCode();
+ @JavaScriptBody(args = {}, body = "Math.random() * Math.pow(2, 32);")
+ native int computeHashCode();
+
/**
* Indicates whether some other object is "equal to" this one.
*
@@ -210,7 +230,28 @@
* be cloned.
* @see java.lang.Cloneable
*/
- protected native Object clone() throws CloneNotSupportedException;
+ protected Object clone() throws CloneNotSupportedException {
+ Object ret = clone(this);
+ if (ret == null) {
+ throw new CloneNotSupportedException(getClass().getName());
+ }
+ return ret;
+ }
+
+ @JavaScriptBody(args = "self", body =
+ "\nif (!self.$instOf_java_lang_Cloneable) {"
+ + "\n return null;"
+ + "\n} else {"
+ + "\n var clone = self.constructor(true);"
+ + "\n var props = Object.getOwnPropertyNames(self);"
+ + "\n for (var i = 0; i < props.length; i++) {"
+ + "\n var p = props[i];"
+ + "\n clone[p] = self[p];"
+ + "\n };"
+ + "\n return clone;"
+ + "\n}"
+ )
+ private static native Object clone(Object self) throws CloneNotSupportedException;
/**
* Returns a string representation of the object. In general, the
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Runnable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/Runnable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * The Runnable interface should be implemented by any
+ * class whose instances are intended to be executed by a thread. The
+ * class must define a method of no arguments called run.
+ *
+ * This interface is designed to provide a common protocol for objects that
+ * wish to execute code while they are active. For example,
+ * Runnable is implemented by class Thread.
+ * Being active simply means that a thread has been started and has not
+ * yet been stopped.
+ *
+ * In addition, Runnable provides the means for a class to be
+ * active while not subclassing Thread. A class that implements
+ * Runnable can run without subclassing Thread
+ * by instantiating a Thread instance and passing itself in
+ * as the target. In most cases, the Runnable interface should
+ * be used if you are only planning to override the run()
+ * method and no other Thread methods.
+ * This is important because classes should not be subclassed
+ * unless the programmer intends on modifying or enhancing the fundamental
+ * behavior of the class.
+ *
+ * @author Arthur van Hoff
+ * @see java.lang.Thread
+ * @see java.util.concurrent.Callable
+ * @since JDK1.0
+ */
+public
+interface Runnable {
+ /**
+ * When an object implementing interface Runnable is used
+ * to create a thread, starting the thread causes the object's
+ * run method to be called in that separately executing
+ * thread.
+ *
+ * The general contract of the method run is that it may
+ * take any action whatsoever.
+ *
+ * @see java.lang.Thread#run()
+ */
+ public abstract void run();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/SecurityException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/SecurityException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang;
+
+/**
+ * Thrown by the security manager to indicate a security violation.
+ *
+ * @author unascribed
+ * @see java.lang.SecurityManager
+ * @since JDK1.0
+ */
+public class SecurityException extends RuntimeException {
+
+ private static final long serialVersionUID = 6878364983674394167L;
+
+ /**
+ * Constructs a SecurityException with no detail message.
+ */
+ public SecurityException() {
+ super();
+ }
+
+ /**
+ * Constructs a SecurityException with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public SecurityException(String s) {
+ super(s);
+ }
+
+ /**
+ * Creates a SecurityException with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public SecurityException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a SecurityException with the specified cause
+ * and a detail message of (cause==null ? null : cause.toString())
+ * (which typically contains the class and detail message of
+ * cause).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public SecurityException(Throwable cause) {
+ super(cause);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StrictMath.java
--- a/emul/src/main/java/java/lang/StrictMath.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1457 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-/**
- * The class {@code StrictMath} contains methods for performing basic
- * numeric operations such as the elementary exponential, logarithm,
- * square root, and trigonometric functions.
- *
- *
To help ensure portability of Java programs, the definitions of
- * some of the numeric functions in this package require that they
- * produce the same results as certain published algorithms. These
- * algorithms are available from the well-known network library
- * {@code netlib} as the package "Freely Distributable Math
- * Library," {@code fdlibm}. These
- * algorithms, which are written in the C programming language, are
- * then to be understood as executed with all floating-point
- * operations following the rules of Java floating-point arithmetic.
- *
- *
The Java math library is defined with respect to
- * {@code fdlibm} version 5.3. Where {@code fdlibm} provides
- * more than one definition for a function (such as
- * {@code acos}), use the "IEEE 754 core function" version
- * (residing in a file whose name begins with the letter
- * {@code e}). The methods which require {@code fdlibm}
- * semantics are {@code sin}, {@code cos}, {@code tan},
- * {@code asin}, {@code acos}, {@code atan},
- * {@code exp}, {@code log}, {@code log10},
- * {@code cbrt}, {@code atan2}, {@code pow},
- * {@code sinh}, {@code cosh}, {@code tanh},
- * {@code hypot}, {@code expm1}, and {@code log1p}.
- *
- * @author unascribed
- * @author Joseph D. Darcy
- * @since 1.3
- */
-
-public final class StrictMath {
-
- /**
- * Don't let anyone instantiate this class.
- */
- private StrictMath() {}
-
- /**
- * The {@code double} value that is closer than any other to
- * e, the base of the natural logarithms.
- */
- public static final double E = 2.7182818284590452354;
-
- /**
- * The {@code double} value that is closer than any other to
- * pi, the ratio of the circumference of a circle to its
- * diameter.
- */
- public static final double PI = 3.14159265358979323846;
-
- /**
- * Returns the trigonometric sine of an angle. Special cases:
- *
If the argument is NaN or an infinity, then the
- * result is NaN.
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- * @param a an angle, in radians.
- * @return the sine of the argument.
- */
- public static native double sin(double a);
-
- /**
- * Returns the trigonometric cosine of an angle. Special cases:
- *
If the argument is NaN or an infinity, then the
- * result is NaN.
- *
- * @param a an angle, in radians.
- * @return the cosine of the argument.
- */
- public static native double cos(double a);
-
- /**
- * Returns the trigonometric tangent of an angle. Special cases:
- *
If the argument is NaN or an infinity, then the result
- * is NaN.
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- * @param a an angle, in radians.
- * @return the tangent of the argument.
- */
- public static native double tan(double a);
-
- /**
- * Returns the arc sine of a value; the returned angle is in the
- * range -pi/2 through pi/2. Special cases:
- *
If the argument is NaN or its absolute value is greater
- * than 1, then the result is NaN.
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- * @param a the value whose arc sine is to be returned.
- * @return the arc sine of the argument.
- */
- public static native double asin(double a);
-
- /**
- * Returns the arc cosine of a value; the returned angle is in the
- * range 0.0 through pi. Special case:
- *
If the argument is NaN or its absolute value is greater
- * than 1, then the result is NaN.
- *
- * @param a the value whose arc cosine is to be returned.
- * @return the arc cosine of the argument.
- */
- public static native double acos(double a);
-
- /**
- * Returns the arc tangent of a value; the returned angle is in the
- * range -pi/2 through pi/2. Special cases:
- *
If the argument is NaN, then the result is NaN.
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- * @param a the value whose arc tangent is to be returned.
- * @return the arc tangent of the argument.
- */
- public static native double atan(double a);
-
- /**
- * Converts an angle measured in degrees to an approximately
- * equivalent angle measured in radians. The conversion from
- * degrees to radians is generally inexact.
- *
- * @param angdeg an angle, in degrees
- * @return the measurement of the angle {@code angdeg}
- * in radians.
- */
- public static strictfp double toRadians(double angdeg) {
- return angdeg / 180.0 * PI;
- }
-
- /**
- * Converts an angle measured in radians to an approximately
- * equivalent angle measured in degrees. The conversion from
- * radians to degrees is generally inexact; users should
- * not expect {@code cos(toRadians(90.0))} to exactly
- * equal {@code 0.0}.
- *
- * @param angrad an angle, in radians
- * @return the measurement of the angle {@code angrad}
- * in degrees.
- */
- public static strictfp double toDegrees(double angrad) {
- return angrad * 180.0 / PI;
- }
-
- /**
- * Returns Euler's number e raised to the power of a
- * {@code double} value. Special cases:
- *
If the argument is NaN, the result is NaN.
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
If the argument is negative infinity, then the result is
- * positive zero.
- *
- * @param a the exponent to raise e to.
- * @return the value e{@code a},
- * where e is the base of the natural logarithms.
- */
- public static native double exp(double a);
-
- /**
- * Returns the natural logarithm (base e) of a {@code double}
- * value. Special cases:
- *
If the argument is NaN or less than zero, then the result
- * is NaN.
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
If the argument is positive zero or negative zero, then the
- * result is negative infinity.
- *
- * @param a a value
- * @return the value ln {@code a}, the natural logarithm of
- * {@code a}.
- */
- public static native double log(double a);
-
-
- /**
- * Returns the base 10 logarithm of a {@code double} value.
- * Special cases:
- *
- *
If the argument is NaN or less than zero, then the result
- * is NaN.
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
If the argument is positive zero or negative zero, then the
- * result is negative infinity.
- *
If the argument is equal to 10n for
- * integer n, then the result is n.
- *
- *
- * @param a a value
- * @return the base 10 logarithm of {@code a}.
- * @since 1.5
- */
- public static native double log10(double a);
-
- /**
- * Returns the correctly rounded positive square root of a
- * {@code double} value.
- * Special cases:
- *
If the argument is NaN or less than zero, then the result
- * is NaN.
- *
If the argument is positive infinity, then the result is positive
- * infinity.
- *
If the argument is positive zero or negative zero, then the
- * result is the same as the argument.
- * Otherwise, the result is the {@code double} value closest to
- * the true mathematical square root of the argument value.
- *
- * @param a a value.
- * @return the positive square root of {@code a}.
- */
- public static native double sqrt(double a);
-
- /**
- * Returns the cube root of a {@code double} value. For
- * positive finite {@code x}, {@code cbrt(-x) ==
- * -cbrt(x)}; that is, the cube root of a negative value is
- * the negative of the cube root of that value's magnitude.
- * Special cases:
- *
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is an infinity
- * with the same sign as the argument.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- * @param a a value.
- * @return the cube root of {@code a}.
- * @since 1.5
- */
- public static native double cbrt(double a);
-
- /**
- * Computes the remainder operation on two arguments as prescribed
- * by the IEEE 754 standard.
- * The remainder value is mathematically equal to
- * f1 - f2 × n,
- * where n is the mathematical integer closest to the exact
- * mathematical value of the quotient {@code f1/f2}, and if two
- * mathematical integers are equally close to {@code f1/f2},
- * then n is the integer that is even. If the remainder is
- * zero, its sign is the same as the sign of the first argument.
- * Special cases:
- *
If either argument is NaN, or the first argument is infinite,
- * or the second argument is positive zero or negative zero, then the
- * result is NaN.
- *
If the first argument is finite and the second argument is
- * infinite, then the result is the same as the first argument.
- *
- * @param f1 the dividend.
- * @param f2 the divisor.
- * @return the remainder when {@code f1} is divided by
- * {@code f2}.
- */
- public static native double IEEEremainder(double f1, double f2);
-
- /**
- * Returns the smallest (closest to negative infinity)
- * {@code double} value that is greater than or equal to the
- * argument and is equal to a mathematical integer. Special cases:
- *
If the argument value is already equal to a
- * mathematical integer, then the result is the same as the
- * argument.
If the argument is NaN or an infinity or
- * positive zero or negative zero, then the result is the same as
- * the argument.
If the argument value is less than zero but
- * greater than -1.0, then the result is negative zero.
Note
- * that the value of {@code StrictMath.ceil(x)} is exactly the
- * value of {@code -StrictMath.floor(-x)}.
- *
- * @param a a value.
- * @return the smallest (closest to negative infinity)
- * floating-point value that is greater than or equal to
- * the argument and is equal to a mathematical integer.
- */
- public static double ceil(double a) {
- return floorOrCeil(a, -0.0, 1.0, 1.0);
- }
-
- /**
- * Returns the largest (closest to positive infinity)
- * {@code double} value that is less than or equal to the
- * argument and is equal to a mathematical integer. Special cases:
- *
If the argument value is already equal to a
- * mathematical integer, then the result is the same as the
- * argument.
If the argument is NaN or an infinity or
- * positive zero or negative zero, then the result is the same as
- * the argument.
- *
- * @param a a value.
- * @return the largest (closest to positive infinity)
- * floating-point value that less than or equal to the argument
- * and is equal to a mathematical integer.
- */
- public static double floor(double a) {
- return floorOrCeil(a, -1.0, 0.0, -1.0);
- }
-
- /**
- * Internal method to share logic between floor and ceil.
- *
- * @param a the value to be floored or ceiled
- * @param negativeBoundary result for values in (-1, 0)
- * @param positiveBoundary result for values in (0, 1)
- * @param increment value to add when the argument is non-integral
- */
- private static double floorOrCeil(double a,
- double negativeBoundary,
- double positiveBoundary,
- double sign) {
- int exponent = getExponent(a);
-
- if (exponent < 0) {
- /*
- * Absolute value of argument is less than 1.
- * floorOrceil(-0.0) => -0.0
- * floorOrceil(+0.0) => +0.0
- */
- return ((a == 0.0) ? a :
- ( (a < 0.0) ? negativeBoundary : positiveBoundary) );
- } else if (exponent >= 52) {
- /*
- * Infinity, NaN, or a value so large it must be integral.
- */
- return a;
- }
- // Else the argument is either an integral value already XOR it
- // has to be rounded to one.
- assert exponent >= 0 && exponent <= 51;
-
- long doppel = Double.doubleToRawLongBits(a);
- long mask = 0; // DoubleConsts.SIGNIF_BIT_MASK >> exponent;
-
- if ( (mask & doppel) == 0L )
- return a; // integral value
- else {
- double result = Double.longBitsToDouble(doppel & (~mask));
- if (sign*a > 0.0)
- result = result + sign;
- return result;
- }
- }
-
- /**
- * Returns the {@code double} value that is closest in value
- * to the argument and is equal to a mathematical integer. If two
- * {@code double} values that are mathematical integers are
- * equally close to the value of the argument, the result is the
- * integer value that is even. Special cases:
- *
If the argument value is already equal to a mathematical
- * integer, then the result is the same as the argument.
- *
If the argument is NaN or an infinity or positive zero or negative
- * zero, then the result is the same as the argument.
- *
- * @param a a value.
- * @return the closest floating-point value to {@code a} that is
- * equal to a mathematical integer.
- * @author Joseph D. Darcy
- */
- public static double rint(double a) {
- throw new UnsupportedOperationException();
- /*
- * If the absolute value of a is not less than 2^52, it
- * is either a finite integer (the double format does not have
- * enough significand bits for a number that large to have any
- * fractional portion), an infinity, or a NaN. In any of
- * these cases, rint of the argument is the argument.
- *
- * Otherwise, the sum (twoToThe52 + a ) will properly round
- * away any fractional portion of a since ulp(twoToThe52) ==
- * 1.0; subtracting out twoToThe52 from this sum will then be
- * exact and leave the rounded integer portion of a.
- *
- * This method does *not* need to be declared strictfp to get
- * fully reproducible results. Whether or not a method is
- * declared strictfp can only make a difference in the
- * returned result if some operation would overflow or
- * underflow with strictfp semantics. The operation
- * (twoToThe52 + a ) cannot overflow since large values of a
- * are screened out; the add cannot underflow since twoToThe52
- * is too large. The subtraction ((twoToThe52 + a ) -
- * twoToThe52) will be exact as discussed above and thus
- * cannot overflow or meaningfully underflow. Finally, the
- * last multiply in the return statement is by plus or minus
- * 1.0, which is exact too.
- */
-// double twoToThe52 = (double)(1L << 52); // 2^52
-// double sign = FpUtils.rawCopySign(1.0, a); // preserve sign info
-// a = Math.abs(a);
-//
-// if (a < twoToThe52) { // E_min <= ilogb(a) <= 51
-// a = ((twoToThe52 + a ) - twoToThe52);
-// }
-//
-// return sign * a; // restore original sign
- }
-
- /**
- * Returns the angle theta from the conversion of rectangular
- * coordinates ({@code x}, {@code y}) to polar
- * coordinates (r, theta).
- * This method computes the phase theta by computing an arc tangent
- * of {@code y/x} in the range of -pi to pi. Special
- * cases:
- *
If either argument is NaN, then the result is NaN.
- *
If the first argument is positive zero and the second argument
- * is positive, or the first argument is positive and finite and the
- * second argument is positive infinity, then the result is positive
- * zero.
- *
If the first argument is negative zero and the second argument
- * is positive, or the first argument is negative and finite and the
- * second argument is positive infinity, then the result is negative zero.
- *
If the first argument is positive zero and the second argument
- * is negative, or the first argument is positive and finite and the
- * second argument is negative infinity, then the result is the
- * {@code double} value closest to pi.
- *
If the first argument is negative zero and the second argument
- * is negative, or the first argument is negative and finite and the
- * second argument is negative infinity, then the result is the
- * {@code double} value closest to -pi.
- *
If the first argument is positive and the second argument is
- * positive zero or negative zero, or the first argument is positive
- * infinity and the second argument is finite, then the result is the
- * {@code double} value closest to pi/2.
- *
If the first argument is negative and the second argument is
- * positive zero or negative zero, or the first argument is negative
- * infinity and the second argument is finite, then the result is the
- * {@code double} value closest to -pi/2.
- *
If both arguments are positive infinity, then the result is the
- * {@code double} value closest to pi/4.
- *
If the first argument is positive infinity and the second argument
- * is negative infinity, then the result is the {@code double}
- * value closest to 3*pi/4.
- *
If the first argument is negative infinity and the second argument
- * is positive infinity, then the result is the {@code double} value
- * closest to -pi/4.
- *
If both arguments are negative infinity, then the result is the
- * {@code double} value closest to -3*pi/4.
- *
- * @param y the ordinate coordinate
- * @param x the abscissa coordinate
- * @return the theta component of the point
- * (r, theta)
- * in polar coordinates that corresponds to the point
- * (x, y) in Cartesian coordinates.
- */
- public static native double atan2(double y, double x);
-
-
- /**
- * Returns the value of the first argument raised to the power of the
- * second argument. Special cases:
- *
- *
If the second argument is positive or negative zero, then the
- * result is 1.0.
- *
If the second argument is 1.0, then the result is the same as the
- * first argument.
- *
If the second argument is NaN, then the result is NaN.
- *
If the first argument is NaN and the second argument is nonzero,
- * then the result is NaN.
- *
- *
If
- *
- *
the absolute value of the first argument is greater than 1
- * and the second argument is positive infinity, or
- *
the absolute value of the first argument is less than 1 and
- * the second argument is negative infinity,
- *
- * then the result is positive infinity.
- *
- *
If
- *
- *
the absolute value of the first argument is greater than 1 and
- * the second argument is negative infinity, or
- *
the absolute value of the
- * first argument is less than 1 and the second argument is positive
- * infinity,
- *
- * then the result is positive zero.
- *
- *
If the absolute value of the first argument equals 1 and the
- * second argument is infinite, then the result is NaN.
- *
- *
If
- *
- *
the first argument is positive zero and the second argument
- * is greater than zero, or
- *
the first argument is positive infinity and the second
- * argument is less than zero,
- *
- * then the result is positive zero.
- *
- *
If
- *
- *
the first argument is positive zero and the second argument
- * is less than zero, or
- *
the first argument is positive infinity and the second
- * argument is greater than zero,
- *
- * then the result is positive infinity.
- *
- *
If
- *
- *
the first argument is negative zero and the second argument
- * is greater than zero but not a finite odd integer, or
- *
the first argument is negative infinity and the second
- * argument is less than zero but not a finite odd integer,
- *
- * then the result is positive zero.
- *
- *
If
- *
- *
the first argument is negative zero and the second argument
- * is a positive finite odd integer, or
- *
the first argument is negative infinity and the second
- * argument is a negative finite odd integer,
- *
- * then the result is negative zero.
- *
- *
If
- *
- *
the first argument is negative zero and the second argument
- * is less than zero but not a finite odd integer, or
- *
the first argument is negative infinity and the second
- * argument is greater than zero but not a finite odd integer,
- *
- * then the result is positive infinity.
- *
- *
If
- *
- *
the first argument is negative zero and the second argument
- * is a negative finite odd integer, or
- *
the first argument is negative infinity and the second
- * argument is a positive finite odd integer,
- *
- * then the result is negative infinity.
- *
- *
If the first argument is finite and less than zero
- *
- *
if the second argument is a finite even integer, the
- * result is equal to the result of raising the absolute value of
- * the first argument to the power of the second argument
- *
- *
if the second argument is a finite odd integer, the result
- * is equal to the negative of the result of raising the absolute
- * value of the first argument to the power of the second
- * argument
- *
- *
if the second argument is finite and not an integer, then
- * the result is NaN.
- *
- *
- *
If both arguments are integers, then the result is exactly equal
- * to the mathematical result of raising the first argument to the power
- * of the second argument if that result can in fact be represented
- * exactly as a {@code double} value.
- *
- *
(In the foregoing descriptions, a floating-point value is
- * considered to be an integer if and only if it is finite and a
- * fixed point of the method {@link #ceil ceil} or,
- * equivalently, a fixed point of the method {@link #floor
- * floor}. A value is a fixed point of a one-argument
- * method if and only if the result of applying the method to the
- * value is equal to the value.)
- *
- * @param a base.
- * @param b the exponent.
- * @return the value {@code a}{@code b}.
- */
- public static native double pow(double a, double b);
-
- /**
- * Returns the closest {@code int} to the argument, with ties
- * rounding up.
- *
- *
Special cases:
- *
If the argument is NaN, the result is 0.
- *
If the argument is negative infinity or any value less than or
- * equal to the value of {@code Integer.MIN_VALUE}, the result is
- * equal to the value of {@code Integer.MIN_VALUE}.
- *
If the argument is positive infinity or any value greater than or
- * equal to the value of {@code Integer.MAX_VALUE}, the result is
- * equal to the value of {@code Integer.MAX_VALUE}.
- *
- * @param a a floating-point value to be rounded to an integer.
- * @return the value of the argument rounded to the nearest
- * {@code int} value.
- * @see java.lang.Integer#MAX_VALUE
- * @see java.lang.Integer#MIN_VALUE
- */
- public static int round(float a) {
- return Math.round(a);
- }
-
- /**
- * Returns the closest {@code long} to the argument, with ties
- * rounding up.
- *
- *
Special cases:
- *
If the argument is NaN, the result is 0.
- *
If the argument is negative infinity or any value less than or
- * equal to the value of {@code Long.MIN_VALUE}, the result is
- * equal to the value of {@code Long.MIN_VALUE}.
- *
If the argument is positive infinity or any value greater than or
- * equal to the value of {@code Long.MAX_VALUE}, the result is
- * equal to the value of {@code Long.MAX_VALUE}.
- *
- * @param a a floating-point value to be rounded to a
- * {@code long}.
- * @return the value of the argument rounded to the nearest
- * {@code long} value.
- * @see java.lang.Long#MAX_VALUE
- * @see java.lang.Long#MIN_VALUE
- */
- public static long round(double a) {
- return Math.round(a);
- }
-
- /**
- * Returns a {@code double} value with a positive sign, greater
- * than or equal to {@code 0.0} and less than {@code 1.0}.
- * Returned values are chosen pseudorandomly with (approximately)
- * uniform distribution from that range.
- *
- *
When this method is first called, it creates a single new
- * pseudorandom-number generator, exactly as if by the expression
- *
- *
{@code new java.util.Random()}
- *
- * This new pseudorandom-number generator is used thereafter for
- * all calls to this method and is used nowhere else.
- *
- *
This method is properly synchronized to allow correct use by
- * more than one thread. However, if many threads need to generate
- * pseudorandom numbers at a great rate, it may reduce contention
- * for each thread to have its own pseudorandom number generator.
- *
- * @return a pseudorandom {@code double} greater than or equal
- * to {@code 0.0} and less than {@code 1.0}.
- * @see Random#nextDouble()
- */
- public static double random() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the absolute value of an {@code int} value..
- * If the argument is not negative, the argument is returned.
- * If the argument is negative, the negation of the argument is returned.
- *
- *
Note that if the argument is equal to the value of
- * {@link Integer#MIN_VALUE}, the most negative representable
- * {@code int} value, the result is that same value, which is
- * negative.
- *
- * @param a the argument whose absolute value is to be determined.
- * @return the absolute value of the argument.
- */
- public static int abs(int a) {
- return (a < 0) ? -a : a;
- }
-
- /**
- * Returns the absolute value of a {@code long} value.
- * If the argument is not negative, the argument is returned.
- * If the argument is negative, the negation of the argument is returned.
- *
- *
Note that if the argument is equal to the value of
- * {@link Long#MIN_VALUE}, the most negative representable
- * {@code long} value, the result is that same value, which
- * is negative.
- *
- * @param a the argument whose absolute value is to be determined.
- * @return the absolute value of the argument.
- */
- public static long abs(long a) {
- return (a < 0) ? -a : a;
- }
-
- /**
- * Returns the absolute value of a {@code float} value.
- * If the argument is not negative, the argument is returned.
- * If the argument is negative, the negation of the argument is returned.
- * Special cases:
- *
If the argument is positive zero or negative zero, the
- * result is positive zero.
- *
If the argument is infinite, the result is positive infinity.
- *
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
- *
- * @param a the argument whose absolute value is to be determined
- * @return the absolute value of the argument.
- */
- public static float abs(float a) {
- return (a <= 0.0F) ? 0.0F - a : a;
- }
-
- /**
- * Returns the absolute value of a {@code double} value.
- * If the argument is not negative, the argument is returned.
- * If the argument is negative, the negation of the argument is returned.
- * Special cases:
- *
If the argument is positive zero or negative zero, the result
- * is positive zero.
- *
If the argument is infinite, the result is positive infinity.
- *
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
- *
- * @param a the argument whose absolute value is to be determined
- * @return the absolute value of the argument.
- */
- public static double abs(double a) {
- return (a <= 0.0D) ? 0.0D - a : a;
- }
-
- /**
- * Returns the greater of two {@code int} values. That is, the
- * result is the argument closer to the value of
- * {@link Integer#MAX_VALUE}. If the arguments have the same value,
- * the result is that same value.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the larger of {@code a} and {@code b}.
- */
- public static int max(int a, int b) {
- return (a >= b) ? a : b;
- }
-
- /**
- * Returns the greater of two {@code long} values. That is, the
- * result is the argument closer to the value of
- * {@link Long#MAX_VALUE}. If the arguments have the same value,
- * the result is that same value.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the larger of {@code a} and {@code b}.
- */
- public static long max(long a, long b) {
- return (a >= b) ? a : b;
- }
-
- // Use raw bit-wise conversions on guaranteed non-NaN arguments.
- private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);
- private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);
-
- /**
- * Returns the greater of two {@code float} values. That is,
- * the result is the argument closer to positive infinity. If the
- * arguments have the same value, the result is that same
- * value. If either value is NaN, then the result is NaN. Unlike
- * the numerical comparison operators, this method considers
- * negative zero to be strictly smaller than positive zero. If one
- * argument is positive zero and the other negative zero, the
- * result is positive zero.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the larger of {@code a} and {@code b}.
- */
- public static float max(float a, float b) {
- if (a != a)
- return a; // a is NaN
- if ((a == 0.0f) &&
- (b == 0.0f) &&
- (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) {
- // Raw conversion ok since NaN can't map to -0.0.
- return b;
- }
- return (a >= b) ? a : b;
- }
-
- /**
- * Returns the greater of two {@code double} values. That
- * is, the result is the argument closer to positive infinity. If
- * the arguments have the same value, the result is that same
- * value. If either value is NaN, then the result is NaN. Unlike
- * the numerical comparison operators, this method considers
- * negative zero to be strictly smaller than positive zero. If one
- * argument is positive zero and the other negative zero, the
- * result is positive zero.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the larger of {@code a} and {@code b}.
- */
- public static double max(double a, double b) {
- if (a != a)
- return a; // a is NaN
- if ((a == 0.0d) &&
- (b == 0.0d) &&
- (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) {
- // Raw conversion ok since NaN can't map to -0.0.
- return b;
- }
- return (a >= b) ? a : b;
- }
-
- /**
- * Returns the smaller of two {@code int} values. That is,
- * the result the argument closer to the value of
- * {@link Integer#MIN_VALUE}. If the arguments have the same
- * value, the result is that same value.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the smaller of {@code a} and {@code b}.
- */
- public static int min(int a, int b) {
- return (a <= b) ? a : b;
- }
-
- /**
- * Returns the smaller of two {@code long} values. That is,
- * the result is the argument closer to the value of
- * {@link Long#MIN_VALUE}. If the arguments have the same
- * value, the result is that same value.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the smaller of {@code a} and {@code b}.
- */
- public static long min(long a, long b) {
- return (a <= b) ? a : b;
- }
-
- /**
- * Returns the smaller of two {@code float} values. That is,
- * the result is the value closer to negative infinity. If the
- * arguments have the same value, the result is that same
- * value. If either value is NaN, then the result is NaN. Unlike
- * the numerical comparison operators, this method considers
- * negative zero to be strictly smaller than positive zero. If
- * one argument is positive zero and the other is negative zero,
- * the result is negative zero.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the smaller of {@code a} and {@code b.}
- */
- public static float min(float a, float b) {
- if (a != a)
- return a; // a is NaN
- if ((a == 0.0f) &&
- (b == 0.0f) &&
- (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) {
- // Raw conversion ok since NaN can't map to -0.0.
- return b;
- }
- return (a <= b) ? a : b;
- }
-
- /**
- * Returns the smaller of two {@code double} values. That
- * is, the result is the value closer to negative infinity. If the
- * arguments have the same value, the result is that same
- * value. If either value is NaN, then the result is NaN. Unlike
- * the numerical comparison operators, this method considers
- * negative zero to be strictly smaller than positive zero. If one
- * argument is positive zero and the other is negative zero, the
- * result is negative zero.
- *
- * @param a an argument.
- * @param b another argument.
- * @return the smaller of {@code a} and {@code b}.
- */
- public static double min(double a, double b) {
- if (a != a)
- return a; // a is NaN
- if ((a == 0.0d) &&
- (b == 0.0d) &&
- (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) {
- // Raw conversion ok since NaN can't map to -0.0.
- return b;
- }
- return (a <= b) ? a : b;
- }
-
- /**
- * Returns the size of an ulp of the argument. An ulp of a
- * {@code double} value is the positive distance between this
- * floating-point value and the {@code double} value next
- * larger in magnitude. Note that for non-NaN x,
- * ulp(-x) == ulp(x).
- *
- *
Special Cases:
- *
- *
If the argument is NaN, then the result is NaN.
- *
If the argument is positive or negative infinity, then the
- * result is positive infinity.
- *
If the argument is positive or negative zero, then the result is
- * {@code Double.MIN_VALUE}.
- *
If the argument is ±{@code Double.MAX_VALUE}, then
- * the result is equal to 2971.
- *
- *
- * @param d the floating-point value whose ulp is to be returned
- * @return the size of an ulp of the argument
- * @author Joseph D. Darcy
- * @since 1.5
- */
- public static double ulp(double d) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the size of an ulp of the argument. An ulp of a
- * {@code float} value is the positive distance between this
- * floating-point value and the {@code float} value next
- * larger in magnitude. Note that for non-NaN x,
- * ulp(-x) == ulp(x).
- *
- *
Special Cases:
- *
- *
If the argument is NaN, then the result is NaN.
- *
If the argument is positive or negative infinity, then the
- * result is positive infinity.
- *
If the argument is positive or negative zero, then the result is
- * {@code Float.MIN_VALUE}.
- *
If the argument is ±{@code Float.MAX_VALUE}, then
- * the result is equal to 2104.
- *
- *
- * @param f the floating-point value whose ulp is to be returned
- * @return the size of an ulp of the argument
- * @author Joseph D. Darcy
- * @since 1.5
- */
- public static float ulp(float f) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the signum function of the argument; zero if the argument
- * is zero, 1.0 if the argument is greater than zero, -1.0 if the
- * argument is less than zero.
- *
- *
Special Cases:
- *
- *
If the argument is NaN, then the result is NaN.
- *
If the argument is positive zero or negative zero, then the
- * result is the same as the argument.
- *
- *
- * @param d the floating-point value whose signum is to be returned
- * @return the signum function of the argument
- * @author Joseph D. Darcy
- * @since 1.5
- */
- public static double signum(double d) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the signum function of the argument; zero if the argument
- * is zero, 1.0f if the argument is greater than zero, -1.0f if the
- * argument is less than zero.
- *
- *
Special Cases:
- *
- *
If the argument is NaN, then the result is NaN.
- *
If the argument is positive zero or negative zero, then the
- * result is the same as the argument.
- *
- *
- * @param f the floating-point value whose signum is to be returned
- * @return the signum function of the argument
- * @author Joseph D. Darcy
- * @since 1.5
- */
- public static float signum(float f) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the hyperbolic sine of a {@code double} value.
- * The hyperbolic sine of x is defined to be
- * (ex - e-x)/2
- * where e is {@linkplain Math#E Euler's number}.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is an infinity
- * with the same sign as the argument.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- * @param x The number whose hyperbolic sine is to be returned.
- * @return The hyperbolic sine of {@code x}.
- * @since 1.5
- */
- public static native double sinh(double x);
-
- /**
- * Returns the hyperbolic cosine of a {@code double} value.
- * The hyperbolic cosine of x is defined to be
- * (ex + e-x)/2
- * where e is {@linkplain Math#E Euler's number}.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is infinite, then the result is positive
- * infinity.
- *
- *
If the argument is zero, then the result is {@code 1.0}.
- *
- *
- *
- * @param x The number whose hyperbolic cosine is to be returned.
- * @return The hyperbolic cosine of {@code x}.
- * @since 1.5
- */
- public static native double cosh(double x);
-
- /**
- * Returns the hyperbolic tangent of a {@code double} value.
- * The hyperbolic tangent of x is defined to be
- * (ex - e-x)/(ex + e-x),
- * in other words, {@linkplain Math#sinh
- * sinh(x)}/{@linkplain Math#cosh cosh(x)}. Note
- * that the absolute value of the exact tanh is always less than
- * 1.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN, then the result is NaN.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
If the argument is positive infinity, then the result is
- * {@code +1.0}.
- *
- *
If the argument is negative infinity, then the result is
- * {@code -1.0}.
- *
- *
- *
- * @param x The number whose hyperbolic tangent is to be returned.
- * @return The hyperbolic tangent of {@code x}.
- * @since 1.5
- */
- public static native double tanh(double x);
-
- /**
- * Returns sqrt(x2 +y2)
- * without intermediate overflow or underflow.
- *
- *
Special cases:
- *
- *
- *
If either argument is infinite, then the result
- * is positive infinity.
- *
- *
If either argument is NaN and neither argument is infinite,
- * then the result is NaN.
- *
- *
- *
- * @param x a value
- * @param y a value
- * @return sqrt(x2 +y2)
- * without intermediate overflow or underflow
- * @since 1.5
- */
- public static native double hypot(double x, double y);
-
- /**
- * Returns ex -1. Note that for values of
- * x near 0, the exact sum of
- * {@code expm1(x)} + 1 is much closer to the true
- * result of ex than {@code exp(x)}.
- *
- *
Special cases:
- *
- *
If the argument is NaN, the result is NaN.
- *
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
- *
If the argument is negative infinity, then the result is
- * -1.0.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- * @param x the exponent to raise e to in the computation of
- * e{@code x} -1.
- * @return the value e{@code x} - 1.
- * @since 1.5
- */
- public static native double expm1(double x);
-
- /**
- * Returns the natural logarithm of the sum of the argument and 1.
- * Note that for small values {@code x}, the result of
- * {@code log1p(x)} is much closer to the true result of ln(1
- * + {@code x}) than the floating-point evaluation of
- * {@code log(1.0+x)}.
- *
- *
Special cases:
- *
- *
- *
If the argument is NaN or less than -1, then the result is
- * NaN.
- *
- *
If the argument is positive infinity, then the result is
- * positive infinity.
- *
- *
If the argument is negative one, then the result is
- * negative infinity.
- *
- *
If the argument is zero, then the result is a zero with the
- * same sign as the argument.
- *
- *
- *
- * @param x a value
- * @return the value ln({@code x} + 1), the natural
- * log of {@code x} + 1
- * @since 1.5
- */
- public static native double log1p(double x);
-
- /**
- * Returns the first floating-point argument with the sign of the
- * second floating-point argument. For this method, a NaN
- * {@code sign} argument is always treated as if it were
- * positive.
- *
- * @param magnitude the parameter providing the magnitude of the result
- * @param sign the parameter providing the sign of the result
- * @return a value with the magnitude of {@code magnitude}
- * and the sign of {@code sign}.
- * @since 1.6
- */
- public static double copySign(double magnitude, double sign) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the first floating-point argument with the sign of the
- * second floating-point argument. For this method, a NaN
- * {@code sign} argument is always treated as if it were
- * positive.
- *
- * @param magnitude the parameter providing the magnitude of the result
- * @param sign the parameter providing the sign of the result
- * @return a value with the magnitude of {@code magnitude}
- * and the sign of {@code sign}.
- * @since 1.6
- */
- public static float copySign(float magnitude, float sign) {
- throw new UnsupportedOperationException();
- }
- /**
- * Returns the unbiased exponent used in the representation of a
- * {@code float}. Special cases:
- *
- *
- *
If the argument is NaN or infinite, then the result is
- * {@link Float#MAX_EXPONENT} + 1.
- *
If the argument is zero or subnormal, then the result is
- * {@link Float#MIN_EXPONENT} -1.
- *
- * @param f a {@code float} value
- * @since 1.6
- */
- public static int getExponent(float f) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the unbiased exponent used in the representation of a
- * {@code double}. Special cases:
- *
- *
- *
If the argument is NaN or infinite, then the result is
- * {@link Double#MAX_EXPONENT} + 1.
- *
If the argument is zero or subnormal, then the result is
- * {@link Double#MIN_EXPONENT} -1.
- *
- * @param d a {@code double} value
- * @since 1.6
- */
- public static int getExponent(double d) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the floating-point number adjacent to the first
- * argument in the direction of the second argument. If both
- * arguments compare as equal the second argument is returned.
- *
- *
Special cases:
- *
- *
If either argument is a NaN, then NaN is returned.
- *
- *
If both arguments are signed zeros, {@code direction}
- * is returned unchanged (as implied by the requirement of
- * returning the second argument if the arguments compare as
- * equal).
- *
- *
If {@code start} is
- * ±{@link Double#MIN_VALUE} and {@code direction}
- * has a value such that the result should have a smaller
- * magnitude, then a zero with the same sign as {@code start}
- * is returned.
- *
- *
If {@code start} is infinite and
- * {@code direction} has a value such that the result should
- * have a smaller magnitude, {@link Double#MAX_VALUE} with the
- * same sign as {@code start} is returned.
- *
- *
If {@code start} is equal to ±
- * {@link Double#MAX_VALUE} and {@code direction} has a
- * value such that the result should have a larger magnitude, an
- * infinity with same sign as {@code start} is returned.
- *
- *
- * @param start starting floating-point value
- * @param direction value indicating which of
- * {@code start}'s neighbors or {@code start} should
- * be returned
- * @return The floating-point number adjacent to {@code start} in the
- * direction of {@code direction}.
- * @since 1.6
- */
- public static double nextAfter(double start, double direction) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the floating-point number adjacent to the first
- * argument in the direction of the second argument. If both
- * arguments compare as equal a value equivalent to the second argument
- * is returned.
- *
- *
Special cases:
- *
- *
If either argument is a NaN, then NaN is returned.
- *
- *
If both arguments are signed zeros, a value equivalent
- * to {@code direction} is returned.
- *
- *
If {@code start} is
- * ±{@link Float#MIN_VALUE} and {@code direction}
- * has a value such that the result should have a smaller
- * magnitude, then a zero with the same sign as {@code start}
- * is returned.
- *
- *
If {@code start} is infinite and
- * {@code direction} has a value such that the result should
- * have a smaller magnitude, {@link Float#MAX_VALUE} with the
- * same sign as {@code start} is returned.
- *
- *
If {@code start} is equal to ±
- * {@link Float#MAX_VALUE} and {@code direction} has a
- * value such that the result should have a larger magnitude, an
- * infinity with same sign as {@code start} is returned.
- *
- *
- * @param start starting floating-point value
- * @param direction value indicating which of
- * {@code start}'s neighbors or {@code start} should
- * be returned
- * @return The floating-point number adjacent to {@code start} in the
- * direction of {@code direction}.
- * @since 1.6
- */
- public static float nextAfter(float start, double direction) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the floating-point value adjacent to {@code d} in
- * the direction of positive infinity. This method is
- * semantically equivalent to {@code nextAfter(d,
- * Double.POSITIVE_INFINITY)}; however, a {@code nextUp}
- * implementation may run faster than its equivalent
- * {@code nextAfter} call.
- *
- *
Special Cases:
- *
- *
If the argument is NaN, the result is NaN.
- *
- *
If the argument is positive infinity, the result is
- * positive infinity.
- *
- *
If the argument is zero, the result is
- * {@link Double#MIN_VALUE}
- *
- *
- *
- * @param d starting floating-point value
- * @return The adjacent floating-point value closer to positive
- * infinity.
- * @since 1.6
- */
- public static double nextUp(double d) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the floating-point value adjacent to {@code f} in
- * the direction of positive infinity. This method is
- * semantically equivalent to {@code nextAfter(f,
- * Float.POSITIVE_INFINITY)}; however, a {@code nextUp}
- * implementation may run faster than its equivalent
- * {@code nextAfter} call.
- *
- *
Special Cases:
- *
- *
If the argument is NaN, the result is NaN.
- *
- *
If the argument is positive infinity, the result is
- * positive infinity.
- *
- *
If the argument is zero, the result is
- * {@link Float#MIN_VALUE}
- *
- *
- *
- * @param f starting floating-point value
- * @return The adjacent floating-point value closer to positive
- * infinity.
- * @since 1.6
- */
- public static float nextUp(float f) {
- throw new UnsupportedOperationException();
- }
-
-
- /**
- * Return {@code d} ×
- * 2{@code scaleFactor} rounded as if performed
- * by a single correctly rounded floating-point multiply to a
- * member of the double value set. See the Java
- * Language Specification for a discussion of floating-point
- * value sets. If the exponent of the result is between {@link
- * Double#MIN_EXPONENT} and {@link Double#MAX_EXPONENT}, the
- * answer is calculated exactly. If the exponent of the result
- * would be larger than {@code Double.MAX_EXPONENT}, an
- * infinity is returned. Note that if the result is subnormal,
- * precision may be lost; that is, when {@code scalb(x, n)}
- * is subnormal, {@code scalb(scalb(x, n), -n)} may not equal
- * x. When the result is non-NaN, the result has the same
- * sign as {@code d}.
- *
- *
Special cases:
- *
- *
If the first argument is NaN, NaN is returned.
- *
If the first argument is infinite, then an infinity of the
- * same sign is returned.
- *
If the first argument is zero, then a zero of the same
- * sign is returned.
- *
- *
- * @param d number to be scaled by a power of two.
- * @param scaleFactor power of 2 used to scale {@code d}
- * @return {@code d} × 2{@code scaleFactor}
- * @since 1.6
- */
- public static double scalb(double d, int scaleFactor) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Return {@code f} ×
- * 2{@code scaleFactor} rounded as if performed
- * by a single correctly rounded floating-point multiply to a
- * member of the float value set. See the Java
- * Language Specification for a discussion of floating-point
- * value sets. If the exponent of the result is between {@link
- * Float#MIN_EXPONENT} and {@link Float#MAX_EXPONENT}, the
- * answer is calculated exactly. If the exponent of the result
- * would be larger than {@code Float.MAX_EXPONENT}, an
- * infinity is returned. Note that if the result is subnormal,
- * precision may be lost; that is, when {@code scalb(x, n)}
- * is subnormal, {@code scalb(scalb(x, n), -n)} may not equal
- * x. When the result is non-NaN, the result has the same
- * sign as {@code f}.
- *
- *
Special cases:
- *
- *
If the first argument is NaN, NaN is returned.
- *
If the first argument is infinite, then an infinity of the
- * same sign is returned.
- *
If the first argument is zero, then a zero of the same
- * sign is returned.
- *
- *
- * @param f number to be scaled by a power of two.
- * @param scaleFactor power of 2 used to scale {@code f}
- * @return {@code f} × 2{@code scaleFactor}
- * @since 1.6
- */
- public static float scalb(float f, int scaleFactor) {
- throw new UnsupportedOperationException();
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/String.java
--- a/emul/src/main/java/java/lang/String.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/String.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,8 +25,11 @@
package java.lang;
+import java.util.Comparator;
import org.apidesign.bck2brwsr.core.ExtraJavaScript;
-import java.util.Comparator;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.core.JavaScriptOnly;
+import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
/**
* The String class represents character strings. All
@@ -99,25 +102,25 @@
@ExtraJavaScript(
resource="/org/apidesign/vm4brwsr/emul/java_lang_String.js",
- processByteCode=false
+ processByteCode=true
)
+@JavaScriptPrototype(container = "String.prototype", prototype = "new String")
public final class String
implements java.io.Serializable, Comparable, CharSequence
{
- /** The value is used for character storage. */
- private final char value[];
-
- /** The offset is the first index of the storage that is used. */
- private final int offset;
-
- /** The count is the number of characters in the String. */
- private final int count;
-
- /** Cache the hash code for the string */
- private int hash; // Default to 0
+ /** real string to delegate to */
+ private Object r;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
+
+ @JavaScriptOnly(name="toString", value="function() { return this.fld_r; }")
+ private static void jsToString() {
+ }
+
+ @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }")
+ private static void jsValudOf() {
+ }
/**
* Class String is special cased within the Serialization Stream Protocol.
@@ -140,9 +143,7 @@
* unnecessary since Strings are immutable.
*/
public String() {
- this.offset = 0;
- this.count = 0;
- this.value = new char[0];
+ this.r = "";
}
/**
@@ -156,23 +157,7 @@
* A {@code String}
*/
public String(String original) {
- int size = original.count;
- char[] originalValue = original.value;
- char[] v;
- if (originalValue.length > size) {
- // The array representing the String is bigger than the new
- // String itself. Perhaps this constructor is being called
- // in order to trim the baggage, so make a copy of the array.
- int off = original.offset;
- v = copyOfRange(originalValue, off, off+size);
- } else {
- // The array representing the String is the same
- // size as the String, so no point in making a copy.
- v = originalValue;
- }
- this.offset = 0;
- this.count = size;
- this.value = v;
+ this.r = original.toString();
}
/**
@@ -184,11 +169,13 @@
* @param value
* The initial value of the string
*/
+ @JavaScriptBody(args = { "charArr" }, body=
+ "for (var i = 0; i < charArr.length; i++) {\n"
+ + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n"
+ + "}\n"
+ + "this.fld_r = charArr.join('');\n"
+ )
public String(char value[]) {
- int size = value.length;
- this.offset = 0;
- this.count = size;
- this.value = copyOf(value, size);
}
/**
@@ -212,20 +199,14 @@
* If the {@code offset} and {@code count} arguments index
* characters outside the bounds of the {@code value} array
*/
+ @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
+ "var up = off + cnt;\n" +
+ "for (var i = off; i < up; i++) {\n" +
+ " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" +
+ "}\n" +
+ "this.fld_r = charArr.slice(off, up).join(\"\");\n"
+ )
public String(char value[], int offset, int count) {
- if (offset < 0) {
- throw new StringIndexOutOfBoundsException(offset);
- }
- if (count < 0) {
- throw new StringIndexOutOfBoundsException(count);
- }
- // Note: offset or count might be near -1>>>1.
- if (offset > value.length - count) {
- throw new StringIndexOutOfBoundsException(offset + count);
- }
- this.offset = 0;
- this.count = count;
- this.value = copyOfRange(value, offset, offset+count);
}
/**
@@ -292,9 +273,7 @@
Character.toSurrogates(c, v, j++);
}
- this.value = v;
- this.count = n;
- this.offset = 0;
+ this.r = new String(v, 0, n);
}
/**
@@ -351,9 +330,7 @@
value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
}
}
- this.offset = 0;
- this.count = count;
- this.value = value;
+ this.r = new String(value, 0, count);
}
/**
@@ -578,9 +555,7 @@
for (int i = 0; i < length; i++) {
v[i] = (char)bytes[offset++];
}
- this.offset = 0;
- this.count = v.length;
- this.value = v;
+ this.r = new String(v, 0, v.length);
}
/**
@@ -613,10 +588,7 @@
* A {@code StringBuffer}
*/
public String(StringBuffer buffer) {
- String result = buffer.toString();
- this.value = result.value;
- this.count = result.count;
- this.offset = result.offset;
+ this.r = buffer.toString();
}
/**
@@ -635,18 +607,7 @@
* @since 1.5
*/
public String(StringBuilder builder) {
- String result = builder.toString();
- this.value = result.value;
- this.count = result.count;
- this.offset = result.offset;
- }
-
-
- // Package private constructor which shares value array for speed.
- String(int offset, int count, char value[]) {
- this.value = value;
- this.offset = offset;
- this.count = count;
+ this.r = builder.toString();
}
/**
@@ -657,8 +618,9 @@
* @return the length of the sequence of characters represented by this
* object.
*/
+ @JavaScriptBody(args = {}, body = "return this.toString().length;")
public int length() {
- return count;
+ throw new UnsupportedOperationException();
}
/**
@@ -669,8 +631,9 @@
*
* @since 1.6
*/
+ @JavaScriptBody(args = {}, body="return this.toString().length === 0;")
public boolean isEmpty() {
- return count == 0;
+ return length() == 0;
}
/**
@@ -691,11 +654,11 @@
* argument is negative or not less than the length of this
* string.
*/
+ @JavaScriptBody(args = { "index" },
+ body = "return this.toString().charCodeAt(index);"
+ )
public char charAt(int index) {
- if ((index < 0) || (index >= count)) {
- throw new StringIndexOutOfBoundsException(index);
- }
- return value[index + offset];
+ throw new UnsupportedOperationException();
}
/**
@@ -721,10 +684,10 @@
* @since 1.5
*/
public int codePointAt(int index) {
- if ((index < 0) || (index >= count)) {
+ if ((index < 0) || (index >= length())) {
throw new StringIndexOutOfBoundsException(index);
}
- return Character.codePointAtImpl(value, offset + index, offset + count);
+ return Character.codePointAtImpl(toCharArray(), offset() + index, offset() + length());
}
/**
@@ -751,10 +714,10 @@
*/
public int codePointBefore(int index) {
int i = index - 1;
- if ((i < 0) || (i >= count)) {
+ if ((i < 0) || (i >= length())) {
throw new StringIndexOutOfBoundsException(index);
}
- return Character.codePointBeforeImpl(value, offset + index, offset);
+ return Character.codePointBeforeImpl(toCharArray(), offset() + index, offset());
}
/**
@@ -779,10 +742,10 @@
* @since 1.5
*/
public int codePointCount(int beginIndex, int endIndex) {
- if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
+ if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) {
throw new IndexOutOfBoundsException();
}
- return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex);
+ return Character.codePointCountImpl(toCharArray(), offset()+beginIndex, endIndex-beginIndex);
}
/**
@@ -806,19 +769,25 @@
* @since 1.5
*/
public int offsetByCodePoints(int index, int codePointOffset) {
- if (index < 0 || index > count) {
+ if (index < 0 || index > length()) {
throw new IndexOutOfBoundsException();
}
- return Character.offsetByCodePointsImpl(value, offset, count,
- offset+index, codePointOffset) - offset;
+ return Character.offsetByCodePointsImpl(toCharArray(), offset(), length(),
+ offset()+index, codePointOffset) - offset();
}
/**
* Copy characters from this string into dst starting at dstBegin.
* This method doesn't perform any range checking.
*/
+ @JavaScriptBody(args = { "arr", "to" }, body =
+ "var s = this.toString();\n" +
+ "for (var i = 0; i < s.length; i++) {\n" +
+ " arr[to++] = s[i];\n" +
+ "}"
+ )
void getChars(char dst[], int dstBegin) {
- arraycopy(value, offset, dst, dstBegin, count);
+ AbstractStringBuilder.arraycopy(toCharArray(), offset(), dst, dstBegin, length());
}
/**
@@ -851,17 +820,23 @@
*
dstBegin+(srcEnd-srcBegin) is larger than
* dst.length
*/
+ @JavaScriptBody(args = { "beg", "end", "arr", "dst" }, body=
+ "var s = this.toString();\n" +
+ "while (beg < end) {\n" +
+ " arr[dst++] = s[beg++];\n" +
+ "}\n"
+ )
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
- if (srcEnd > count) {
+ if (srcEnd > length()) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
- arraycopy(value, offset + srcBegin, dst, dstBegin,
+ AbstractStringBuilder.arraycopy(toCharArray(), offset() + srcBegin, dst, dstBegin,
srcEnd - srcBegin);
}
@@ -913,16 +888,16 @@
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
- if (srcEnd > count) {
+ if (srcEnd > length()) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
int j = dstBegin;
- int n = offset + srcEnd;
- int i = offset + srcBegin;
- char[] val = value; /* avoid getfield opcode */
+ int n = offset() + srcEnd;
+ int i = offset() + srcBegin;
+ char[] val = toCharArray(); /* avoid getfield opcode */
while (i < n) {
dst[j++] = (byte)val[i++];
@@ -1018,18 +993,22 @@
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
+ @JavaScriptBody(args = { "obj" }, body =
+ "return obj != null && obj.$instOf_java_lang_String && "
+ + "this.toString() === obj.toString();"
+ )
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
- int n = count;
- if (n == anotherString.count) {
- char v1[] = value;
- char v2[] = anotherString.value;
- int i = offset;
- int j = anotherString.offset;
+ int n = length();
+ if (n == anotherString.length()) {
+ char v1[] = toCharArray();
+ char v2[] = anotherString.toCharArray();
+ int i = offset();
+ int j = anotherString.offset();
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
@@ -1075,15 +1054,15 @@
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
- if (count != cs.length())
+ if (length() != cs.length())
return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
- char v1[] = value;
+ char v1[] = toCharArray();
char v2[] = ((AbstractStringBuilder)cs).getValue();
- int i = offset;
+ int i = offset();
int j = 0;
- int n = count;
+ int n = length();
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
@@ -1094,10 +1073,10 @@
if (cs.equals(this))
return true;
// Argument is a generic CharSequence
- char v1[] = value;
- int i = offset;
+ char v1[] = toCharArray();
+ int i = offset();
int j = 0;
- int n = count;
+ int n = length();
while (n-- != 0) {
if (v1[i++] != cs.charAt(j++))
return false;
@@ -1135,8 +1114,8 @@
*/
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true :
- (anotherString != null) && (anotherString.count == count) &&
- regionMatches(true, 0, anotherString, 0, count);
+ (anotherString != null) && (anotherString.length() == length()) &&
+ regionMatches(true, 0, anotherString, 0, length());
}
/**
@@ -1181,13 +1160,13 @@
* lexicographically greater than the string argument.
*/
public int compareTo(String anotherString) {
- int len1 = count;
- int len2 = anotherString.count;
+ int len1 = length();
+ int len2 = anotherString.length();
int n = Math.min(len1, len2);
- char v1[] = value;
- char v2[] = anotherString.value;
- int i = offset;
- int j = anotherString.offset;
+ char v1[] = toCharArray();
+ char v2[] = anotherString.toCharArray();
+ int i = offset();
+ int j = anotherString.offset();
if (i == j) {
int k = i;
@@ -1226,6 +1205,11 @@
*/
public static final Comparator CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
+
+ private static int offset() {
+ return 0;
+ }
+
private static class CaseInsensitiveComparator
implements Comparator, java.io.Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
@@ -1312,13 +1296,13 @@
*/
public boolean regionMatches(int toffset, String other, int ooffset,
int len) {
- char ta[] = value;
- int to = offset + toffset;
- char pa[] = other.value;
- int po = other.offset + ooffset;
+ char ta[] = toCharArray();
+ int to = offset() + toffset;
+ char pa[] = other.toCharArray();
+ int po = other.offset() + ooffset;
// Note: toffset, ooffset, or len might be near -1>>>1.
- if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len)
- || (ooffset > (long)other.count - len)) {
+ if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len)
+ || (ooffset > (long)other.length() - len)) {
return false;
}
while (len-- > 0) {
@@ -1381,13 +1365,13 @@
*/
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) {
- char ta[] = value;
- int to = offset + toffset;
- char pa[] = other.value;
- int po = other.offset + ooffset;
+ char ta[] = toCharArray();
+ int to = offset() + toffset;
+ char pa[] = other.toCharArray();
+ int po = other.offset() + ooffset;
// Note: toffset, ooffset, or len might be near -1>>>1.
- if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) ||
- (ooffset > (long)other.count - len)) {
+ if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) ||
+ (ooffset > (long)other.length() - len)) {
return false;
}
while (len-- > 0) {
@@ -1436,14 +1420,18 @@
* this.substring(toffset).startsWith(prefix)
*
*/
+ @JavaScriptBody(args = { "find", "from" }, body=
+ "find = find.toString();\n" +
+ "return this.toString().substring(from, from + find.length) === find;\n"
+ )
public boolean startsWith(String prefix, int toffset) {
- char ta[] = value;
- int to = offset + toffset;
- char pa[] = prefix.value;
- int po = prefix.offset;
- int pc = prefix.count;
+ char ta[] = toCharArray();
+ int to = offset() + toffset;
+ char pa[] = prefix.toCharArray();
+ int po = prefix.offset();
+ int pc = prefix.length();
// Note: toffset might be near -1>>>1.
- if ((toffset < 0) || (toffset > count - pc)) {
+ if ((toffset < 0) || (toffset > length() - pc)) {
return false;
}
while (--pc >= 0) {
@@ -1483,7 +1471,7 @@
* as determined by the {@link #equals(Object)} method.
*/
public boolean endsWith(String suffix) {
- return startsWith(suffix, count - suffix.count);
+ return startsWith(suffix, length() - suffix.length());
}
/**
@@ -1500,16 +1488,17 @@
* @return a hash code value for this object.
*/
public int hashCode() {
- int h = hash;
- if (h == 0 && count > 0) {
- int off = offset;
- char val[] = value;
- int len = count;
+ return super.hashCode();
+ }
+ int computeHashCode() {
+ int h = 0;
+ if (h == 0 && length() > 0) {
+ int off = offset();
+ int len = length();
for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
+ h = 31*h + charAt(off++);
}
- hash = h;
}
return h;
}
@@ -1581,10 +1570,14 @@
* than or equal to fromIndex, or -1
* if the character does not occur.
*/
+ @JavaScriptBody(args = { "ch", "from" }, body =
+ "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
+ "return this.toString().indexOf(ch, from);\n"
+ )
public int indexOf(int ch, int fromIndex) {
if (fromIndex < 0) {
fromIndex = 0;
- } else if (fromIndex >= count) {
+ } else if (fromIndex >= length()) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
@@ -1592,9 +1585,9 @@
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
- final char[] value = this.value;
- final int offset = this.offset;
- final int max = offset + count;
+ final char[] value = this.toCharArray();
+ final int offset = this.offset();
+ final int max = offset + length();
for (int i = offset + fromIndex; i < max ; i++) {
if (value[i] == ch) {
return i - offset;
@@ -1611,11 +1604,11 @@
*/
private int indexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
- final char[] value = this.value;
- final int offset = this.offset;
+ final char[] value = this.toCharArray();
+ final int offset = this.offset();
final char hi = Character.highSurrogate(ch);
final char lo = Character.lowSurrogate(ch);
- final int max = offset + count - 1;
+ final int max = offset + length() - 1;
for (int i = offset + fromIndex; i < max; i++) {
if (value[i] == hi && value[i+1] == lo) {
return i - offset;
@@ -1649,7 +1642,7 @@
* -1 if the character does not occur.
*/
public int lastIndexOf(int ch) {
- return lastIndexOf(ch, count - 1);
+ return lastIndexOf(ch, length() - 1);
}
/**
@@ -1686,13 +1679,17 @@
* than or equal to fromIndex, or -1
* if the character does not occur before that point.
*/
+ @JavaScriptBody(args = { "ch", "from" }, body =
+ "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
+ "return this.toString().lastIndexOf(ch, from);"
+ )
public int lastIndexOf(int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
- final char[] value = this.value;
- final int offset = this.offset;
- int i = offset + Math.min(fromIndex, count - 1);
+ final char[] value = this.toCharArray();
+ final int offset = this.offset();
+ int i = offset + Math.min(fromIndex, length() - 1);
for (; i >= offset ; i--) {
if (value[i] == ch) {
return i - offset;
@@ -1709,11 +1706,11 @@
*/
private int lastIndexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
- final char[] value = this.value;
- final int offset = this.offset;
+ final char[] value = this.toCharArray();
+ final int offset = this.offset();
char hi = Character.highSurrogate(ch);
char lo = Character.lowSurrogate(ch);
- int i = offset + Math.min(fromIndex, count - 2);
+ int i = offset + Math.min(fromIndex, length() - 2);
for (; i >= offset; i--) {
if (value[i] == hi && value[i+1] == lo) {
return i - offset;
@@ -1757,61 +1754,10 @@
* starting at the specified index,
* or {@code -1} if there is no such occurrence.
*/
- public int indexOf(String str, int fromIndex) {
- return indexOf(value, offset, count,
- str.value, str.offset, str.count, fromIndex);
- }
-
- /**
- * Code shared by String and StringBuffer to do searches. The
- * source is the character array being searched, and the target
- * is the string being searched for.
- *
- * @param source the characters being searched.
- * @param sourceOffset offset of the source string.
- * @param sourceCount count of the source string.
- * @param target the characters being searched for.
- * @param targetOffset offset of the target string.
- * @param targetCount count of the target string.
- * @param fromIndex the index to begin searching from.
- */
- static int indexOf(char[] source, int sourceOffset, int sourceCount,
- char[] target, int targetOffset, int targetCount,
- int fromIndex) {
- if (fromIndex >= sourceCount) {
- return (targetCount == 0 ? sourceCount : -1);
- }
- if (fromIndex < 0) {
- fromIndex = 0;
- }
- if (targetCount == 0) {
- return fromIndex;
- }
-
- char first = target[targetOffset];
- int max = sourceOffset + (sourceCount - targetCount);
-
- for (int i = sourceOffset + fromIndex; i <= max; i++) {
- /* Look for first character. */
- if (source[i] != first) {
- while (++i <= max && source[i] != first);
- }
-
- /* Found first character, now look at the rest of v2 */
- if (i <= max) {
- int j = i + 1;
- int end = j + targetCount - 1;
- for (int k = targetOffset + 1; j < end && source[j] ==
- target[k]; j++, k++);
-
- if (j == end) {
- /* Found whole string. */
- return i - sourceOffset;
- }
- }
- }
- return -1;
- }
+ @JavaScriptBody(args = { "str", "fromIndex" }, body =
+ "return this.toString().indexOf(str.toString(), fromIndex);"
+ )
+ public native int indexOf(String str, int fromIndex);
/**
* Returns the index within this string of the last occurrence of the
@@ -1829,7 +1775,7 @@
* or {@code -1} if there is no such occurrence.
*/
public int lastIndexOf(String str) {
- return lastIndexOf(str, count);
+ return lastIndexOf(str, length());
}
/**
@@ -1848,9 +1794,11 @@
* searching backward from the specified index,
* or {@code -1} if there is no such occurrence.
*/
+ @JavaScriptBody(args = { "s", "from" }, body =
+ "return this.toString().lastIndexOf(s.toString(), from);"
+ )
public int lastIndexOf(String str, int fromIndex) {
- return lastIndexOf(value, offset, count,
- str.value, str.offset, str.count, fromIndex);
+ return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex);
}
/**
@@ -1930,7 +1878,7 @@
* length of this String object.
*/
public String substring(int beginIndex) {
- return substring(beginIndex, count);
+ return substring(beginIndex, length());
}
/**
@@ -1955,18 +1903,21 @@
* beginIndex is larger than
* endIndex.
*/
+ @JavaScriptBody(args = { "beginIndex", "endIndex" }, body =
+ "return this.toString().substring(beginIndex, endIndex);"
+ )
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
- if (endIndex > count) {
+ if (endIndex > length()) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
- return ((beginIndex == 0) && (endIndex == count)) ? this :
- new String(offset + beginIndex, endIndex - beginIndex, value);
+ return ((beginIndex == 0) && (endIndex == length())) ? this :
+ new String(toCharArray(), offset() + beginIndex, endIndex - beginIndex);
}
/**
@@ -2026,10 +1977,10 @@
if (otherLen == 0) {
return this;
}
- char buf[] = new char[count + otherLen];
- getChars(0, count, buf, 0);
- str.getChars(0, otherLen, buf, count);
- return new String(0, count + otherLen, buf);
+ char buf[] = new char[length() + otherLen];
+ getChars(0, length(), buf, 0);
+ str.getChars(0, otherLen, buf, length());
+ return new String(buf, 0, length() + otherLen);
}
/**
@@ -2061,12 +2012,24 @@
* @return a string derived from this string by replacing every
* occurrence of oldChar with newChar.
*/
+ @JavaScriptBody(args = { "arg1", "arg2" }, body =
+ "if (typeof arg1 === 'number') arg1 = String.fromCharCode(arg1);\n" +
+ "if (typeof arg2 === 'number') arg2 = String.fromCharCode(arg2);\n" +
+ "var s = this.toString();\n" +
+ "for (;;) {\n" +
+ " var ret = s.replace(arg1, arg2);\n" +
+ " if (ret === s) {\n" +
+ " return ret;\n" +
+ " }\n" +
+ " s = ret;\n" +
+ "}"
+ )
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
- int len = count;
+ int len = length();
int i = -1;
- char[] val = value; /* avoid getfield opcode */
- int off = offset; /* avoid getfield opcode */
+ char[] val = toCharArray(); /* avoid getfield opcode */
+ int off = offset(); /* avoid getfield opcode */
while (++i < len) {
if (val[off + i] == oldChar) {
@@ -2083,7 +2046,7 @@
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
- return new String(0, len, buf);
+ return new String(buf, 0, len);
}
}
return this;
@@ -2115,6 +2078,12 @@
* @since 1.4
* @spec JSR-51
*/
+ @JavaScriptBody(args = { "regex" }, body =
+ "var self = this.toString();\n"
+ + "var re = new RegExp(regex.toString());\n"
+ + "var r = re.exec(self);\n"
+ + "return r != null && r.length > 0 && self.length == r[0].length;"
+ )
public boolean matches(String regex) {
throw new UnsupportedOperationException();
}
@@ -2527,6 +2496,7 @@
* @return the String, converted to lowercase.
* @see java.lang.String#toLowerCase(Locale)
*/
+ @JavaScriptBody(args = {}, body = "return this.toLowerCase();")
public String toLowerCase() {
throw new UnsupportedOperationException("Should be supported but without connection to locale");
}
@@ -2692,6 +2662,7 @@
* @return the String, converted to uppercase.
* @see java.lang.String#toUpperCase(Locale)
*/
+ @JavaScriptBody(args = {}, body = "return this.toUpperCase();")
public String toUpperCase() {
throw new UnsupportedOperationException();
}
@@ -2728,10 +2699,10 @@
* trailing white space.
*/
public String trim() {
- int len = count;
+ int len = length();
int st = 0;
- int off = offset; /* avoid getfield opcode */
- char[] val = value; /* avoid getfield opcode */
+ int off = offset(); /* avoid getfield opcode */
+ char[] val = toCharArray(); /* avoid getfield opcode */
while ((st < len) && (val[off + st] <= ' ')) {
st++;
@@ -2739,7 +2710,7 @@
while ((st < len) && (val[off + len - 1] <= ' ')) {
len--;
}
- return ((st > 0) || (len < count)) ? substring(st, len) : this;
+ return ((st > 0) || (len < length())) ? substring(st, len) : this;
}
/**
@@ -2747,6 +2718,7 @@
*
* @return the string itself.
*/
+ @JavaScriptBody(args = {}, body = "return this.toString();")
public String toString() {
return this;
}
@@ -2759,8 +2731,8 @@
* the character sequence represented by this string.
*/
public char[] toCharArray() {
- char result[] = new char[count];
- getChars(0, count, result, 0);
+ char result[] = new char[length()];
+ getChars(0, length(), result, 0);
return result;
}
@@ -2951,7 +2923,7 @@
*/
public static String valueOf(char c) {
char data[] = {c};
- return new String(0, 1, data);
+ return new String(data, 0, 1);
}
/**
@@ -3034,32 +3006,4 @@
* guaranteed to be from a pool of unique strings.
*/
public native String intern();
-
- static char[] copyOfRange(char[] original, int from, int to) {
- int newLength = to - from;
- if (newLength < 0) {
- throw new IllegalArgumentException(from + " > " + to);
- }
- char[] copy = new char[newLength];
- arraycopy(original, from, copy, 0,
- Math.min(original.length - from, newLength));
- return copy;
- }
- static char[] copyOf(char[] original, int newLength) {
- char[] copy = new char[newLength];
- arraycopy(original, 0, copy, 0,
- Math.min(original.length, newLength));
- return copy;
- }
- static void arraycopy(
- char[] value, int srcBegin, char[] dst, int dstBegin, int count
- ) {
- while (count-- > 0) {
- dst[dstBegin++] = value[srcBegin++];
- }
- }
- // access system property
- static String getProperty(String nm) {
- return null;
- }
}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StringBuffer.java
--- a/emul/src/main/java/java/lang/StringBuffer.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/StringBuffer.java Wed Jan 23 20:16:48 2013 +0100
@@ -527,8 +527,7 @@
* @since 1.4
*/
public synchronized int indexOf(String str, int fromIndex) {
- return String.indexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.indexOf(str, fromIndex);
}
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StringBuilder.java
--- a/emul/src/main/java/java/lang/StringBuilder.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/StringBuilder.java Wed Jan 23 20:16:48 2013 +0100
@@ -376,8 +376,7 @@
* @throws NullPointerException {@inheritDoc}
*/
public int indexOf(String str, int fromIndex) {
- return String.indexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.indexOf(str, fromIndex);
}
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Throwable.java
--- a/emul/src/main/java/java/lang/Throwable.java Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/java/java/lang/Throwable.java Wed Jan 23 20:16:48 2013 +0100
@@ -25,6 +25,8 @@
package java.lang;
import java.io.*;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.core.JavaScriptOnly;
/**
* The {@code Throwable} class is the superclass of all errors and
@@ -233,6 +235,13 @@
private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted";
/** Caption for labeling causative exception stack traces */
+ @JavaScriptOnly(name="toString", value="function() { return this.toString__Ljava_lang_String_2().toString(); }")
+ private static void jsToString() {
+ }
+
+ @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }")
+ private static void jsValudOf() {
+ }
private static final String CAUSE_CAPTION = "Caused by: ";
/** Caption for labeling suppressed exception stack traces */
@@ -782,6 +791,7 @@
return this;
}
+ @JavaScriptBody(args = { "dummy" }, body = "")
private native Throwable fillInStackTrace(int dummy);
/**
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Void.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/Void.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * The {@code Void} class is an uninstantiable placeholder class to hold a
+ * reference to the {@code Class} object representing the Java keyword
+ * void.
+ *
+ * @author unascribed
+ * @since JDK1.1
+ */
+public final
+class Void {
+
+ /**
+ * The {@code Class} object representing the pseudo-type corresponding to
+ * the keyword {@code void}.
+ */
+ public static final Class TYPE = Class.getPrimitiveClass("void");
+
+ /*
+ * The Void class cannot be instantiated.
+ */
+ private Void() {}
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/AccessibleObject.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/AccessibleObject.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The AccessibleObject class is the base class for Field, Method and
+ * Constructor objects. It provides the ability to flag a reflected
+ * object as suppressing default Java language access control checks
+ * when it is used. The access checks--for public, default (package)
+ * access, protected, and private members--are performed when Fields,
+ * Methods or Constructors are used to set or get fields, to invoke
+ * methods, or to create and initialize new instances of classes,
+ * respectively.
+ *
+ *
Setting the {@code accessible} flag in a reflected object
+ * permits sophisticated applications with sufficient privilege, such
+ * as Java Object Serialization or other persistence mechanisms, to
+ * manipulate objects in a manner that would normally be prohibited.
+ *
+ *
By default, a reflected object is not accessible.
+ *
+ * @see Field
+ * @see Method
+ * @see Constructor
+ * @see ReflectPermission
+ *
+ * @since 1.2
+ */
+public class AccessibleObject implements AnnotatedElement {
+
+ /**
+ * Convenience method to set the {@code accessible} flag for an
+ * array of objects with a single security check (for efficiency).
+ *
+ *
First, if there is a security manager, its
+ * {@code checkPermission} method is called with a
+ * {@code ReflectPermission("suppressAccessChecks")} permission.
+ *
+ *
A {@code SecurityException} is raised if {@code flag} is
+ * {@code true} but accessibility of any of the elements of the input
+ * {@code array} may not be changed (for example, if the element
+ * object is a {@link Constructor} object for the class {@link
+ * java.lang.Class}). In the event of such a SecurityException, the
+ * accessibility of objects is set to {@code flag} for array elements
+ * upto (and excluding) the element for which the exception occurred; the
+ * accessibility of elements beyond (and including) the element for which
+ * the exception occurred is unchanged.
+ *
+ * @param array the array of AccessibleObjects
+ * @param flag the new value for the {@code accessible} flag
+ * in each object
+ * @throws SecurityException if the request is denied.
+ * @see SecurityManager#checkPermission
+ * @see java.lang.RuntimePermission
+ */
+ public static void setAccessible(AccessibleObject[] array, boolean flag)
+ throws SecurityException {
+ throw new SecurityException();
+ }
+
+ /**
+ * Set the {@code accessible} flag for this object to
+ * the indicated boolean value. A value of {@code true} indicates that
+ * the reflected object should suppress Java language access
+ * checking when it is used. A value of {@code false} indicates
+ * that the reflected object should enforce Java language access checks.
+ *
+ *
First, if there is a security manager, its
+ * {@code checkPermission} method is called with a
+ * {@code ReflectPermission("suppressAccessChecks")} permission.
+ *
+ *
A {@code SecurityException} is raised if {@code flag} is
+ * {@code true} but accessibility of this object may not be changed
+ * (for example, if this element object is a {@link Constructor} object for
+ * the class {@link java.lang.Class}).
+ *
+ *
A {@code SecurityException} is raised if this object is a {@link
+ * java.lang.reflect.Constructor} object for the class
+ * {@code java.lang.Class}, and {@code flag} is true.
+ *
+ * @param flag the new value for the {@code accessible} flag
+ * @throws SecurityException if the request is denied.
+ * @see SecurityManager#checkPermission
+ * @see java.lang.RuntimePermission
+ */
+ public void setAccessible(boolean flag) throws SecurityException {
+ throw new SecurityException();
+ }
+
+ /**
+ * Get the value of the {@code accessible} flag for this object.
+ *
+ * @return the value of the object's {@code accessible} flag
+ */
+ public boolean isAccessible() {
+ return override;
+ }
+
+ /**
+ * Constructor: only used by the Java Virtual Machine.
+ */
+ protected AccessibleObject() {}
+
+ // Indicates whether language-level access checks are overridden
+ // by this object. Initializes to "false". This field is used by
+ // Field, Method, and Constructor.
+ //
+ // NOTE: for security purposes, this field must not be visible
+ // outside this package.
+ boolean override;
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public T getAnnotation(Class annotationClass) {
+ throw new AssertionError("All subclasses should override this method");
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public boolean isAnnotationPresent(
+ Class extends Annotation> annotationClass) {
+ return getAnnotation(annotationClass) != null;
+ }
+
+ /**
+ * @since 1.5
+ */
+ public Annotation[] getAnnotations() {
+ return getDeclaredAnnotations();
+ }
+
+ /**
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ throw new AssertionError("All subclasses should override this method");
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/AnnotatedElement.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/AnnotatedElement.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Represents an annotated element of the program currently running in this
+ * VM. This interface allows annotations to be read reflectively. All
+ * annotations returned by methods in this interface are immutable and
+ * serializable. It is permissible for the caller to modify the
+ * arrays returned by accessors for array-valued enum members; it will
+ * have no affect on the arrays returned to other callers.
+ *
+ *
If an annotation returned by a method in this interface contains
+ * (directly or indirectly) a {@link Class}-valued member referring to
+ * a class that is not accessible in this VM, attempting to read the class
+ * by calling the relevant Class-returning method on the returned annotation
+ * will result in a {@link TypeNotPresentException}.
+ *
+ *
Similarly, attempting to read an enum-valued member will result in
+ * a {@link EnumConstantNotPresentException} if the enum constant in the
+ * annotation is no longer present in the enum type.
+ *
+ *
Finally, Attempting to read a member whose definition has evolved
+ * incompatibly will result in a {@link
+ * java.lang.annotation.AnnotationTypeMismatchException} or an
+ * {@link java.lang.annotation.IncompleteAnnotationException}.
+ *
+ * @see java.lang.EnumConstantNotPresentException
+ * @see java.lang.TypeNotPresentException
+ * @see java.lang.annotation.AnnotationFormatError
+ * @see java.lang.annotation.AnnotationTypeMismatchException
+ * @see java.lang.annotation.IncompleteAnnotationException
+ * @since 1.5
+ * @author Josh Bloch
+ */
+public interface AnnotatedElement {
+ /**
+ * Returns true if an annotation for the specified type
+ * is present on this element, else false. This method
+ * is designed primarily for convenient access to marker annotations.
+ *
+ * @param annotationClass the Class object corresponding to the
+ * annotation type
+ * @return true if an annotation for the specified annotation
+ * type is present on this element, else false
+ * @throws NullPointerException if the given annotation class is null
+ * @since 1.5
+ */
+ boolean isAnnotationPresent(Class extends Annotation> annotationClass);
+
+ /**
+ * Returns this element's annotation for the specified type if
+ * such an annotation is present, else null.
+ *
+ * @param annotationClass the Class object corresponding to the
+ * annotation type
+ * @return this element's annotation for the specified annotation type if
+ * present on this element, else null
+ * @throws NullPointerException if the given annotation class is null
+ * @since 1.5
+ */
+ T getAnnotation(Class annotationClass);
+
+ /**
+ * Returns all annotations present on this element. (Returns an array
+ * of length zero if this element has no annotations.) The caller of
+ * this method is free to modify the returned array; it will have no
+ * effect on the arrays returned to other callers.
+ *
+ * @return all annotations present on this element
+ * @since 1.5
+ */
+ Annotation[] getAnnotations();
+
+ /**
+ * Returns all annotations that are directly present on this
+ * element. Unlike the other methods in this interface, this method
+ * ignores inherited annotations. (Returns an array of length zero if
+ * no annotations are directly present on this element.) The caller of
+ * this method is free to modify the returned array; it will have no
+ * effect on the arrays returned to other callers.
+ *
+ * @return All annotations directly present on this element
+ * @since 1.5
+ */
+ Annotation[] getDeclaredAnnotations();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Array.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Array.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
+
+/**
+ * The {@code Array} class provides static methods to dynamically create and
+ * access Java arrays.
+ *
+ *
{@code Array} permits widening conversions to occur during a get or set
+ * operation, but throws an {@code IllegalArgumentException} if a narrowing
+ * conversion would occur.
+ *
+ * @author Nakul Saraiya
+ */
+@JavaScriptPrototype(prototype = "new Array", container = "Array.prototype")
+public final
+class Array {
+
+ /**
+ * Constructor. Class Array is not instantiable.
+ */
+ private Array() {}
+
+ /**
+ * Creates a new array with the specified component type and
+ * length.
+ * Invoking this method is equivalent to creating an array
+ * as follows:
+ *
+ *
+ * @param componentType the {@code Class} object representing the
+ * component type of the new array
+ * @param length the length of the new array
+ * @return the new array
+ * @exception NullPointerException if the specified
+ * {@code componentType} parameter is null
+ * @exception IllegalArgumentException if componentType is {@link Void#TYPE}
+ * @exception NegativeArraySizeException if the specified {@code length}
+ * is negative
+ */
+ public static Object newInstance(Class> componentType, int length)
+ throws NegativeArraySizeException {
+ if (length < 0) {
+ throw new NegativeArraySizeException();
+ }
+ String sig = findSignature(componentType);
+ return newArray(componentType.isPrimitive(), sig, length);
+ }
+
+ private static String findSignature(Class> type) {
+ if (type == Integer.TYPE) {
+ return "[I";
+ }
+ if (type == Long.TYPE) {
+ return "[J";
+ }
+ if (type == Double.TYPE) {
+ return "[D";
+ }
+ if (type == Float.TYPE) {
+ return "[F";
+ }
+ if (type == Byte.TYPE) {
+ return "[B";
+ }
+ if (type == Boolean.TYPE) {
+ return "[Z";
+ }
+ if (type == Short.TYPE) {
+ return "[S";
+ }
+ if (type == Character.TYPE) {
+ return "[C";
+ }
+ if (type.getName().equals("void")) {
+ throw new IllegalStateException("Can't create array for " + type);
+ }
+ return "[L" + type.getName() + ";";
+ }
+ /**
+ * Creates a new array
+ * with the specified component type and dimensions.
+ * If {@code componentType}
+ * represents a non-array class or interface, the new array
+ * has {@code dimensions.length} dimensions and
+ * {@code componentType} as its component type. If
+ * {@code componentType} represents an array class, the
+ * number of dimensions of the new array is equal to the sum
+ * of {@code dimensions.length} and the number of
+ * dimensions of {@code componentType}. In this case, the
+ * component type of the new array is the component type of
+ * {@code componentType}.
+ *
+ *
The number of dimensions of the new array must not
+ * exceed the number of array dimensions supported by the
+ * implementation (typically 255).
+ *
+ * @param componentType the {@code Class} object representing the component
+ * type of the new array
+ * @param dimensions an array of {@code int} representing the dimensions of
+ * the new array
+ * @return the new array
+ * @exception NullPointerException if the specified
+ * {@code componentType} argument is null
+ * @exception IllegalArgumentException if the specified {@code dimensions}
+ * argument is a zero-dimensional array, or if the number of
+ * requested dimensions exceeds the limit on the number of array dimensions
+ * supported by the implementation (typically 255), or if componentType
+ * is {@link Void#TYPE}.
+ * @exception NegativeArraySizeException if any of the components in
+ * the specified {@code dimensions} argument is negative.
+ */
+ public static Object newInstance(Class> componentType, int... dimensions)
+ throws IllegalArgumentException, NegativeArraySizeException {
+ StringBuilder sig = new StringBuilder();
+ for (int i = 1; i < dimensions.length; i++) {
+ sig.append('[');
+ }
+ sig.append(findSignature(componentType));
+ return multiNewArray(sig.toString(), dimensions, 0);
+ }
+
+ /**
+ * Returns the length of the specified array object, as an {@code int}.
+ *
+ * @param array the array
+ * @return the length of the array
+ * @exception IllegalArgumentException if the object argument is not
+ * an array
+ */
+ public static int getLength(Object array)
+ throws IllegalArgumentException {
+ if (!array.getClass().isArray()) {
+ throw new IllegalArgumentException("Argument is not an array");
+ }
+ return length(array);
+ }
+
+ @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
+ private static native int length(Object arr);
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object. The value is automatically wrapped in an object
+ * if it has a primitive type.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the (possibly wrapped) value of the indexed component in
+ * the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ */
+ public static Object get(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t.isPrimitive()) {
+ return Array.fromPrimitive(t, array, index);
+ } else {
+ return ((Object[])array)[index];
+ }
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code boolean}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static native boolean getBoolean(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code byte}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static byte getByte(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ if (array.getClass().getComponentType() != Byte.TYPE) {
+ throw new IllegalArgumentException();
+ }
+ byte[] arr = (byte[]) array;
+ return arr[index];
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code char}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static native char getChar(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code short}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static short getShort(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t == Short.TYPE) {
+ short[] arr = (short[]) array;
+ return arr[index];
+ }
+ return getByte(array, index);
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as an {@code int}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static int getInt(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t == Integer.TYPE) {
+ int[] arr = (int[]) array;
+ return arr[index];
+ }
+ return getShort(array, index);
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code long}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static long getLong(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t == Long.TYPE) {
+ long[] arr = (long[]) array;
+ return arr[index];
+ }
+ return getInt(array, index);
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code float}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static float getFloat(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t == Float.TYPE) {
+ float[] arr = (float[]) array;
+ return arr[index];
+ }
+ return getLong(array, index);
+ }
+
+ /**
+ * Returns the value of the indexed component in the specified
+ * array object, as a {@code double}.
+ *
+ * @param array the array
+ * @param index the index
+ * @return the value of the indexed component in the specified array
+ * @exception NullPointerException If the specified object is null
+ * @exception IllegalArgumentException If the specified object is not
+ * an array, or if the indexed element cannot be converted to the
+ * return type by an identity or widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to the
+ * length of the specified array
+ * @see Array#get
+ */
+ public static double getDouble(Object array, int index)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ final Class> t = array.getClass().getComponentType();
+ if (t == Double.TYPE) {
+ double[] arr = (double[]) array;
+ return arr[index];
+ }
+ return getFloat(array, index);
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified new value. The new value is first
+ * automatically unwrapped if the array has a primitive component
+ * type.
+ * @param array the array
+ * @param index the index into the array
+ * @param value the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the array component type is primitive and
+ * an unwrapping conversion fails
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ */
+ public static void set(Object array, int index, Object value)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ if (array.getClass().getComponentType().isPrimitive()) {
+ throw new IllegalArgumentException();
+ } else {
+ Object[] arr = (Object[])array;
+ arr[index] = value;
+ }
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code boolean} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param z the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static native void setBoolean(Object array, int index, boolean z)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code byte} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param b the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setByte(Object array, int index, byte b)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Byte.TYPE) {
+ byte[] arr = (byte[]) array;
+ arr[index] = b;
+ } else {
+ setShort(array, index, b);
+ }
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code char} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param c the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static native void setChar(Object array, int index, char c)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code short} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param s the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setShort(Object array, int index, short s)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Short.TYPE) {
+ short[] arr = (short[]) array;
+ arr[index] = s;
+ } else {
+ setInt(array, index, s);
+ }
+
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code int} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param i the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setInt(Object array, int index, int i)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Integer.TYPE) {
+ long[] arr = (long[]) array;
+ arr[index] = i;
+ } else {
+ setLong(array, index, i);
+ }
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code long} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param l the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setLong(Object array, int index, long l)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Long.TYPE) {
+ long[] arr = (long[]) array;
+ arr[index] = l;
+ } else {
+ setFloat(array, index, l);
+ }
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code float} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param f the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setFloat(Object array, int index, float f)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Float.TYPE) {
+ float[] arr = (float[])array;
+ arr[index] = f;
+ } else {
+ setDouble(array, index, f);
+ }
+ }
+
+ /**
+ * Sets the value of the indexed component of the specified array
+ * object to the specified {@code double} value.
+ * @param array the array
+ * @param index the index into the array
+ * @param d the new value of the indexed component
+ * @exception NullPointerException If the specified object argument
+ * is null
+ * @exception IllegalArgumentException If the specified object argument
+ * is not an array, or if the specified value cannot be converted
+ * to the underlying array's component type by an identity or a
+ * primitive widening conversion
+ * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
+ * argument is negative, or if it is greater than or equal to
+ * the length of the specified array
+ * @see Array#set
+ */
+ public static void setDouble(Object array, int index, double d)
+ throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ Class> t = array.getClass().getComponentType();
+ if (t == Double.TYPE) {
+ double[] arr = (double[])array;
+ arr[index] = d;
+ } else {
+ throw new IllegalArgumentException("argument type mismatch");
+ }
+ }
+
+ /*
+ * Private
+ */
+
+ @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
+ "var arr = new Array(length);\n"
+ + "var value = primitive ? 0 : null;\n"
+ + "for(var i = 0; i < length; i++) arr[i] = value;\n"
+ + "arr.jvmName = sig;\n"
+ + "return arr;"
+ )
+ private static native Object newArray(boolean primitive, String sig, int length);
+
+ private static Object multiNewArray(String sig, int[] dims, int index)
+ throws IllegalArgumentException, NegativeArraySizeException {
+ if (dims.length == index + 1) {
+ return newArray(sig.length() == 2, sig, dims[index]);
+ }
+ Object[] arr = (Object[]) newArray(false, sig, dims[index]);
+ String compsig = sig.substring(1);
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = multiNewArray(compsig, dims, index + 1);
+ }
+ return arr;
+ }
+ private static Object fromPrimitive(Class> t, Object array, int index) {
+ return Method.fromPrimitive(t, atArray(array, index));
+ }
+
+ @JavaScriptBody(args = { "array", "index" }, body = "return array[index]")
+ private static native Object atArray(Object array, int index);
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Field.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Field.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,953 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+
+/**
+ * A {@code Field} provides information about, and dynamic access to, a
+ * single field of a class or an interface. The reflected field may
+ * be a class (static) field or an instance field.
+ *
+ *
A {@code Field} permits widening conversions to occur during a get or
+ * set access operation, but throws an {@code IllegalArgumentException} if a
+ * narrowing conversion would occur.
+ *
+ * @see Member
+ * @see java.lang.Class
+ * @see java.lang.Class#getFields()
+ * @see java.lang.Class#getField(String)
+ * @see java.lang.Class#getDeclaredFields()
+ * @see java.lang.Class#getDeclaredField(String)
+ *
+ * @author Kenneth Russell
+ * @author Nakul Saraiya
+ */
+public final
+class Field extends AccessibleObject implements Member {
+
+ private Class> clazz;
+ private int slot;
+ // This is guaranteed to be interned by the VM in the 1.4
+ // reflection implementation
+ private String name;
+ private Class> type;
+ private int modifiers;
+ // Generics and annotations support
+ private transient String signature;
+ private byte[] annotations;
+ // For sharing of FieldAccessors. This branching structure is
+ // currently only two levels deep (i.e., one root Field and
+ // potentially many Field objects pointing to it.)
+ private Field root;
+
+ // Generics infrastructure
+
+ private String getGenericSignature() {return signature;}
+
+
+ /**
+ * Package-private constructor used by ReflectAccess to enable
+ * instantiation of these objects in Java code from the java.lang
+ * package via sun.reflect.LangReflectAccess.
+ */
+ Field(Class> declaringClass,
+ String name,
+ Class> type,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations)
+ {
+ this.clazz = declaringClass;
+ this.name = name;
+ this.type = type;
+ this.modifiers = modifiers;
+ this.slot = slot;
+ this.signature = signature;
+ this.annotations = annotations;
+ }
+
+ /**
+ * Package-private routine (exposed to java.lang.Class via
+ * ReflectAccess) which returns a copy of this Field. The copy's
+ * "root" field points to this Field.
+ */
+ Field copy() {
+ // This routine enables sharing of FieldAccessor objects
+ // among Field objects which refer to the same underlying
+ // method in the VM. (All of this contortion is only necessary
+ // because of the "accessibility" bit in AccessibleObject,
+ // which implicitly requires that new java.lang.reflect
+ // objects be fabricated for each reflective call on Class
+ // objects.)
+ Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
+ res.root = this;
+ return res;
+ }
+
+ /**
+ * Returns the {@code Class} object representing the class or interface
+ * that declares the field represented by this {@code Field} object.
+ */
+ public Class> getDeclaringClass() {
+ return clazz;
+ }
+
+ /**
+ * Returns the name of the field represented by this {@code Field} object.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the Java language modifiers for the field represented
+ * by this {@code Field} object, as an integer. The {@code Modifier} class should
+ * be used to decode the modifiers.
+ *
+ * @see Modifier
+ */
+ public int getModifiers() {
+ return modifiers;
+ }
+
+ /**
+ * Returns {@code true} if this field represents an element of
+ * an enumerated type; returns {@code false} otherwise.
+ *
+ * @return {@code true} if and only if this field represents an element of
+ * an enumerated type.
+ * @since 1.5
+ */
+ public boolean isEnumConstant() {
+ return (getModifiers() & Modifier.ENUM) != 0;
+ }
+
+ /**
+ * Returns {@code true} if this field is a synthetic
+ * field; returns {@code false} otherwise.
+ *
+ * @return true if and only if this field is a synthetic
+ * field as defined by the Java Language Specification.
+ * @since 1.5
+ */
+ public boolean isSynthetic() {
+ return Modifier.isSynthetic(getModifiers());
+ }
+
+ /**
+ * Returns a {@code Class} object that identifies the
+ * declared type for the field represented by this
+ * {@code Field} object.
+ *
+ * @return a {@code Class} object identifying the declared
+ * type of the field represented by this object
+ */
+ public Class> getType() {
+ return type;
+ }
+
+ /**
+ * Returns a {@code Type} object that represents the declared type for
+ * the field represented by this {@code Field} object.
+ *
+ *
If the {@code Type} is a parameterized type, the
+ * {@code Type} object returned must accurately reflect the
+ * actual type parameters used in the source code.
+ *
+ *
If the type of the underlying field is a type variable or a
+ * parameterized type, it is created. Otherwise, it is resolved.
+ *
+ * @return a {@code Type} object that represents the declared type for
+ * the field represented by this {@code Field} object
+ * @throws GenericSignatureFormatError if the generic field
+ * signature does not conform to the format specified in
+ * The Java™ Virtual Machine Specification
+ * @throws TypeNotPresentException if the generic type
+ * signature of the underlying field refers to a non-existent
+ * type declaration
+ * @throws MalformedParameterizedTypeException if the generic
+ * signature of the underlying field refers to a parameterized type
+ * that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type getGenericType() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /**
+ * Compares this {@code Field} against the specified object. Returns
+ * true if the objects are the same. Two {@code Field} objects are the same if
+ * they were declared by the same class and have the same name
+ * and type.
+ */
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof Field) {
+ Field other = (Field)obj;
+ return (getDeclaringClass() == other.getDeclaringClass())
+ && (getName() == other.getName())
+ && (getType() == other.getType());
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hashcode for this {@code Field}. This is computed as the
+ * exclusive-or of the hashcodes for the underlying field's
+ * declaring class name and its name.
+ */
+ public int hashCode() {
+ return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
+ }
+
+ /**
+ * Returns a string describing this {@code Field}. The format is
+ * the access modifiers for the field, if any, followed
+ * by the field type, followed by a space, followed by
+ * the fully-qualified name of the class declaring the field,
+ * followed by a period, followed by the name of the field.
+ * For example:
+ *
+ * public static final int java.lang.Thread.MIN_PRIORITY
+ * private int java.io.FileDescriptor.fd
+ *
+ *
+ *
The modifiers are placed in canonical order as specified by
+ * "The Java Language Specification". This is {@code public},
+ * {@code protected} or {@code private} first, and then other
+ * modifiers in the following order: {@code static}, {@code final},
+ * {@code transient}, {@code volatile}.
+ */
+ public String toString() {
+ int mod = getModifiers();
+ return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
+ + getTypeName(getType()) + " "
+ + getTypeName(getDeclaringClass()) + "."
+ + getName());
+ }
+
+ /**
+ * Returns a string describing this {@code Field}, including
+ * its generic type. The format is the access modifiers for the
+ * field, if any, followed by the generic field type, followed by
+ * a space, followed by the fully-qualified name of the class
+ * declaring the field, followed by a period, followed by the name
+ * of the field.
+ *
+ *
The modifiers are placed in canonical order as specified by
+ * "The Java Language Specification". This is {@code public},
+ * {@code protected} or {@code private} first, and then other
+ * modifiers in the following order: {@code static}, {@code final},
+ * {@code transient}, {@code volatile}.
+ *
+ * @return a string describing this {@code Field}, including
+ * its generic type
+ *
+ * @since 1.5
+ */
+ public String toGenericString() {
+ int mod = getModifiers();
+ Type fieldType = getGenericType();
+ return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
+ + ((fieldType instanceof Class) ?
+ getTypeName((Class)fieldType): fieldType.toString())+ " "
+ + getTypeName(getDeclaringClass()) + "."
+ + getName());
+ }
+
+ /**
+ * Returns the value of the field represented by this {@code Field}, on
+ * the specified object. The value is automatically wrapped in an
+ * object if it has a primitive type.
+ *
+ *
The underlying field's value is obtained as follows:
+ *
+ *
If the underlying field is a static field, the {@code obj} argument
+ * is ignored; it may be null.
+ *
+ *
Otherwise, the underlying field is an instance field. If the
+ * specified {@code obj} argument is null, the method throws a
+ * {@code NullPointerException}. If the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field, the method throws an {@code IllegalArgumentException}.
+ *
+ *
If this {@code Field} object is enforcing Java language access control, and
+ * the underlying field is inaccessible, the method throws an
+ * {@code IllegalAccessException}.
+ * If the underlying field is static, the class that declared the
+ * field is initialized if it has not already been initialized.
+ *
+ *
Otherwise, the value is retrieved from the underlying instance
+ * or static field. If the field has a primitive type, the value
+ * is wrapped in an object before being returned, otherwise it is
+ * returned as is.
+ *
+ *
If the field is hidden in the type of {@code obj},
+ * the field's value is obtained according to the preceding rules.
+ *
+ * @param obj object from which the represented field's value is
+ * to be extracted
+ * @return the value of the represented field in object
+ * {@code obj}; primitive values are wrapped in an appropriate
+ * object before being returned
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof).
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ */
+ public Object get(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).get(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance {@code boolean} field.
+ *
+ * @param obj the object to extract the {@code boolean} value
+ * from
+ * @return the value of the {@code boolean} field
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code boolean} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public boolean getBoolean(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getBoolean(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance {@code byte} field.
+ *
+ * @param obj the object to extract the {@code byte} value
+ * from
+ * @return the value of the {@code byte} field
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code byte} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public byte getByte(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getByte(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code char} or of another primitive type convertible to
+ * type {@code char} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code char} value
+ * from
+ * @return the value of the field converted to type {@code char}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code char} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public char getChar(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getChar(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code short} or of another primitive type convertible to
+ * type {@code short} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code short} value
+ * from
+ * @return the value of the field converted to type {@code short}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code short} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public short getShort(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getShort(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code int} or of another primitive type convertible to
+ * type {@code int} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code int} value
+ * from
+ * @return the value of the field converted to type {@code int}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code int} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public int getInt(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getInt(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code long} or of another primitive type convertible to
+ * type {@code long} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code long} value
+ * from
+ * @return the value of the field converted to type {@code long}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code long} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public long getLong(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getLong(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code float} or of another primitive type convertible to
+ * type {@code float} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code float} value
+ * from
+ * @return the value of the field converted to type {@code float}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code float} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public float getFloat(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getFloat(obj);
+ }
+
+ /**
+ * Gets the value of a static or instance field of type
+ * {@code double} or of another primitive type convertible to
+ * type {@code double} via a widening conversion.
+ *
+ * @param obj the object to extract the {@code double} value
+ * from
+ * @return the value of the field converted to type {@code double}
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is inaccessible.
+ * @exception IllegalArgumentException if the specified object is not
+ * an instance of the class or interface declaring the
+ * underlying field (or a subclass or implementor
+ * thereof), or if the field value cannot be
+ * converted to the type {@code double} by a
+ * widening conversion.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#get
+ */
+ public double getDouble(Object obj)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ return getFieldAccessor(obj).getDouble(obj);
+ }
+
+ /**
+ * Sets the field represented by this {@code Field} object on the
+ * specified object argument to the specified new value. The new
+ * value is automatically unwrapped if the underlying field has a
+ * primitive type.
+ *
+ *
The operation proceeds as follows:
+ *
+ *
If the underlying field is static, the {@code obj} argument is
+ * ignored; it may be null.
+ *
+ *
Otherwise the underlying field is an instance field. If the
+ * specified object argument is null, the method throws a
+ * {@code NullPointerException}. If the specified object argument is not
+ * an instance of the class or interface declaring the underlying
+ * field, the method throws an {@code IllegalArgumentException}.
+ *
+ *
If this {@code Field} object is enforcing Java language access control, and
+ * the underlying field is inaccessible, the method throws an
+ * {@code IllegalAccessException}.
+ *
+ *
If the underlying field is final, the method throws an
+ * {@code IllegalAccessException} unless {@code setAccessible(true)}
+ * has succeeded for this {@code Field} object
+ * and the field is non-static. Setting a final field in this way
+ * is meaningful only during deserialization or reconstruction of
+ * instances of classes with blank final fields, before they are
+ * made available for access by other parts of a program. Use in
+ * any other context may have unpredictable effects, including cases
+ * in which other parts of a program continue to use the original
+ * value of this field.
+ *
+ *
If the underlying field is of a primitive type, an unwrapping
+ * conversion is attempted to convert the new value to a value of
+ * a primitive type. If this attempt fails, the method throws an
+ * {@code IllegalArgumentException}.
+ *
+ *
If, after possible unwrapping, the new value cannot be
+ * converted to the type of the underlying field by an identity or
+ * widening conversion, the method throws an
+ * {@code IllegalArgumentException}.
+ *
+ *
If the underlying field is static, the class that declared the
+ * field is initialized if it has not already been initialized.
+ *
+ *
The field is set to the possibly unwrapped and widened new value.
+ *
+ *
If the field is hidden in the type of {@code obj},
+ * the field's value is set according to the preceding rules.
+ *
+ * @param obj the object whose field should be modified
+ * @param value the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ */
+ public void set(Object obj, Object value)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).set(obj, value);
+ }
+
+ /**
+ * Sets the value of a field as a {@code boolean} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, zObj)},
+ * where {@code zObj} is a {@code Boolean} object and
+ * {@code zObj.booleanValue() == z}.
+ *
+ * @param obj the object whose field should be modified
+ * @param z the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setBoolean(Object obj, boolean z)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setBoolean(obj, z);
+ }
+
+ /**
+ * Sets the value of a field as a {@code byte} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, bObj)},
+ * where {@code bObj} is a {@code Byte} object and
+ * {@code bObj.byteValue() == b}.
+ *
+ * @param obj the object whose field should be modified
+ * @param b the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setByte(Object obj, byte b)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setByte(obj, b);
+ }
+
+ /**
+ * Sets the value of a field as a {@code char} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, cObj)},
+ * where {@code cObj} is a {@code Character} object and
+ * {@code cObj.charValue() == c}.
+ *
+ * @param obj the object whose field should be modified
+ * @param c the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setChar(Object obj, char c)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setChar(obj, c);
+ }
+
+ /**
+ * Sets the value of a field as a {@code short} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, sObj)},
+ * where {@code sObj} is a {@code Short} object and
+ * {@code sObj.shortValue() == s}.
+ *
+ * @param obj the object whose field should be modified
+ * @param s the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setShort(Object obj, short s)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setShort(obj, s);
+ }
+
+ /**
+ * Sets the value of a field as an {@code int} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, iObj)},
+ * where {@code iObj} is a {@code Integer} object and
+ * {@code iObj.intValue() == i}.
+ *
+ * @param obj the object whose field should be modified
+ * @param i the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setInt(Object obj, int i)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setInt(obj, i);
+ }
+
+ /**
+ * Sets the value of a field as a {@code long} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, lObj)},
+ * where {@code lObj} is a {@code Long} object and
+ * {@code lObj.longValue() == l}.
+ *
+ * @param obj the object whose field should be modified
+ * @param l the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setLong(Object obj, long l)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setLong(obj, l);
+ }
+
+ /**
+ * Sets the value of a field as a {@code float} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, fObj)},
+ * where {@code fObj} is a {@code Float} object and
+ * {@code fObj.floatValue() == f}.
+ *
+ * @param obj the object whose field should be modified
+ * @param f the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setFloat(Object obj, float f)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setFloat(obj, f);
+ }
+
+ /**
+ * Sets the value of a field as a {@code double} on the specified object.
+ * This method is equivalent to
+ * {@code set(obj, dObj)},
+ * where {@code dObj} is a {@code Double} object and
+ * {@code dObj.doubleValue() == d}.
+ *
+ * @param obj the object whose field should be modified
+ * @param d the new value for the field of {@code obj}
+ * being modified
+ *
+ * @exception IllegalAccessException if this {@code Field} object
+ * is enforcing Java language access control and the underlying
+ * field is either inaccessible or final.
+ * @exception IllegalArgumentException if the specified object is not an
+ * instance of the class or interface declaring the underlying
+ * field (or a subclass or implementor thereof),
+ * or if an unwrapping conversion fails.
+ * @exception NullPointerException if the specified object is null
+ * and the field is an instance field.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ * @see Field#set
+ */
+ public void setDouble(Object obj, double d)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ getFieldAccessor(obj).setDouble(obj, d);
+ }
+
+ // Convenience routine which performs security checks
+ private FieldAccessor getFieldAccessor(Object obj)
+ throws IllegalAccessException
+ {
+ throw new SecurityException();
+ }
+
+ private static abstract class FieldAccessor {
+ abstract void setShort(Object obj, short s);
+ abstract void setInt(Object obj, int i);
+ abstract void setChar(Object obj, char c);
+ abstract void setByte(Object obj, byte b);
+ abstract void setBoolean(Object obj, boolean z);
+ abstract void set(Object obj, Object value);
+ abstract double getDouble(Object obj);
+ abstract void setLong(Object obj, long l);
+ abstract void setFloat(Object obj, float f);
+ abstract void setDouble(Object obj, double d);
+ abstract long getLong(Object obj);
+ abstract int getInt(Object obj);
+ abstract short getShort(Object obj);
+ abstract char getChar(Object obj);
+ abstract byte getByte(Object obj);
+ abstract boolean getBoolean(Object obj);
+ abstract Object get(Object obj);
+ abstract float getFloat(Object obj);
+ }
+
+ /*
+ * Utility routine to paper over array type names
+ */
+ static String getTypeName(Class> type) {
+ if (type.isArray()) {
+ try {
+ Class> cl = type;
+ int dimensions = 0;
+ while (cl.isArray()) {
+ dimensions++;
+ cl = cl.getComponentType();
+ }
+ StringBuffer sb = new StringBuffer();
+ sb.append(cl.getName());
+ for (int i = 0; i < dimensions; i++) {
+ sb.append("[]");
+ }
+ return sb.toString();
+ } catch (Throwable e) { /*FALLTHRU*/ }
+ }
+ return type.getName();
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public T getAnnotation(Class annotationClass) {
+ if (annotationClass == null)
+ throw new NullPointerException();
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ throw new UnsupportedOperationException();
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/GenericDeclaration.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/GenericDeclaration.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * A common interface for all entities that declare type variables.
+ *
+ * @since 1.5
+ */
+public interface GenericDeclaration {
+ /**
+ * Returns an array of {@code TypeVariable} objects that
+ * represent the type variables declared by the generic
+ * declaration represented by this {@code GenericDeclaration}
+ * object, in declaration order. Returns an array of length 0 if
+ * the underlying generic declaration declares no type variables.
+ *
+ * @return an array of {@code TypeVariable} objects that represent
+ * the type variables declared by this generic declaration
+ * @throws GenericSignatureFormatError if the generic
+ * signature of this generic declaration does not conform to
+ * the format specified in
+ * The Java™ Virtual Machine Specification
+ */
+ public TypeVariable>[] getTypeParameters();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/InvocationTargetException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/InvocationTargetException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * InvocationTargetException is a checked exception that wraps
+ * an exception thrown by an invoked method or constructor.
+ *
+ *
As of release 1.4, this exception has been retrofitted to conform to
+ * the general purpose exception-chaining mechanism. The "target exception"
+ * that is provided at construction time and accessed via the
+ * {@link #getTargetException()} method is now known as the cause,
+ * and may be accessed via the {@link Throwable#getCause()} method,
+ * as well as the aforementioned "legacy method."
+ *
+ * @see Method
+ * @see Constructor
+ */
+public class InvocationTargetException extends ReflectiveOperationException {
+ /**
+ * Use serialVersionUID from JDK 1.1.X for interoperability
+ */
+ private static final long serialVersionUID = 4085088731926701167L;
+
+ /**
+ * This field holds the target if the
+ * InvocationTargetException(Throwable target) constructor was
+ * used to instantiate the object
+ *
+ * @serial
+ *
+ */
+ private Throwable target;
+
+ /**
+ * Constructs an {@code InvocationTargetException} with
+ * {@code null} as the target exception.
+ */
+ protected InvocationTargetException() {
+ super((Throwable)null); // Disallow initCause
+ }
+
+ /**
+ * Constructs a InvocationTargetException with a target exception.
+ *
+ * @param target the target exception
+ */
+ public InvocationTargetException(Throwable target) {
+ super((Throwable)null); // Disallow initCause
+ this.target = target;
+ }
+
+ /**
+ * Constructs a InvocationTargetException with a target exception
+ * and a detail message.
+ *
+ * @param target the target exception
+ * @param s the detail message
+ */
+ public InvocationTargetException(Throwable target, String s) {
+ super(s, null); // Disallow initCause
+ this.target = target;
+ }
+
+ /**
+ * Get the thrown target exception.
+ *
+ *
This method predates the general-purpose exception chaining facility.
+ * The {@link Throwable#getCause()} method is now the preferred means of
+ * obtaining this information.
+ *
+ * @return the thrown target exception (cause of this exception).
+ */
+ public Throwable getTargetException() {
+ return target;
+ }
+
+ /**
+ * Returns the cause of this exception (the thrown target exception,
+ * which may be {@code null}).
+ *
+ * @return the cause of this exception.
+ * @since 1.4
+ */
+ public Throwable getCause() {
+ return target;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Member.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Member.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * Member is an interface that reflects identifying information about
+ * a single member (a field or a method) or a constructor.
+ *
+ * @see java.lang.Class
+ * @see Field
+ * @see Method
+ * @see Constructor
+ *
+ * @author Nakul Saraiya
+ */
+public
+interface Member {
+
+ /**
+ * Identifies the set of all public members of a class or interface,
+ * including inherited members.
+ * @see java.lang.SecurityManager#checkMemberAccess
+ */
+ public static final int PUBLIC = 0;
+
+ /**
+ * Identifies the set of declared members of a class or interface.
+ * Inherited members are not included.
+ * @see java.lang.SecurityManager#checkMemberAccess
+ */
+ public static final int DECLARED = 1;
+
+ /**
+ * Returns the Class object representing the class or interface
+ * that declares the member or constructor represented by this Member.
+ *
+ * @return an object representing the declaring class of the
+ * underlying member
+ */
+ public Class> getDeclaringClass();
+
+ /**
+ * Returns the simple name of the underlying member or constructor
+ * represented by this Member.
+ *
+ * @return the simple name of the underlying member
+ */
+ public String getName();
+
+ /**
+ * Returns the Java language modifiers for the member or
+ * constructor represented by this Member, as an integer. The
+ * Modifier class should be used to decode the modifiers in
+ * the integer.
+ *
+ * @return the Java language modifiers for the underlying member
+ * @see Modifier
+ */
+ public int getModifiers();
+
+ /**
+ * Returns {@code true} if this member was introduced by
+ * the compiler; returns {@code false} otherwise.
+ *
+ * @return true if and only if this member was introduced by
+ * the compiler.
+ * @since 1.5
+ */
+ public boolean isSynthetic();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Method.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Method.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+import java.util.Enumeration;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.emul.AnnotationImpl;
+import org.apidesign.bck2brwsr.emul.MethodImpl;
+
+/**
+ * A {@code Method} provides information about, and access to, a single method
+ * on a class or interface. The reflected method may be a class method
+ * or an instance method (including an abstract method).
+ *
+ *
A {@code Method} permits widening conversions to occur when matching the
+ * actual parameters to invoke with the underlying method's formal
+ * parameters, but it throws an {@code IllegalArgumentException} if a
+ * narrowing conversion would occur.
+ *
+ * @see Member
+ * @see java.lang.Class
+ * @see java.lang.Class#getMethods()
+ * @see java.lang.Class#getMethod(String, Class[])
+ * @see java.lang.Class#getDeclaredMethods()
+ * @see java.lang.Class#getDeclaredMethod(String, Class[])
+ *
+ * @author Kenneth Russell
+ * @author Nakul Saraiya
+ */
+public final
+ class Method extends AccessibleObject implements GenericDeclaration,
+ Member {
+ private final Class> clazz;
+ private final String name;
+ private final Object data;
+ private final String sig;
+
+ // Generics infrastructure
+
+ private String getGenericSignature() {return null;}
+
+ /**
+ * Package-private constructor used by ReflectAccess to enable
+ * instantiation of these objects in Java code from the java.lang
+ * package via sun.reflect.LangReflectAccess.
+ */
+ Method(Class> declaringClass, String name, Object data, String sig)
+ {
+ this.clazz = declaringClass;
+ this.name = name;
+ this.data = data;
+ this.sig = sig;
+ }
+
+ /**
+ * Package-private routine (exposed to java.lang.Class via
+ * ReflectAccess) which returns a copy of this Method. The copy's
+ * "root" field points to this Method.
+ */
+ Method copy() {
+ return this;
+ }
+
+ /**
+ * Returns the {@code Class} object representing the class or interface
+ * that declares the method represented by this {@code Method} object.
+ */
+ public Class> getDeclaringClass() {
+ return clazz;
+ }
+
+ /**
+ * Returns the name of the method represented by this {@code Method}
+ * object, as a {@code String}.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the Java language modifiers for the method represented
+ * by this {@code Method} object, as an integer. The {@code Modifier} class should
+ * be used to decode the modifiers.
+ *
+ * @see Modifier
+ */
+ public int getModifiers() {
+ return getAccess(data);
+ }
+
+ @JavaScriptBody(args = "self", body = "return self.access;")
+ private static native int getAccess(Object self);
+
+ /**
+ * Returns an array of {@code TypeVariable} objects that represent the
+ * type variables declared by the generic declaration represented by this
+ * {@code GenericDeclaration} object, in declaration order. Returns an
+ * array of length 0 if the underlying generic declaration declares no type
+ * variables.
+ *
+ * @return an array of {@code TypeVariable} objects that represent
+ * the type variables declared by this generic declaration
+ * @throws GenericSignatureFormatError if the generic
+ * signature of this generic declaration does not conform to
+ * the format specified in
+ * The Java™ Virtual Machine Specification
+ * @since 1.5
+ */
+ public TypeVariable[] getTypeParameters() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a {@code Class} object that represents the formal return type
+ * of the method represented by this {@code Method} object.
+ *
+ * @return the return type for the method this object represents
+ */
+ public Class> getReturnType() {
+ return MethodImpl.signatureParser(sig).nextElement();
+ }
+
+ /**
+ * Returns a {@code Type} object that represents the formal return
+ * type of the method represented by this {@code Method} object.
+ *
+ *
If the return type is a parameterized type,
+ * the {@code Type} object returned must accurately reflect
+ * the actual type parameters used in the source code.
+ *
+ *
If the return type is a type variable or a parameterized type, it
+ * is created. Otherwise, it is resolved.
+ *
+ * @return a {@code Type} object that represents the formal return
+ * type of the underlying method
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in
+ * The Java™ Virtual Machine Specification
+ * @throws TypeNotPresentException if the underlying method's
+ * return type refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if the
+ * underlying method's return typed refers to a parameterized
+ * type that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type getGenericReturnType() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /**
+ * Returns an array of {@code Class} objects that represent the formal
+ * parameter types, in declaration order, of the method
+ * represented by this {@code Method} object. Returns an array of length
+ * 0 if the underlying method takes no parameters.
+ *
+ * @return the parameter types for the method this object
+ * represents
+ */
+ public Class>[] getParameterTypes() {
+ Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1];
+ Enumeration en = MethodImpl.signatureParser(sig);
+ en.nextElement(); // return type
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = en.nextElement();
+ }
+ return arr;
+ }
+
+ /**
+ * Returns an array of {@code Type} objects that represent the formal
+ * parameter types, in declaration order, of the method represented by
+ * this {@code Method} object. Returns an array of length 0 if the
+ * underlying method takes no parameters.
+ *
+ *
If a formal parameter type is a parameterized type,
+ * the {@code Type} object returned for it must accurately reflect
+ * the actual type parameters used in the source code.
+ *
+ *
If a formal parameter type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of Types that represent the formal
+ * parameter types of the underlying method, in declaration order
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in
+ * The Java™ Virtual Machine Specification
+ * @throws TypeNotPresentException if any of the parameter
+ * types of the underlying method refers to a non-existent type
+ * declaration
+ * @throws MalformedParameterizedTypeException if any of
+ * the underlying method's parameter types refer to a parameterized
+ * type that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /**
+ * Returns an array of {@code Class} objects that represent
+ * the types of the exceptions declared to be thrown
+ * by the underlying method
+ * represented by this {@code Method} object. Returns an array of length
+ * 0 if the method declares no exceptions in its {@code throws} clause.
+ *
+ * @return the exception types declared as being thrown by the
+ * method this object represents
+ */
+ public Class>[] getExceptionTypes() {
+ throw new UnsupportedOperationException();
+ //return (Class>[]) exceptionTypes.clone();
+ }
+
+ /**
+ * Returns an array of {@code Type} objects that represent the
+ * exceptions declared to be thrown by this {@code Method} object.
+ * Returns an array of length 0 if the underlying method declares
+ * no exceptions in its {@code throws} clause.
+ *
+ *
If an exception type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of Types that represent the exception types
+ * thrown by the underlying method
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in
+ * The Java™ Virtual Machine Specification
+ * @throws TypeNotPresentException if the underlying method's
+ * {@code throws} clause refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if
+ * the underlying method's {@code throws} clause refers to a
+ * parameterized type that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Compares this {@code Method} against the specified object. Returns
+ * true if the objects are the same. Two {@code Methods} are the same if
+ * they were declared by the same class and have the same name
+ * and formal parameter types and return type.
+ */
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof Method) {
+ Method other = (Method)obj;
+ return data == other.data;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hashcode for this {@code Method}. The hashcode is computed
+ * as the exclusive-or of the hashcodes for the underlying
+ * method's declaring class name and the method's name.
+ */
+ public int hashCode() {
+ return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
+ }
+
+ /**
+ * Returns a string describing this {@code Method}. The string is
+ * formatted as the method access modifiers, if any, followed by
+ * the method return type, followed by a space, followed by the
+ * class declaring the method, followed by a period, followed by
+ * the method name, followed by a parenthesized, comma-separated
+ * list of the method's formal parameter types. If the method
+ * throws checked exceptions, the parameter list is followed by a
+ * space, followed by the word throws followed by a
+ * comma-separated list of the thrown exception types.
+ * For example:
+ *
+ * public boolean java.lang.Object.equals(java.lang.Object)
+ *
+ *
+ *
The access modifiers are placed in canonical order as
+ * specified by "The Java Language Specification". This is
+ * {@code public}, {@code protected} or {@code private} first,
+ * and then other modifiers in the following order:
+ * {@code abstract}, {@code static}, {@code final},
+ * {@code synchronized}, {@code native}, {@code strictfp}.
+ */
+ public String toString() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ int mod = getModifiers() & Modifier.methodModifiers();
+ if (mod != 0) {
+ sb.append(Modifier.toString(mod)).append(' ');
+ }
+ sb.append(Field.getTypeName(getReturnType())).append(' ');
+ sb.append(Field.getTypeName(getDeclaringClass())).append('.');
+ sb.append(getName()).append('(');
+ Class>[] params = getParameterTypes(); // avoid clone
+ for (int j = 0; j < params.length; j++) {
+ sb.append(Field.getTypeName(params[j]));
+ if (j < (params.length - 1))
+ sb.append(',');
+ }
+ sb.append(')');
+ /*
+ Class>[] exceptions = exceptionTypes; // avoid clone
+ if (exceptions.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptions.length; k++) {
+ sb.append(exceptions[k].getName());
+ if (k < (exceptions.length - 1))
+ sb.append(',');
+ }
+ }
+ */
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Returns a string describing this {@code Method}, including
+ * type parameters. The string is formatted as the method access
+ * modifiers, if any, followed by an angle-bracketed
+ * comma-separated list of the method's type parameters, if any,
+ * followed by the method's generic return type, followed by a
+ * space, followed by the class declaring the method, followed by
+ * a period, followed by the method name, followed by a
+ * parenthesized, comma-separated list of the method's generic
+ * formal parameter types.
+ *
+ * If this method was declared to take a variable number of
+ * arguments, instead of denoting the last parameter as
+ * "Type[]", it is denoted as
+ * "Type...".
+ *
+ * A space is used to separate access modifiers from one another
+ * and from the type parameters or return type. If there are no
+ * type parameters, the type parameter list is elided; if the type
+ * parameter list is present, a space separates the list from the
+ * class name. If the method is declared to throw exceptions, the
+ * parameter list is followed by a space, followed by the word
+ * throws followed by a comma-separated list of the generic thrown
+ * exception types. If there are no type parameters, the type
+ * parameter list is elided.
+ *
+ *
The access modifiers are placed in canonical order as
+ * specified by "The Java Language Specification". This is
+ * {@code public}, {@code protected} or {@code private} first,
+ * and then other modifiers in the following order:
+ * {@code abstract}, {@code static}, {@code final},
+ * {@code synchronized}, {@code native}, {@code strictfp}.
+ *
+ * @return a string describing this {@code Method},
+ * include type parameters
+ *
+ * @since 1.5
+ */
+ public String toGenericString() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ int mod = getModifiers() & Modifier.methodModifiers();
+ if (mod != 0) {
+ sb.append(Modifier.toString(mod)).append(' ');
+ }
+ TypeVariable>[] typeparms = getTypeParameters();
+ if (typeparms.length > 0) {
+ boolean first = true;
+ sb.append('<');
+ for(TypeVariable> typeparm: typeparms) {
+ if (!first)
+ sb.append(',');
+ // Class objects can't occur here; no need to test
+ // and call Class.getName().
+ sb.append(typeparm.toString());
+ first = false;
+ }
+ sb.append("> ");
+ }
+
+ Type genRetType = getGenericReturnType();
+ sb.append( ((genRetType instanceof Class>)?
+ Field.getTypeName((Class>)genRetType):genRetType.toString()))
+ .append(' ');
+
+ sb.append(Field.getTypeName(getDeclaringClass())).append('.');
+ sb.append(getName()).append('(');
+ Type[] params = getGenericParameterTypes();
+ for (int j = 0; j < params.length; j++) {
+ String param = (params[j] instanceof Class)?
+ Field.getTypeName((Class)params[j]):
+ (params[j].toString());
+ if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
+ param = param.replaceFirst("\\[\\]$", "...");
+ sb.append(param);
+ if (j < (params.length - 1))
+ sb.append(',');
+ }
+ sb.append(')');
+ Type[] exceptions = getGenericExceptionTypes();
+ if (exceptions.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptions.length; k++) {
+ sb.append((exceptions[k] instanceof Class)?
+ ((Class)exceptions[k]).getName():
+ exceptions[k].toString());
+ if (k < (exceptions.length - 1))
+ sb.append(',');
+ }
+ }
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Invokes the underlying method represented by this {@code Method}
+ * object, on the specified object with the specified parameters.
+ * Individual parameters are automatically unwrapped to match
+ * primitive formal parameters, and both primitive and reference
+ * parameters are subject to method invocation conversions as
+ * necessary.
+ *
+ *
If the underlying method is static, then the specified {@code obj}
+ * argument is ignored. It may be null.
+ *
+ *
If the number of formal parameters required by the underlying method is
+ * 0, the supplied {@code args} array may be of length 0 or null.
+ *
+ *
If the underlying method is an instance method, it is invoked
+ * using dynamic method lookup as documented in The Java Language
+ * Specification, Second Edition, section 15.12.4.4; in particular,
+ * overriding based on the runtime type of the target object will occur.
+ *
+ *
If the underlying method is static, the class that declared
+ * the method is initialized if it has not already been initialized.
+ *
+ *
If the method completes normally, the value it returns is
+ * returned to the caller of invoke; if the value has a primitive
+ * type, it is first appropriately wrapped in an object. However,
+ * if the value has the type of an array of a primitive type, the
+ * elements of the array are not wrapped in objects; in
+ * other words, an array of primitive type is returned. If the
+ * underlying method return type is void, the invocation returns
+ * null.
+ *
+ * @param obj the object the underlying method is invoked from
+ * @param args the arguments used for the method call
+ * @return the result of dispatching the method represented by
+ * this object on {@code obj} with parameters
+ * {@code args}
+ *
+ * @exception IllegalAccessException if this {@code Method} object
+ * is enforcing Java language access control and the underlying
+ * method is inaccessible.
+ * @exception IllegalArgumentException if the method is an
+ * instance method and the specified object argument
+ * is not an instance of the class or interface
+ * declaring the underlying method (or of a subclass
+ * or implementor thereof); if the number of actual
+ * and formal parameters differ; if an unwrapping
+ * conversion for primitive arguments fails; or if,
+ * after possible unwrapping, a parameter value
+ * cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion.
+ * @exception InvocationTargetException if the underlying method
+ * throws an exception.
+ * @exception NullPointerException if the specified object is null
+ * and the method is an instance method.
+ * @exception ExceptionInInitializerError if the initialization
+ * provoked by this method fails.
+ */
+ public Object invoke(Object obj, Object... args)
+ throws IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException
+ {
+ final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
+ if (isStatic && obj == null) {
+ throw new NullPointerException();
+ }
+ Class[] types = getParameterTypes();
+ if (types.length != args.length) {
+ throw new IllegalArgumentException("Types len " + types.length + " args: " + args.length);
+ } else {
+ args = args.clone();
+ for (int i = 0; i < types.length; i++) {
+ Class c = types[i];
+ if (c.isPrimitive()) {
+ args[i] = toPrimitive(c, args[i]);
+ }
+ }
+ }
+ Object res = invoke0(isStatic, this, obj, args);
+ if (getReturnType().isPrimitive()) {
+ res = fromPrimitive(getReturnType(), res);
+ }
+ return res;
+ }
+
+ @JavaScriptBody(args = { "st", "method", "self", "args" }, body =
+ "var p;\n"
+ + "if (st) {\n"
+ + " p = new Array(1);\n"
+ + " p[0] = self;\n"
+ + " p = p.concat(args);\n"
+ + "} else {\n"
+ + " p = args;\n"
+ + "}\n"
+ + "return method.fld_data.apply(self, p);\n"
+ )
+ private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
+
+ static Object fromPrimitive(Class> type, Object o) {
+ if (type == Integer.TYPE) {
+ return fromRaw(Integer.class, "valueOf__Ljava_lang_Integer_2I", o);
+ }
+ if (type == Long.TYPE) {
+ return fromRaw(Long.class, "valueOf__Ljava_lang_Long_2J", o);
+ }
+ if (type == Double.TYPE) {
+ return fromRaw(Double.class, "valueOf__Ljava_lang_Double_2D", o);
+ }
+ if (type == Float.TYPE) {
+ return fromRaw(Float.class, "valueOf__Ljava_lang_Float_2F", o);
+ }
+ if (type == Byte.TYPE) {
+ return fromRaw(Byte.class, "valueOf__Ljava_lang_Byte_2B", o);
+ }
+ if (type == Boolean.TYPE) {
+ return fromRaw(Boolean.class, "valueOf__Ljava_lang_Boolean_2Z", o);
+ }
+ if (type == Short.TYPE) {
+ return fromRaw(Short.class, "valueOf__Ljava_lang_Short_2S", o);
+ }
+ if (type == Character.TYPE) {
+ return fromRaw(Character.class, "valueOf__Ljava_lang_Character_2C", o);
+ }
+ if (type.getName().equals("void")) {
+ return null;
+ }
+ throw new IllegalStateException("Can't convert " + o);
+ }
+
+ @JavaScriptBody(args = { "cls", "m", "o" },
+ body = "return cls.cnstr(false)[m](o);"
+ )
+ private static native Integer fromRaw(Class> cls, String m, Object o);
+
+ private static Object toPrimitive(Class> type, Object o) {
+ if (type == Integer.TYPE) {
+ return toRaw("intValue__I", o);
+ }
+ if (type == Long.TYPE) {
+ return toRaw("longValue__J", o);
+ }
+ if (type == Double.TYPE) {
+ return toRaw("doubleValue__D", o);
+ }
+ if (type == Float.TYPE) {
+ return toRaw("floatValue__F", o);
+ }
+ if (type == Byte.TYPE) {
+ return toRaw("byteValue__B", o);
+ }
+ if (type == Boolean.TYPE) {
+ return toRaw("booleanValue__Z", o);
+ }
+ if (type == Short.TYPE) {
+ return toRaw("shortValue__S", o);
+ }
+ if (type == Character.TYPE) {
+ return toRaw("charValue__C", o);
+ }
+ if (type.getName().equals("void")) {
+ return o;
+ }
+ throw new IllegalStateException("Can't convert " + o);
+ }
+
+ @JavaScriptBody(args = { "m", "o" },
+ body = "return o[m](o);"
+ )
+ private static native Object toRaw(String m, Object o);
+
+ /**
+ * Returns {@code true} if this method is a bridge
+ * method; returns {@code false} otherwise.
+ *
+ * @return true if and only if this method is a bridge
+ * method as defined by the Java Language Specification.
+ * @since 1.5
+ */
+ public boolean isBridge() {
+ return (getModifiers() & Modifier.BRIDGE) != 0;
+ }
+
+ /**
+ * Returns {@code true} if this method was declared to take
+ * a variable number of arguments; returns {@code false}
+ * otherwise.
+ *
+ * @return {@code true} if an only if this method was declared to
+ * take a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs() {
+ return (getModifiers() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Returns {@code true} if this method is a synthetic
+ * method; returns {@code false} otherwise.
+ *
+ * @return true if and only if this method is a synthetic
+ * method as defined by the Java Language Specification.
+ * @since 1.5
+ */
+ public boolean isSynthetic() {
+ return Modifier.isSynthetic(getModifiers());
+ }
+
+ @JavaScriptBody(args = { "ac" },
+ body =
+ "if (this.fld_data.anno) {"
+ + " return this.fld_data.anno['L' + ac.jvmName + ';'];"
+ + "} else return null;"
+ )
+ private Object getAnnotationData(Class> annotationClass) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public T getAnnotation(Class annotationClass) {
+ Object data = getAnnotationData(annotationClass);
+ return data == null ? null : AnnotationImpl.create(annotationClass, data);
+ }
+
+ /**
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the default value for the annotation member represented by
+ * this {@code Method} instance. If the member is of a primitive type,
+ * an instance of the corresponding wrapper type is returned. Returns
+ * null if no default is associated with the member, or if the method
+ * instance does not represent a declared member of an annotation type.
+ *
+ * @return the default value for the annotation member represented
+ * by this {@code Method} instance.
+ * @throws TypeNotPresentException if the annotation is of type
+ * {@link Class} and no definition can be found for the
+ * default class value.
+ * @since 1.5
+ */
+ public Object getDefaultValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns an array of arrays that represent the annotations on the formal
+ * parameters, in declaration order, of the method represented by
+ * this {@code Method} object. (Returns an array of length zero if the
+ * underlying method is parameterless. If the method has one or more
+ * parameters, a nested array of length zero is returned for each parameter
+ * with no annotations.) The annotation objects contained in the returned
+ * arrays are serializable. The caller of this method is free to modify
+ * the returned arrays; it will have no effect on the arrays returned to
+ * other callers.
+ *
+ * @return an array of arrays that represent the annotations on the formal
+ * parameters, in declaration order, of the method represented by this
+ * Method object
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations() {
+ throw new UnsupportedOperationException();
+ }
+
+ static {
+ MethodImpl.INSTANCE = new MethodImpl() {
+ protected Method create(Class> declaringClass, String name, Object data, String sig) {
+ return new Method(declaringClass, name, data, sig);
+ }
+ };
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Modifier.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Modifier.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * The Modifier class provides {@code static} methods and
+ * constants to decode class and member access modifiers. The sets of
+ * modifiers are represented as integers with distinct bit positions
+ * representing different modifiers. The values for the constants
+ * representing the modifiers are taken from the tables in sections 4.1, 4.4, 4.5, and 4.7 of
+ * The Java™ Virtual Machine Specification.
+ *
+ * @see Class#getModifiers()
+ * @see Member#getModifiers()
+ *
+ * @author Nakul Saraiya
+ * @author Kenneth Russell
+ */
+public
+class Modifier {
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code public} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code public} modifier; {@code false} otherwise.
+ */
+ public static boolean isPublic(int mod) {
+ return (mod & PUBLIC) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code private} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code private} modifier; {@code false} otherwise.
+ */
+ public static boolean isPrivate(int mod) {
+ return (mod & PRIVATE) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code protected} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code protected} modifier; {@code false} otherwise.
+ */
+ public static boolean isProtected(int mod) {
+ return (mod & PROTECTED) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code static} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code static} modifier; {@code false} otherwise.
+ */
+ public static boolean isStatic(int mod) {
+ return (mod & STATIC) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code final} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code final} modifier; {@code false} otherwise.
+ */
+ public static boolean isFinal(int mod) {
+ return (mod & FINAL) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code synchronized} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code synchronized} modifier; {@code false} otherwise.
+ */
+ public static boolean isSynchronized(int mod) {
+ return (mod & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code volatile} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code volatile} modifier; {@code false} otherwise.
+ */
+ public static boolean isVolatile(int mod) {
+ return (mod & VOLATILE) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code transient} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code transient} modifier; {@code false} otherwise.
+ */
+ public static boolean isTransient(int mod) {
+ return (mod & TRANSIENT) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code native} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code native} modifier; {@code false} otherwise.
+ */
+ public static boolean isNative(int mod) {
+ return (mod & NATIVE) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code interface} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code interface} modifier; {@code false} otherwise.
+ */
+ public static boolean isInterface(int mod) {
+ return (mod & INTERFACE) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code abstract} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code abstract} modifier; {@code false} otherwise.
+ */
+ public static boolean isAbstract(int mod) {
+ return (mod & ABSTRACT) != 0;
+ }
+
+ /**
+ * Return {@code true} if the integer argument includes the
+ * {@code strictfp} modifier, {@code false} otherwise.
+ *
+ * @param mod a set of modifiers
+ * @return {@code true} if {@code mod} includes the
+ * {@code strictfp} modifier; {@code false} otherwise.
+ */
+ public static boolean isStrict(int mod) {
+ return (mod & STRICT) != 0;
+ }
+
+ /**
+ * Return a string describing the access modifier flags in
+ * the specified modifier. For example:
+ *
+ * public final synchronized strictfp
+ *
+ * The modifier names are returned in an order consistent with the
+ * suggested modifier orderings given in sections 8.1.1, 8.3.1, 8.4.3, 8.8.3, and 9.1.1 of
+ * The Java™ Language Specification.
+ * The full modifier ordering used by this method is:
+ *
{@code
+ * public protected private abstract static final transient
+ * volatile synchronized native strictfp
+ * interface }
+ * The {@code interface} modifier discussed in this class is
+ * not a true modifier in the Java language and it appears after
+ * all other modifiers listed by this method. This method may
+ * return a string of modifiers that are not valid modifiers of a
+ * Java entity; in other words, no checking is done on the
+ * possible validity of the combination of modifiers represented
+ * by the input.
+ *
+ * Note that to perform such checking for a known kind of entity,
+ * such as a constructor or method, first AND the argument of
+ * {@code toString} with the appropriate mask from a method like
+ * {@link #constructorModifiers} or {@link #methodModifiers}.
+ *
+ * @param mod a set of modifiers
+ * @return a string representation of the set of modifiers
+ * represented by {@code mod}
+ */
+ public static String toString(int mod) {
+ StringBuffer sb = new StringBuffer();
+ int len;
+
+ if ((mod & PUBLIC) != 0) sb.append("public ");
+ if ((mod & PROTECTED) != 0) sb.append("protected ");
+ if ((mod & PRIVATE) != 0) sb.append("private ");
+
+ /* Canonical order */
+ if ((mod & ABSTRACT) != 0) sb.append("abstract ");
+ if ((mod & STATIC) != 0) sb.append("static ");
+ if ((mod & FINAL) != 0) sb.append("final ");
+ if ((mod & TRANSIENT) != 0) sb.append("transient ");
+ if ((mod & VOLATILE) != 0) sb.append("volatile ");
+ if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized ");
+ if ((mod & NATIVE) != 0) sb.append("native ");
+ if ((mod & STRICT) != 0) sb.append("strictfp ");
+ if ((mod & INTERFACE) != 0) sb.append("interface ");
+
+ if ((len = sb.length()) > 0) /* trim trailing space */
+ return sb.toString().substring(0, len-1);
+ return "";
+ }
+
+ /*
+ * Access modifier flag constants from tables 4.1, 4.4, 4.5, and 4.7 of
+ * The Java™ Virtual Machine Specification
+ */
+
+ /**
+ * The {@code int} value representing the {@code public}
+ * modifier.
+ */
+ public static final int PUBLIC = 0x00000001;
+
+ /**
+ * The {@code int} value representing the {@code private}
+ * modifier.
+ */
+ public static final int PRIVATE = 0x00000002;
+
+ /**
+ * The {@code int} value representing the {@code protected}
+ * modifier.
+ */
+ public static final int PROTECTED = 0x00000004;
+
+ /**
+ * The {@code int} value representing the {@code static}
+ * modifier.
+ */
+ public static final int STATIC = 0x00000008;
+
+ /**
+ * The {@code int} value representing the {@code final}
+ * modifier.
+ */
+ public static final int FINAL = 0x00000010;
+
+ /**
+ * The {@code int} value representing the {@code synchronized}
+ * modifier.
+ */
+ public static final int SYNCHRONIZED = 0x00000020;
+
+ /**
+ * The {@code int} value representing the {@code volatile}
+ * modifier.
+ */
+ public static final int VOLATILE = 0x00000040;
+
+ /**
+ * The {@code int} value representing the {@code transient}
+ * modifier.
+ */
+ public static final int TRANSIENT = 0x00000080;
+
+ /**
+ * The {@code int} value representing the {@code native}
+ * modifier.
+ */
+ public static final int NATIVE = 0x00000100;
+
+ /**
+ * The {@code int} value representing the {@code interface}
+ * modifier.
+ */
+ public static final int INTERFACE = 0x00000200;
+
+ /**
+ * The {@code int} value representing the {@code abstract}
+ * modifier.
+ */
+ public static final int ABSTRACT = 0x00000400;
+
+ /**
+ * The {@code int} value representing the {@code strictfp}
+ * modifier.
+ */
+ public static final int STRICT = 0x00000800;
+
+ // Bits not (yet) exposed in the public API either because they
+ // have different meanings for fields and methods and there is no
+ // way to distinguish between the two in this class, or because
+ // they are not Java programming language keywords
+ static final int BRIDGE = 0x00000040;
+ static final int VARARGS = 0x00000080;
+ static final int SYNTHETIC = 0x00001000;
+ static final int ANNOTATION= 0x00002000;
+ static final int ENUM = 0x00004000;
+ static boolean isSynthetic(int mod) {
+ return (mod & SYNTHETIC) != 0;
+ }
+
+ /**
+ * See JLSv3 section 8.1.1.
+ */
+ private static final int CLASS_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL |
+ Modifier.STRICT;
+
+ /**
+ * See JLSv3 section 9.1.1.
+ */
+ private static final int INTERFACE_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.STRICT;
+
+
+ /**
+ * See JLSv3 section 8.8.3.
+ */
+ private static final int CONSTRUCTOR_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
+
+ /**
+ * See JLSv3 section 8.4.3.
+ */
+ private static final int METHOD_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL |
+ Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.STRICT;
+
+ /**
+ * See JLSv3 section 8.3.1.
+ */
+ private static final int FIELD_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT |
+ Modifier.VOLATILE;
+
+ /**
+ * Return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a class.
+ * @return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a class.
+ *
+ * @jls 8.1.1 Class Modifiers
+ * @since 1.7
+ */
+ public static int classModifiers() {
+ return CLASS_MODIFIERS;
+ }
+
+ /**
+ * Return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to an interface.
+ * @return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to an inteface.
+ *
+ * @jls 9.1.1 Interface Modifiers
+ * @since 1.7
+ */
+ public static int interfaceModifiers() {
+ return INTERFACE_MODIFIERS;
+ }
+
+ /**
+ * Return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a constructor.
+ * @return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a constructor.
+ *
+ * @jls 8.8.3 Constructor Modifiers
+ * @since 1.7
+ */
+ public static int constructorModifiers() {
+ return CONSTRUCTOR_MODIFIERS;
+ }
+
+ /**
+ * Return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a method.
+ * @return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a method.
+ *
+ * @jls 8.4.3 Method Modifiers
+ * @since 1.7
+ */
+ public static int methodModifiers() {
+ return METHOD_MODIFIERS;
+ }
+
+
+ /**
+ * Return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a field.
+ * @return an {@code int} value OR-ing together the source language
+ * modifiers that can be applied to a field.
+ *
+ * @jls 8.3.1 Field Modifiers
+ * @since 1.7
+ */
+ public static int fieldModifiers() {
+ return FIELD_MODIFIERS;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Type.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/Type.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * Type is the common superinterface for all types in the Java
+ * programming language. These include raw types, parameterized types,
+ * array types, type variables and primitive types.
+ *
+ * @since 1.5
+ */
+
+public interface Type {
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/TypeVariable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/TypeVariable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * TypeVariable is the common superinterface for type variables of kinds.
+ * A type variable is created the first time it is needed by a reflective
+ * method, as specified in this package. If a type variable t is referenced
+ * by a type (i.e, class, interface or annotation type) T, and T is declared
+ * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t
+ * requires the resolution (see JVMS 5) of the ith enclosing class of T,
+ * for i = 0 to n, inclusive. Creating a type variable must not cause the
+ * creation of its bounds. Repeated creation of a type variable has no effect.
+ *
+ *
Multiple objects may be instantiated at run-time to
+ * represent a given type variable. Even though a type variable is
+ * created only once, this does not imply any requirement to cache
+ * instances representing the type variable. However, all instances
+ * representing a type variable must be equal() to each other.
+ * As a consequence, users of type variables must not rely on the identity
+ * of instances of classes implementing this interface.
+ *
+ * @param the type of generic declaration that declared the
+ * underlying type variable.
+ *
+ * @since 1.5
+ */
+public interface TypeVariable extends Type {
+ /**
+ * Returns an array of {@code Type} objects representing the
+ * upper bound(s) of this type variable. Note that if no upper bound is
+ * explicitly declared, the upper bound is {@code Object}.
+ *
+ *
For each upper bound B:
if B is a parameterized
+ * type or a type variable, it is created, (see {@link
+ * java.lang.reflect.ParameterizedType ParameterizedType} for the
+ * details of the creation process for parameterized types).
+ *
Otherwise, B is resolved.
+ *
+ * @throws TypeNotPresentException if any of the
+ * bounds refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if any of the
+ * bounds refer to a parameterized type that cannot be instantiated
+ * for any reason
+ * @return an array of {@code Type}s representing the upper
+ * bound(s) of this type variable
+ */
+ Type[] getBounds();
+
+ /**
+ * Returns the {@code GenericDeclaration} object representing the
+ * generic declaration declared this type variable.
+ *
+ * @return the generic declaration declared for this type variable.
+ *
+ * @since 1.5
+ */
+ D getGenericDeclaration();
+
+ /**
+ * Returns the name of this type variable, as it occurs in the source code.
+ *
+ * @return the name of this type variable, as it appears in the source code
+ */
+ String getName();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/package-info.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/lang/reflect/package-info.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides classes and interfaces for obtaining reflective
+ * information about classes and objects. Reflection allows
+ * programmatic access to information about the fields, methods and
+ * constructors of loaded classes, and the use of reflected fields,
+ * methods, and constructors to operate on their underlying
+ * counterparts, within security restrictions.
+ *
+ *
{@code AccessibleObject} allows suppression of access checks if
+ * the necessary {@code ReflectPermission} is available.
+ *
+ *
{@code Array} provides static methods to dynamically create and
+ * access arrays.
+ *
+ *
Classes in this package, along with {@code java.lang.Class}
+ * accommodate applications such as debuggers, interpreters, object
+ * inspectors, class browsers, and services such as Object
+ * Serialization and JavaBeans that need access to either the public
+ * members of a target object (based on its runtime class) or the
+ * members declared by a given class.
+ *
+ * @since JDK1.1
+ */
+package java.lang.reflect;
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/MalformedURLException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/net/MalformedURLException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+import java.io.IOException;
+
+/**
+ * Thrown to indicate that a malformed URL has occurred. Either no
+ * legal protocol could be found in a specification string or the
+ * string could not be parsed.
+ *
+ * @author Arthur van Hoff
+ * @since JDK1.0
+ */
+public class MalformedURLException extends IOException {
+ private static final long serialVersionUID = -182787522200415866L;
+
+ /**
+ * Constructs a MalformedURLException with no detail message.
+ */
+ public MalformedURLException() {
+ }
+
+ /**
+ * Constructs a MalformedURLException with the
+ * specified detail message.
+ *
+ * @param msg the detail message.
+ */
+ public MalformedURLException(String msg) {
+ super(msg);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/URL.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/net/URL.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,1037 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ * Class URL represents a Uniform Resource
+ * Locator, a pointer to a "resource" on the World
+ * Wide Web. A resource can be something as simple as a file or a
+ * directory, or it can be a reference to a more complicated object,
+ * such as a query to a database or to a search engine. More
+ * information on the types of URLs and their formats can be found at:
+ *
+ * In general, a URL can be broken into several parts. The previous
+ * example of a URL indicates that the protocol to use is
+ * http (HyperText Transfer Protocol) and that the
+ * information resides on a host machine named
+ * www.socs.uts.edu.au. The information on that host
+ * machine is named /MosaicDocs-old/url-primer.html. The exact
+ * meaning of this name on the host machine is both protocol
+ * dependent and host dependent. The information normally resides in
+ * a file, but it could be generated on the fly. This component of
+ * the URL is called the path component.
+ *
+ * A URL can optionally specify a "port", which is the
+ * port number to which the TCP connection is made on the remote host
+ * machine. If the port is not specified, the default port for
+ * the protocol is used instead. For example, the default port for
+ * http is 80. An alternative port could be
+ * specified as:
+ *
+ * A URL may have appended to it a "fragment", also known
+ * as a "ref" or a "reference". The fragment is indicated by the sharp
+ * sign character "#" followed by more characters. For example,
+ *
+ * http://java.sun.com/index.html#chapter1
+ *
+ *
+ * This fragment is not technically part of the URL. Rather, it
+ * indicates that after the specified resource is retrieved, the
+ * application is specifically interested in that part of the
+ * document that has the tag chapter1 attached to it. The
+ * meaning of a tag is resource specific.
+ *
+ * An application can also specify a "relative URL",
+ * which contains only enough information to reach the resource
+ * relative to another URL. Relative URLs are frequently used within
+ * HTML pages. For example, if the contents of the URL:
+ *
+ * http://java.sun.com/index.html
+ *
+ * contained within it the relative URL:
+ *
+ * FAQ.html
+ *
+ * it would be a shorthand for:
+ *
+ * http://java.sun.com/FAQ.html
+ *
+ *
+ * The relative URL need not specify all the components of a URL. If
+ * the protocol, host name, or port number is missing, the value is
+ * inherited from the fully specified URL. The file component must be
+ * specified. The optional fragment is not inherited.
+ *
+ * The URL class does not itself encode or decode any URL components
+ * according to the escaping mechanism defined in RFC2396. It is the
+ * responsibility of the caller to encode any fields, which need to be
+ * escaped prior to calling URL, and also to decode any escaped fields,
+ * that are returned from URL. Furthermore, because URL has no knowledge
+ * of URL escaping, it does not recognise equivalence between the encoded
+ * or decoded form of the same URL. For example, the two URLs:
+ *
http://foo.com/hello world/ and http://foo.com/hello%20world
+ * would be considered not equal to each other.
+ *
+ * Note, the {@link java.net.URI} class does perform escaping of its
+ * component fields in certain circumstances. The recommended way
+ * to manage the encoding and decoding of URLs is to use {@link java.net.URI},
+ * and to convert between these two classes using {@link #toURI()} and
+ * {@link URI#toURL()}.
+ *
+ * The {@link URLEncoder} and {@link URLDecoder} classes can also be
+ * used, but only for HTML form encoding, which is not the same
+ * as the encoding scheme defined in RFC2396.
+ *
+ * @author James Gosling
+ * @since JDK1.0
+ */
+public final class URL implements java.io.Serializable {
+
+ static final long serialVersionUID = -7627629688361524110L;
+
+ /**
+ * The property which specifies the package prefix list to be scanned
+ * for protocol handlers. The value of this property (if any) should
+ * be a vertical bar delimited list of package names to search through
+ * for a protocol handler to load. The policy of this class is that
+ * all protocol handlers will be in a class called .Handler,
+ * and each package in the list is examined in turn for a matching
+ * handler. If none are found (or the property is not specified), the
+ * default package prefix, sun.net.www.protocol, is used. The search
+ * proceeds from the first package in the list to the last and stops
+ * when a match is found.
+ */
+ private static final String protocolPathProp = "java.protocol.handler.pkgs";
+
+ /**
+ * The protocol to use (ftp, http, nntp, ... etc.) .
+ * @serial
+ */
+ private String protocol;
+
+ /**
+ * The host name to connect to.
+ * @serial
+ */
+ private String host;
+
+ /**
+ * The protocol port to connect to.
+ * @serial
+ */
+ private int port = -1;
+
+ /**
+ * The specified file name on that host. file is
+ * defined as path[?query]
+ * @serial
+ */
+ private String file;
+
+ /**
+ * The query part of this URL.
+ */
+ private transient String query;
+
+ /**
+ * The authority part of this URL.
+ * @serial
+ */
+ private String authority;
+
+ /**
+ * The path part of this URL.
+ */
+ private transient String path;
+
+ /**
+ * The userinfo part of this URL.
+ */
+ private transient String userInfo;
+
+ /**
+ * # reference.
+ * @serial
+ */
+ private String ref;
+
+ /**
+ * The host's IP address, used in equals and hashCode.
+ * Computed on demand. An uninitialized or unknown hostAddress is null.
+ */
+ transient Object hostAddress;
+
+ /**
+ * The URLStreamHandler for this URL.
+ */
+ transient URLStreamHandler handler;
+
+ /* Our hash code.
+ * @serial
+ */
+ private int hashCode = -1;
+
+ /**
+ * Creates a URL object from the specified
+ * protocol, host, port
+ * number, and file.
+ *
+ * host can be expressed as a host name or a literal
+ * IP address. If IPv6 literal address is used, it should be
+ * enclosed in square brackets ('[' and ']'), as
+ * specified by RFC 2732;
+ * However, the literal IPv6 address format defined in RFC 2373: IP
+ * Version 6 Addressing Architecture is also accepted.
+ *
+ * Specifying a port number of -1
+ * indicates that the URL should use the default port for the
+ * protocol.
+ *
+ * If this is the first URL object being created with the specified
+ * protocol, a stream protocol handler object, an instance of
+ * class URLStreamHandler, is created for that protocol:
+ *
+ *
If the application has previously set up an instance of
+ * URLStreamHandlerFactory as the stream handler factory,
+ * then the createURLStreamHandler method of that instance
+ * is called with the protocol string as an argument to create the
+ * stream protocol handler.
+ *
If no URLStreamHandlerFactory has yet been set up,
+ * or if the factory's createURLStreamHandler method
+ * returns null, then the constructor finds the
+ * value of the system property:
+ *
+ * java.protocol.handler.pkgs
+ *
+ * If the value of that system property is not null,
+ * it is interpreted as a list of packages separated by a vertical
+ * slash character '|'. The constructor tries to load
+ * the class named:
+ *
+ * <package>.<protocol>.Handler
+ *
+ * where <package> is replaced by the name of the package
+ * and <protocol> is replaced by the name of the protocol.
+ * If this class does not exist, or if the class exists but it is not
+ * a subclass of URLStreamHandler, then the next package
+ * in the list is tried.
+ *
If the previous step fails to find a protocol handler, then the
+ * constructor tries to load from a system default package.
+ *
+ * If this class does not exist, or if the class exists but it is not a
+ * subclass of URLStreamHandler, then a
+ * MalformedURLException is thrown.
+ *
+ *
+ *
Protocol handlers for the following protocols are guaranteed
+ * to exist on the search path :-
+ *
+ * http, https, ftp, file, and jar
+ *
+ * Protocol handlers for additional protocols may also be
+ * available.
+ *
+ *
No validation of the inputs is performed by this constructor.
+ *
+ * @param protocol the name of the protocol to use.
+ * @param host the name of the host.
+ * @param port the port number on the host.
+ * @param file the file on the host
+ * @exception MalformedURLException if an unknown protocol is specified.
+ * @see java.lang.System#getProperty(java.lang.String)
+ * @see java.net.URL#setURLStreamHandlerFactory(
+ * java.net.URLStreamHandlerFactory)
+ * @see java.net.URLStreamHandler
+ * @see java.net.URLStreamHandlerFactory#createURLStreamHandler(
+ * java.lang.String)
+ */
+ public URL(String protocol, String host, int port, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, port, file, null);
+ }
+
+ /**
+ * Creates a URL from the specified protocol
+ * name, host name, and file name. The
+ * default port for the specified protocol is used.
+ *
+ * This method is equivalent to calling the four-argument
+ * constructor with the arguments being protocol,
+ * host, -1, and file.
+ *
+ * No validation of the inputs is performed by this constructor.
+ *
+ * @param protocol the name of the protocol to use.
+ * @param host the name of the host.
+ * @param file the file on the host.
+ * @exception MalformedURLException if an unknown protocol is specified.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String,
+ * int, java.lang.String)
+ */
+ public URL(String protocol, String host, String file)
+ throws MalformedURLException {
+ this(protocol, host, -1, file);
+ }
+
+ /**
+ * Creates a URL object from the specified
+ * protocol, host, port
+ * number, file, and handler. Specifying
+ * a port number of -1 indicates that
+ * the URL should use the default port for the protocol. Specifying
+ * a handler of null indicates that the URL
+ * should use a default stream handler for the protocol, as outlined
+ * for:
+ * java.net.URL#URL(java.lang.String, java.lang.String, int,
+ * java.lang.String)
+ *
+ *
If the handler is not null and there is a security manager,
+ * the security manager's checkPermission
+ * method is called with a
+ * NetPermission("specifyStreamHandler") permission.
+ * This may result in a SecurityException.
+ *
+ * No validation of the inputs is performed by this constructor.
+ *
+ * @param protocol the name of the protocol to use.
+ * @param host the name of the host.
+ * @param port the port number on the host.
+ * @param file the file on the host
+ * @param handler the stream handler for the URL.
+ * @exception MalformedURLException if an unknown protocol is specified.
+ * @exception SecurityException
+ * if a security manager exists and its
+ * checkPermission method doesn't allow
+ * specifying a stream handler explicitly.
+ * @see java.lang.System#getProperty(java.lang.String)
+ * @see java.net.URL#setURLStreamHandlerFactory(
+ * java.net.URLStreamHandlerFactory)
+ * @see java.net.URLStreamHandler
+ * @see java.net.URLStreamHandlerFactory#createURLStreamHandler(
+ * java.lang.String)
+ * @see SecurityManager#checkPermission
+ * @see java.net.NetPermission
+ */
+ public URL(String protocol, String host, int port, String file,
+ URLStreamHandler handler) throws MalformedURLException {
+ if (handler != null) {
+ throw new SecurityException();
+ }
+
+ protocol = protocol.toLowerCase();
+ this.protocol = protocol;
+ if (host != null) {
+
+ /**
+ * if host is a literal IPv6 address,
+ * we will make it conform to RFC 2732
+ */
+ if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
+ host = "["+host+"]";
+ }
+ this.host = host;
+
+ if (port < -1) {
+ throw new MalformedURLException("Invalid port number :" +
+ port);
+ }
+ this.port = port;
+ authority = (port == -1) ? host : host + ":" + port;
+ }
+
+ Parts parts = new Parts(file);
+ path = parts.getPath();
+ query = parts.getQuery();
+
+ if (query != null) {
+ this.file = path + "?" + query;
+ } else {
+ this.file = path;
+ }
+ ref = parts.getRef();
+
+ // Note: we don't do validation of the URL here. Too risky to change
+ // right now, but worth considering for future reference. -br
+ if (handler == null &&
+ (handler = getURLStreamHandler(protocol)) == null) {
+ throw new MalformedURLException("unknown protocol: " + protocol);
+ }
+ this.handler = handler;
+ }
+
+ /**
+ * Creates a URL object from the String
+ * representation.
+ *
+ * This constructor is equivalent to a call to the two-argument
+ * constructor with a null first argument.
+ *
+ * @param spec the String to parse as a URL.
+ * @exception MalformedURLException if no protocol is specified, or an
+ * unknown protocol is found, or spec is null.
+ * @see java.net.URL#URL(java.net.URL, java.lang.String)
+ */
+ public URL(String spec) throws MalformedURLException {
+ this(null, spec);
+ }
+
+ /**
+ * Creates a URL by parsing the given spec within a specified context.
+ *
+ * The new URL is created from the given context URL and the spec
+ * argument as described in
+ * RFC2396 "Uniform Resource Identifiers : Generic * Syntax" :
+ *
+ * The reference is parsed into the scheme, authority, path, query and
+ * fragment parts. If the path component is empty and the scheme,
+ * authority, and query components are undefined, then the new URL is a
+ * reference to the current document. Otherwise, the fragment and query
+ * parts present in the spec are used in the new URL.
+ *
+ * If the scheme component is defined in the given spec and does not match
+ * the scheme of the context, then the new URL is created as an absolute
+ * URL based on the spec alone. Otherwise the scheme component is inherited
+ * from the context URL.
+ *
+ * If the authority component is present in the spec then the spec is
+ * treated as absolute and the spec authority and path will replace the
+ * context authority and path. If the authority component is absent in the
+ * spec then the authority of the new URL will be inherited from the
+ * context.
+ *
+ * If the spec's path component begins with a slash character
+ * "/" then the
+ * path is treated as absolute and the spec path replaces the context path.
+ *
+ * Otherwise, the path is treated as a relative path and is appended to the
+ * context path, as described in RFC2396. Also, in this case,
+ * the path is canonicalized through the removal of directory
+ * changes made by occurences of ".." and ".".
+ *
+ * For a more detailed description of URL parsing, refer to RFC2396.
+ *
+ * @param context the context in which to parse the specification.
+ * @param spec the String to parse as a URL.
+ * @exception MalformedURLException if no protocol is specified, or an
+ * unknown protocol is found, or spec is null.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String,
+ * int, java.lang.String)
+ * @see java.net.URLStreamHandler
+ * @see java.net.URLStreamHandler#parseURL(java.net.URL,
+ * java.lang.String, int, int)
+ */
+ public URL(URL context, String spec) throws MalformedURLException {
+ this(context, spec, null);
+ }
+
+ /**
+ * Creates a URL by parsing the given spec with the specified handler
+ * within a specified context. If the handler is null, the parsing
+ * occurs as with the two argument constructor.
+ *
+ * @param context the context in which to parse the specification.
+ * @param spec the String to parse as a URL.
+ * @param handler the stream handler for the URL.
+ * @exception MalformedURLException if no protocol is specified, or an
+ * unknown protocol is found, or spec is null.
+ * @exception SecurityException
+ * if a security manager exists and its
+ * checkPermission method doesn't allow
+ * specifying a stream handler.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String,
+ * int, java.lang.String)
+ * @see java.net.URLStreamHandler
+ * @see java.net.URLStreamHandler#parseURL(java.net.URL,
+ * java.lang.String, int, int)
+ */
+ public URL(URL context, String spec, URLStreamHandler handler)
+ throws MalformedURLException
+ {
+ String original = spec;
+ int i, limit, c;
+ int start = 0;
+ String newProtocol = null;
+ boolean aRef=false;
+ boolean isRelative = false;
+
+ // Check for permission to specify a handler
+ if (handler != null) {
+ throw new SecurityException();
+ }
+
+ try {
+ limit = spec.length();
+ while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
+ limit--; //eliminate trailing whitespace
+ }
+ while ((start < limit) && (spec.charAt(start) <= ' ')) {
+ start++; // eliminate leading whitespace
+ }
+
+ if (spec.regionMatches(true, start, "url:", 0, 4)) {
+ start += 4;
+ }
+ if (start < spec.length() && spec.charAt(start) == '#') {
+ /* we're assuming this is a ref relative to the context URL.
+ * This means protocols cannot start w/ '#', but we must parse
+ * ref URL's like: "hello:there" w/ a ':' in them.
+ */
+ aRef=true;
+ }
+ for (i = start ; !aRef && (i < limit) &&
+ ((c = spec.charAt(i)) != '/') ; i++) {
+ if (c == ':') {
+
+ String s = spec.substring(start, i).toLowerCase();
+ if (isValidProtocol(s)) {
+ newProtocol = s;
+ start = i + 1;
+ }
+ break;
+ }
+ }
+
+ // Only use our context if the protocols match.
+ protocol = newProtocol;
+ if ((context != null) && ((newProtocol == null) ||
+ newProtocol.equalsIgnoreCase(context.protocol))) {
+ // inherit the protocol handler from the context
+ // if not specified to the constructor
+ if (handler == null) {
+ handler = context.handler;
+ }
+
+ // If the context is a hierarchical URL scheme and the spec
+ // contains a matching scheme then maintain backwards
+ // compatibility and treat it as if the spec didn't contain
+ // the scheme; see 5.2.3 of RFC2396
+ if (context.path != null && context.path.startsWith("/"))
+ newProtocol = null;
+
+ if (newProtocol == null) {
+ protocol = context.protocol;
+ authority = context.authority;
+ userInfo = context.userInfo;
+ host = context.host;
+ port = context.port;
+ file = context.file;
+ path = context.path;
+ isRelative = true;
+ }
+ }
+
+ if (protocol == null) {
+ throw new MalformedURLException("no protocol: "+original);
+ }
+
+ // Get the protocol handler if not specified or the protocol
+ // of the context could not be used
+ if (handler == null &&
+ (handler = getURLStreamHandler(protocol)) == null) {
+ throw new MalformedURLException("unknown protocol: "+protocol);
+ }
+ this.handler = handler;
+
+ i = spec.indexOf('#', start);
+ if (i >= 0) {
+//thrw(protocol + " hnd: " + handler.getClass().getName() + " i: " + i);
+ ref = spec.substring(i + 1, limit);
+ limit = i;
+ }
+
+ /*
+ * Handle special case inheritance of query and fragment
+ * implied by RFC2396 section 5.2.2.
+ */
+ if (isRelative && start == limit) {
+ query = context.query;
+ if (ref == null) {
+ ref = context.ref;
+ }
+ }
+
+ handler.parseURL(this, spec, start, limit);
+
+ } catch(MalformedURLException e) {
+ throw e;
+ } catch(Exception e) {
+ MalformedURLException exception = new MalformedURLException(e.getMessage());
+ exception.initCause(e);
+ throw exception;
+ }
+ }
+
+ /*
+ * Returns true if specified string is a valid protocol name.
+ */
+ private boolean isValidProtocol(String protocol) {
+ int len = protocol.length();
+ if (len < 1)
+ return false;
+ char c = protocol.charAt(0);
+ if (!Character.isLetter(c))
+ return false;
+ for (int i = 1; i < len; i++) {
+ c = protocol.charAt(i);
+ if (!Character.isLetterOrDigit(c) && c != '.' && c != '+' &&
+ c != '-') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Sets the fields of the URL. This is not a public method so that
+ * only URLStreamHandlers can modify URL fields. URLs are
+ * otherwise constant.
+ *
+ * @param protocol the name of the protocol to use
+ * @param host the name of the host
+ @param port the port number on the host
+ * @param file the file on the host
+ * @param ref the internal reference in the URL
+ */
+ protected void set(String protocol, String host,
+ int port, String file, String ref) {
+ synchronized (this) {
+ this.protocol = protocol;
+ this.host = host;
+ authority = port == -1 ? host : host + ":" + port;
+ this.port = port;
+ this.file = file;
+ this.ref = ref;
+ /* This is very important. We must recompute this after the
+ * URL has been changed. */
+ hashCode = -1;
+ hostAddress = null;
+ int q = file.lastIndexOf('?');
+ if (q != -1) {
+ query = file.substring(q+1);
+ path = file.substring(0, q);
+ } else
+ path = file;
+ }
+ }
+
+ /**
+ * Sets the specified 8 fields of the URL. This is not a public method so
+ * that only URLStreamHandlers can modify URL fields. URLs are otherwise
+ * constant.
+ *
+ * @param protocol the name of the protocol to use
+ * @param host the name of the host
+ * @param port the port number on the host
+ * @param authority the authority part for the url
+ * @param userInfo the username and password
+ * @param path the file on the host
+ * @param ref the internal reference in the URL
+ * @param query the query part of this URL
+ * @since 1.3
+ */
+ protected void set(String protocol, String host, int port,
+ String authority, String userInfo, String path,
+ String query, String ref) {
+ synchronized (this) {
+ this.protocol = protocol;
+ this.host = host;
+ this.port = port;
+ this.file = query == null ? path : path + "?" + query;
+ this.userInfo = userInfo;
+ this.path = path;
+ this.ref = ref;
+ /* This is very important. We must recompute this after the
+ * URL has been changed. */
+ hashCode = -1;
+ hostAddress = null;
+ this.query = query;
+ this.authority = authority;
+ }
+ }
+
+ /**
+ * Gets the query part of this URL.
+ *
+ * @return the query part of this URL,
+ * or null if one does not exist
+ * @since 1.3
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Gets the path part of this URL.
+ *
+ * @return the path part of this URL, or an
+ * empty string if one does not exist
+ * @since 1.3
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Gets the userInfo part of this URL.
+ *
+ * @return the userInfo part of this URL, or
+ * null if one does not exist
+ * @since 1.3
+ */
+ public String getUserInfo() {
+ return userInfo;
+ }
+
+ /**
+ * Gets the authority part of this URL.
+ *
+ * @return the authority part of this URL
+ * @since 1.3
+ */
+ public String getAuthority() {
+ return authority;
+ }
+
+ /**
+ * Gets the port number of this URL.
+ *
+ * @return the port number, or -1 if the port is not set
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Gets the default port number of the protocol associated
+ * with this URL. If the URL scheme or the URLStreamHandler
+ * for the URL do not define a default port number,
+ * then -1 is returned.
+ *
+ * @return the port number
+ * @since 1.4
+ */
+ public int getDefaultPort() {
+ return handler.getDefaultPort();
+ }
+
+ /**
+ * Gets the protocol name of this URL.
+ *
+ * @return the protocol of this URL.
+ */
+ public String getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * Gets the host name of this URL, if applicable.
+ * The format of the host conforms to RFC 2732, i.e. for a
+ * literal IPv6 address, this method will return the IPv6 address
+ * enclosed in square brackets ('[' and ']').
+ *
+ * @return the host name of this URL.
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * Gets the file name of this URL.
+ * The returned file portion will be
+ * the same as getPath(), plus the concatenation of
+ * the value of getQuery(), if any. If there is
+ * no query portion, this method and getPath() will
+ * return identical results.
+ *
+ * @return the file name of this URL,
+ * or an empty string if one does not exist
+ */
+ public String getFile() {
+ return file;
+ }
+
+ /**
+ * Gets the anchor (also known as the "reference") of this
+ * URL.
+ *
+ * @return the anchor (also known as the "reference") of this
+ * URL, or null if one does not exist
+ */
+ public String getRef() {
+ return ref;
+ }
+
+ /**
+ * Compares this URL for equality with another object.
+ *
+ * If the given object is not a URL then this method immediately returns
+ * false.
+ *
+ * Two URL objects are equal if they have the same protocol, reference
+ * equivalent hosts, have the same port number on the host, and the same
+ * file and fragment of the file.
+ *
+ * Two hosts are considered equivalent if both host names can be resolved
+ * into the same IP addresses; else if either host name can't be
+ * resolved, the host names must be equal without regard to case; or both
+ * host names equal to null.
+ *
+ * Since hosts comparison requires name resolution, this operation is a
+ * blocking operation.
+ *
+ * Note: The defined behavior for equals is known to
+ * be inconsistent with virtual hosting in HTTP.
+ *
+ * @param obj the URL to compare against.
+ * @return true if the objects are the same;
+ * false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof URL))
+ return false;
+ URL u2 = (URL)obj;
+
+ return handler.equals(this, u2);
+ }
+
+ /**
+ * Creates an integer suitable for hash table indexing.
+ *
+ * The hash code is based upon all the URL components relevant for URL
+ * comparison. As such, this operation is a blocking operation.
+ *
+ * @return a hash code for this URL.
+ */
+ public synchronized int hashCode() {
+ if (hashCode != -1)
+ return hashCode;
+
+ hashCode = handler.hashCode(this);
+ return hashCode;
+ }
+
+ /**
+ * Compares two URLs, excluding the fragment component.
+ *
+ * Returns true if this URL and the
+ * other argument are equal without taking the
+ * fragment component into consideration.
+ *
+ * @param other the URL to compare against.
+ * @return true if they reference the same remote object;
+ * false otherwise.
+ */
+ public boolean sameFile(URL other) {
+ return handler.sameFile(this, other);
+ }
+
+ /**
+ * Constructs a string representation of this URL. The
+ * string is created by calling the toExternalForm
+ * method of the stream protocol handler for this object.
+ *
+ * @return a string representation of this object.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String, int,
+ * java.lang.String)
+ * @see java.net.URLStreamHandler#toExternalForm(java.net.URL)
+ */
+ public String toString() {
+ return toExternalForm();
+ }
+
+ /**
+ * Constructs a string representation of this URL. The
+ * string is created by calling the toExternalForm
+ * method of the stream protocol handler for this object.
+ *
+ * @return a string representation of this object.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String,
+ * int, java.lang.String)
+ * @see java.net.URLStreamHandler#toExternalForm(java.net.URL)
+ */
+ public String toExternalForm() {
+ return handler.toExternalForm(this);
+ }
+
+ /**
+ * Returns a {@link java.net.URLConnection URLConnection} instance that
+ * represents a connection to the remote object referred to by the
+ * {@code URL}.
+ *
+ *
A new instance of {@linkplain java.net.URLConnection URLConnection} is
+ * created every time when invoking the
+ * {@linkplain java.net.URLStreamHandler#openConnection(URL)
+ * URLStreamHandler.openConnection(URL)} method of the protocol handler for
+ * this URL.
+ *
+ *
It should be noted that a URLConnection instance does not establish
+ * the actual network connection on creation. This will happen only when
+ * calling {@linkplain java.net.URLConnection#connect() URLConnection.connect()}.
+ *
+ *
If for the URL's protocol (such as HTTP or JAR), there
+ * exists a public, specialized URLConnection subclass belonging
+ * to one of the following packages or one of their subpackages:
+ * java.lang, java.io, java.util, java.net, the connection
+ * returned will be of that subclass. For example, for HTTP an
+ * HttpURLConnection will be returned, and for JAR a
+ * JarURLConnection will be returned.
+ *
+ * @return a {@link java.net.URLConnection URLConnection} linking
+ * to the URL.
+ * @exception IOException if an I/O exception occurs.
+ * @see java.net.URL#URL(java.lang.String, java.lang.String,
+ * int, java.lang.String)
+ */
+// public URLConnection openConnection() throws java.io.IOException {
+// return handler.openConnection(this);
+// }
+
+
+ /**
+ * Opens a connection to this URL and returns an
+ * InputStream for reading from that connection. This
+ * method is a shorthand for:
+ *
+ * openConnection().getInputStream()
+ *
+ *
+ * @return an input stream for reading from the URL connection.
+ * @exception IOException if an I/O exception occurs.
+ * @see java.net.URL#openConnection()
+ * @see java.net.URLConnection#getInputStream()
+ */
+ public final InputStream openStream() throws java.io.IOException {
+ throw new IOException();
+// return openConnection().getInputStream();
+ }
+
+ /**
+ * Gets the contents of this URL. This method is a shorthand for:
+ *
+ * openConnection().getContent()
+ *
+ *
+ * @return the contents of this URL.
+ * @exception IOException if an I/O exception occurs.
+ * @see java.net.URLConnection#getContent()
+ */
+ public final Object getContent() throws java.io.IOException {
+ return loadText(toExternalForm());
+ }
+
+ @JavaScriptBody(args = "url", body = ""
+ + "var request = new XMLHttpRequest();\n"
+ + "request.open('GET', url, false);\n"
+ + "request.send();\n"
+ + "return request.responseText;\n"
+ )
+ private static native String loadText(String url) throws IOException;
+
+ /**
+ * Gets the contents of this URL. This method is a shorthand for:
+ *
+ * openConnection().getContent(Class[])
+ *
+ *
+ * @param classes an array of Java types
+ * @return the content object of this URL that is the first match of
+ * the types specified in the classes array.
+ * null if none of the requested types are supported.
+ * @exception IOException if an I/O exception occurs.
+ * @see java.net.URLConnection#getContent(Class[])
+ * @since 1.3
+ */
+ public final Object getContent(Class[] classes)
+ throws java.io.IOException {
+ for (Class> c : classes) {
+ if (c == String.class) {
+ return getContent();
+ }
+ }
+ return null;
+ }
+
+ static URLStreamHandler getURLStreamHandler(String protocol) {
+ URLStreamHandler universal = new URLStreamHandler() {};
+ return universal;
+ }
+
+}
+
+class Parts {
+ String path, query, ref;
+
+ Parts(String file) {
+ int ind = file.indexOf('#');
+ ref = ind < 0 ? null: file.substring(ind + 1);
+ file = ind < 0 ? file: file.substring(0, ind);
+ int q = file.lastIndexOf('?');
+ if (q != -1) {
+ query = file.substring(q+1);
+ path = file.substring(0, q);
+ } else {
+ path = file;
+ }
+ }
+
+ String getPath() {
+ return path;
+ }
+
+ String getQuery() {
+ return query;
+ }
+
+ String getRef() {
+ return ref;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/URLStreamHandler.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/net/URLStreamHandler.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+
+/**
+ * The abstract class URLStreamHandler is the common
+ * superclass for all stream protocol handlers. A stream protocol
+ * handler knows how to make a connection for a particular protocol
+ * type, such as http, ftp, or
+ * gopher.
+ *
+ * In most cases, an instance of a URLStreamHandler
+ * subclass is not created directly by an application. Rather, the
+ * first time a protocol name is encountered when constructing a
+ * URL, the appropriate stream protocol handler is
+ * automatically loaded.
+ *
+ * @author James Gosling
+ * @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
+ * @since JDK1.0
+ */
+public abstract class URLStreamHandler {
+ /**
+ * Opens a connection to the object referenced by the
+ * URL argument.
+ * This method should be overridden by a subclass.
+ *
+ *
If for the handler's protocol (such as HTTP or JAR), there
+ * exists a public, specialized URLConnection subclass belonging
+ * to one of the following packages or one of their subpackages:
+ * java.lang, java.io, java.util, java.net, the connection
+ * returned will be of that subclass. For example, for HTTP an
+ * HttpURLConnection will be returned, and for JAR a
+ * JarURLConnection will be returned.
+ *
+ * @param u the URL that this connects to.
+ * @return a URLConnection object for the URL.
+ * @exception IOException if an I/O error occurs while opening the
+ * connection.
+ */
+// abstract protected URLConnection openConnection(URL u) throws IOException;
+
+ /**
+ * Same as openConnection(URL), except that the connection will be
+ * made through the specified proxy; Protocol handlers that do not
+ * support proxying will ignore the proxy parameter and make a
+ * normal connection.
+ *
+ * Calling this method preempts the system's default ProxySelector
+ * settings.
+ *
+ * @param u the URL that this connects to.
+ * @param p the proxy through which the connection will be made.
+ * If direct connection is desired, Proxy.NO_PROXY
+ * should be specified.
+ * @return a URLConnection object for the URL.
+ * @exception IOException if an I/O error occurs while opening the
+ * connection.
+ * @exception IllegalArgumentException if either u or p is null,
+ * or p has the wrong type.
+ * @exception UnsupportedOperationException if the subclass that
+ * implements the protocol doesn't support this method.
+ * @since 1.5
+ */
+// protected URLConnection openConnection(URL u, Proxy p) throws IOException {
+// throw new UnsupportedOperationException("Method not implemented.");
+// }
+
+ /**
+ * Parses the string representation of a URL into a
+ * URL object.
+ *
+ * If there is any inherited context, then it has already been
+ * copied into the URL argument.
+ *
+ * The parseURL method of URLStreamHandler
+ * parses the string representation as if it were an
+ * http specification. Most URL protocol families have a
+ * similar parsing. A stream protocol handler for a protocol that has
+ * a different syntax must override this routine.
+ *
+ * @param u the URL to receive the result of parsing
+ * the spec.
+ * @param spec the String representing the URL that
+ * must be parsed.
+ * @param start the character index at which to begin parsing. This is
+ * just past the ':' (if there is one) that
+ * specifies the determination of the protocol name.
+ * @param limit the character position to stop parsing at. This is the
+ * end of the string or the position of the
+ * "#" character, if present. All information
+ * after the sharp sign indicates an anchor.
+ */
+ protected void parseURL(URL u, String spec, int start, int limit) {
+ // These fields may receive context content if this was relative URL
+ String protocol = u.getProtocol();
+ String authority = u.getAuthority();
+ String userInfo = u.getUserInfo();
+ String host = u.getHost();
+ int port = u.getPort();
+ String path = u.getPath();
+ String query = u.getQuery();
+
+ // This field has already been parsed
+ String ref = u.getRef();
+
+ boolean isRelPath = false;
+ boolean queryOnly = false;
+
+// FIX: should not assume query if opaque
+ // Strip off the query part
+ if (start < limit) {
+ int queryStart = spec.indexOf('?');
+ queryOnly = queryStart == start;
+ if ((queryStart != -1) && (queryStart < limit)) {
+ query = spec.substring(queryStart+1, limit);
+ if (limit > queryStart)
+ limit = queryStart;
+ spec = spec.substring(0, queryStart);
+ }
+ }
+
+ int i = 0;
+ // Parse the authority part if any
+ boolean isUNCName = (start <= limit - 4) &&
+ (spec.charAt(start) == '/') &&
+ (spec.charAt(start + 1) == '/') &&
+ (spec.charAt(start + 2) == '/') &&
+ (spec.charAt(start + 3) == '/');
+ if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') &&
+ (spec.charAt(start + 1) == '/')) {
+ start += 2;
+ i = spec.indexOf('/', start);
+ if (i < 0) {
+ i = spec.indexOf('?', start);
+ if (i < 0)
+ i = limit;
+ }
+
+ host = authority = spec.substring(start, i);
+
+ int ind = authority.indexOf('@');
+ if (ind != -1) {
+ userInfo = authority.substring(0, ind);
+ host = authority.substring(ind+1);
+ } else {
+ userInfo = null;
+ }
+ if (host != null) {
+ // If the host is surrounded by [ and ] then its an IPv6
+ // literal address as specified in RFC2732
+ if (host.length()>0 && (host.charAt(0) == '[')) {
+ if ((ind = host.indexOf(']')) > 2) {
+
+ String nhost = host ;
+ host = nhost.substring(0,ind+1);
+// if (!IPAddressUtil.
+// isIPv6LiteralAddress(host.substring(1, ind))) {
+// throw new IllegalArgumentException(
+// "Invalid host: "+ host);
+// }
+
+ port = -1 ;
+ if (nhost.length() > ind+1) {
+ if (nhost.charAt(ind+1) == ':') {
+ ++ind ;
+ // port can be null according to RFC2396
+ if (nhost.length() > (ind + 1)) {
+ port = Integer.parseInt(nhost.substring(ind+1));
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "Invalid authority field: " + authority);
+ }
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "Invalid authority field: " + authority);
+ }
+ } else {
+ ind = host.indexOf(':');
+ port = -1;
+ if (ind >= 0) {
+ // port can be null according to RFC2396
+ if (host.length() > (ind + 1)) {
+ port = Integer.parseInt(host.substring(ind + 1));
+ }
+ host = host.substring(0, ind);
+ }
+ }
+ } else {
+ host = "";
+ }
+ if (port < -1)
+ throw new IllegalArgumentException("Invalid port number :" +
+ port);
+ start = i;
+ // If the authority is defined then the path is defined by the
+ // spec only; See RFC 2396 Section 5.2.4.
+ if (authority != null && authority.length() > 0)
+ path = "";
+ }
+
+ if (host == null) {
+ host = "";
+ }
+
+ // Parse the file path if any
+ if (start < limit) {
+ if (spec.charAt(start) == '/') {
+ path = spec.substring(start, limit);
+ } else if (path != null && path.length() > 0) {
+ isRelPath = true;
+ int ind = path.lastIndexOf('/');
+ String seperator = "";
+ if (ind == -1 && authority != null)
+ seperator = "/";
+ path = path.substring(0, ind + 1) + seperator +
+ spec.substring(start, limit);
+
+ } else {
+ String seperator = (authority != null) ? "/" : "";
+ path = seperator + spec.substring(start, limit);
+ }
+ } else if (queryOnly && path != null) {
+ int ind = path.lastIndexOf('/');
+ if (ind < 0)
+ ind = 0;
+ path = path.substring(0, ind) + "/";
+ }
+ if (path == null)
+ path = "";
+
+ if (isRelPath) {
+ // Remove embedded /./
+ while ((i = path.indexOf("/./")) >= 0) {
+ path = path.substring(0, i) + path.substring(i + 2);
+ }
+ // Remove embedded /../ if possible
+ i = 0;
+ while ((i = path.indexOf("/../", i)) >= 0) {
+ /*
+ * A "/../" will cancel the previous segment and itself,
+ * unless that segment is a "/../" itself
+ * i.e. "/a/b/../c" becomes "/a/c"
+ * but "/../../a" should stay unchanged
+ */
+ if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
+ (path.indexOf("/../", limit) != 0)) {
+ path = path.substring(0, limit) + path.substring(i + 3);
+ i = 0;
+ } else {
+ i = i + 3;
+ }
+ }
+ // Remove trailing .. if possible
+ while (path.endsWith("/..")) {
+ i = path.indexOf("/..");
+ if ((limit = path.lastIndexOf('/', i - 1)) >= 0) {
+ path = path.substring(0, limit+1);
+ } else {
+ break;
+ }
+ }
+ // Remove starting .
+ if (path.startsWith("./") && path.length() > 2)
+ path = path.substring(2);
+
+ // Remove trailing .
+ if (path.endsWith("/."))
+ path = path.substring(0, path.length() -1);
+ }
+
+ setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
+ }
+
+ /**
+ * Returns the default port for a URL parsed by this handler. This method
+ * is meant to be overidden by handlers with default port numbers.
+ * @return the default port for a URL parsed by this handler.
+ * @since 1.3
+ */
+ protected int getDefaultPort() {
+ return -1;
+ }
+
+ /**
+ * Provides the default equals calculation. May be overidden by handlers
+ * for other protocols that have different requirements for equals().
+ * This method requires that none of its arguments is null. This is
+ * guaranteed by the fact that it is only called by java.net.URL class.
+ * @param u1 a URL object
+ * @param u2 a URL object
+ * @return true if the two urls are
+ * considered equal, ie. they refer to the same
+ * fragment in the same file.
+ * @since 1.3
+ */
+ protected boolean equals(URL u1, URL u2) {
+ String ref1 = u1.getRef();
+ String ref2 = u2.getRef();
+ return (ref1 == ref2 || (ref1 != null && ref1.equals(ref2))) &&
+ sameFile(u1, u2);
+ }
+
+ /**
+ * Provides the default hash calculation. May be overidden by handlers for
+ * other protocols that have different requirements for hashCode
+ * calculation.
+ * @param u a URL object
+ * @return an int suitable for hash table indexing
+ * @since 1.3
+ */
+ protected int hashCode(URL u) {
+ int h = 0;
+
+ // Generate the protocol part.
+ String protocol = u.getProtocol();
+ if (protocol != null)
+ h += protocol.hashCode();
+
+ // Generate the host part.
+ Object addr = getHostAddress(u);
+ if (addr != null) {
+ h += addr.hashCode();
+ } else {
+ String host = u.getHost();
+ if (host != null)
+ h += host.toLowerCase().hashCode();
+ }
+
+ // Generate the file part.
+ String file = u.getFile();
+ if (file != null)
+ h += file.hashCode();
+
+ // Generate the port part.
+ if (u.getPort() == -1)
+ h += getDefaultPort();
+ else
+ h += u.getPort();
+
+ // Generate the ref part.
+ String ref = u.getRef();
+ if (ref != null)
+ h += ref.hashCode();
+
+ return h;
+ }
+
+ /**
+ * Compare two urls to see whether they refer to the same file,
+ * i.e., having the same protocol, host, port, and path.
+ * This method requires that none of its arguments is null. This is
+ * guaranteed by the fact that it is only called indirectly
+ * by java.net.URL class.
+ * @param u1 a URL object
+ * @param u2 a URL object
+ * @return true if u1 and u2 refer to the same file
+ * @since 1.3
+ */
+ protected boolean sameFile(URL u1, URL u2) {
+ // Compare the protocols.
+ if (!((u1.getProtocol() == u2.getProtocol()) ||
+ (u1.getProtocol() != null &&
+ u1.getProtocol().equalsIgnoreCase(u2.getProtocol()))))
+ return false;
+
+ // Compare the files.
+ if (!(u1.getFile() == u2.getFile() ||
+ (u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
+ return false;
+
+ // Compare the ports.
+ int port1, port2;
+ port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort();
+ port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort();
+ if (port1 != port2)
+ return false;
+
+ // Compare the hosts.
+ if (!hostsEqual(u1, u2))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Get the IP address of our host. An empty host field or a DNS failure
+ * will result in a null return.
+ *
+ * @param u a URL object
+ * @return an InetAddress representing the host
+ * IP address.
+ * @since 1.3
+ */
+ private synchronized Object getHostAddress(URL u) {
+ return u.hostAddress;
+ }
+
+ /**
+ * Compares the host components of two URLs.
+ * @param u1 the URL of the first host to compare
+ * @param u2 the URL of the second host to compare
+ * @return true if and only if they
+ * are equal, false otherwise.
+ * @since 1.3
+ */
+ protected boolean hostsEqual(URL u1, URL u2) {
+ Object a1 = getHostAddress(u1);
+ Object a2 = getHostAddress(u2);
+ // if we have internet address for both, compare them
+ if (a1 != null && a2 != null) {
+ return a1.equals(a2);
+ // else, if both have host names, compare them
+ } else if (u1.getHost() != null && u2.getHost() != null)
+ return u1.getHost().equalsIgnoreCase(u2.getHost());
+ else
+ return u1.getHost() == null && u2.getHost() == null;
+ }
+
+ /**
+ * Converts a URL of a specific protocol to a
+ * String.
+ *
+ * @param u the URL.
+ * @return a string representation of the URL argument.
+ */
+ protected String toExternalForm(URL u) {
+
+ // pre-compute length of StringBuffer
+ int len = u.getProtocol().length() + 1;
+ if (u.getAuthority() != null && u.getAuthority().length() > 0)
+ len += 2 + u.getAuthority().length();
+ if (u.getPath() != null) {
+ len += u.getPath().length();
+ }
+ if (u.getQuery() != null) {
+ len += 1 + u.getQuery().length();
+ }
+ if (u.getRef() != null)
+ len += 1 + u.getRef().length();
+
+ StringBuffer result = new StringBuffer(len);
+ result.append(u.getProtocol());
+ result.append(":");
+ if (u.getAuthority() != null && u.getAuthority().length() > 0) {
+ result.append("//");
+ result.append(u.getAuthority());
+ }
+ if (u.getPath() != null) {
+ result.append(u.getPath());
+ }
+ if (u.getQuery() != null) {
+ result.append('?');
+ result.append(u.getQuery());
+ }
+ if (u.getRef() != null) {
+ result.append("#");
+ result.append(u.getRef());
+ }
+ return result.toString();
+ }
+
+ /**
+ * Sets the fields of the URL argument to the indicated values.
+ * Only classes derived from URLStreamHandler are supposed to be able
+ * to call the set method on a URL.
+ *
+ * @param u the URL to modify.
+ * @param protocol the protocol name.
+ * @param host the remote host value for the URL.
+ * @param port the port on the remote machine.
+ * @param authority the authority part for the URL.
+ * @param userInfo the userInfo part of the URL.
+ * @param path the path component of the URL.
+ * @param query the query part for the URL.
+ * @param ref the reference.
+ * @exception SecurityException if the protocol handler of the URL is
+ * different from this one
+ * @see java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
+ * @since 1.3
+ */
+ protected void setURL(URL u, String protocol, String host, int port,
+ String authority, String userInfo, String path,
+ String query, String ref) {
+ if (this != u.handler) {
+ throw new SecurityException("handler for url different from " +
+ "this handler");
+ }
+ // ensure that no one can reset the protocol on a given URL.
+ u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref);
+ }
+
+ /**
+ * Sets the fields of the URL argument to the indicated values.
+ * Only classes derived from URLStreamHandler are supposed to be able
+ * to call the set method on a URL.
+ *
+ * @param u the URL to modify.
+ * @param protocol the protocol name. This value is ignored since 1.2.
+ * @param host the remote host value for the URL.
+ * @param port the port on the remote machine.
+ * @param file the file.
+ * @param ref the reference.
+ * @exception SecurityException if the protocol handler of the URL is
+ * different from this one
+ * @deprecated Use setURL(URL, String, String, int, String, String, String,
+ * String);
+ */
+ @Deprecated
+ protected void setURL(URL u, String protocol, String host, int port,
+ String file, String ref) {
+ /*
+ * Only old URL handlers call this, so assume that the host
+ * field might contain "user:passwd@host". Fix as necessary.
+ */
+ String authority = null;
+ String userInfo = null;
+ if (host != null && host.length() != 0) {
+ authority = (port == -1) ? host : host + ":" + port;
+ int at = host.lastIndexOf('@');
+ if (at != -1) {
+ userInfo = host.substring(0, at);
+ host = host.substring(at+1);
+ }
+ }
+
+ /*
+ * Assume file might contain query part. Fix as necessary.
+ */
+ String path = null;
+ String query = null;
+ if (file != null) {
+ int q = file.lastIndexOf('?');
+ if (q != -1) {
+ query = file.substring(q+1);
+ path = file.substring(0, q);
+ } else
+ path = file;
+ }
+ setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/util/Enumeration.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/util/Enumeration.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util;
+
+/**
+ * An object that implements the Enumeration interface generates a
+ * series of elements, one at a time. Successive calls to the
+ * nextElement method return successive elements of the
+ * series.
+ *
+ * For example, to print all elements of a Vector<E>v:
+ *
+ * for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
+ * System.out.println(e.nextElement());
+ *
+ * Methods are provided to enumerate through the elements of a
+ * vector, the keys of a hashtable, and the values in a hashtable.
+ * Enumerations are also used to specify the input streams to a
+ * SequenceInputStream.
+ *
+ * NOTE: The functionality of this interface is duplicated by the Iterator
+ * interface. In addition, Iterator adds an optional remove operation, and
+ * has shorter method names. New implementations should consider using
+ * Iterator in preference to Enumeration.
+ *
+ * @see java.util.Iterator
+ * @see java.io.SequenceInputStream
+ * @see java.util.Enumeration#nextElement()
+ * @see java.util.Hashtable
+ * @see java.util.Hashtable#elements()
+ * @see java.util.Hashtable#keys()
+ * @see java.util.Vector
+ * @see java.util.Vector#elements()
+ *
+ * @author Lee Boynton
+ * @since JDK1.0
+ */
+public interface Enumeration {
+ /**
+ * Tests if this enumeration contains more elements.
+ *
+ * @return true if and only if this enumeration object
+ * contains at least one more element to provide;
+ * false otherwise.
+ */
+ boolean hasMoreElements();
+
+ /**
+ * Returns the next element of this enumeration if this enumeration
+ * object has at least one more element to provide.
+ *
+ * @return the next element of this enumeration.
+ * @exception NoSuchElementException if no more elements exist.
+ */
+ E nextElement();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/util/NoSuchElementException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/java/util/NoSuchElementException.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util;
+
+/**
+ * Thrown by the nextElement method of an
+ * Enumeration to indicate that there are no more
+ * elements in the enumeration.
+ *
+ * @author unascribed
+ * @see java.util.Enumeration
+ * @see java.util.Enumeration#nextElement()
+ * @since JDK1.0
+ */
+public
+class NoSuchElementException extends RuntimeException {
+ private static final long serialVersionUID = 6769829250639411880L;
+
+ /**
+ * Constructs a NoSuchElementException with null
+ * as its error message string.
+ */
+ public NoSuchElementException() {
+ super();
+ }
+
+ /**
+ * Constructs a NoSuchElementException, saving a reference
+ * to the error message string s for later retrieval by the
+ * getMessage method.
+ *
+ * @param s the detail message.
+ */
+ public NoSuchElementException(String s) {
+ super(s);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,81 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.emul;
+
+import java.lang.annotation.Annotation;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class AnnotationImpl implements Annotation {
+ public Class extends Annotation> annotationType() {
+ return getClass();
+ }
+
+ @JavaScriptBody(args = { "a", "n", "values" }, body = ""
+ + "function f(v, p) {\n"
+ + " var val = v;\n"
+ + " var prop = p;\n"
+ + " return function() {\n"
+ + " return val[prop];\n"
+ + " };\n"
+ + "}\n"
+ + "var props = Object.getOwnPropertyNames(values);\n"
+ + "for (var i = 0; i < props.length; i++) {\n"
+ + " var p = props[i];\n"
+ + " a[p] = new f(values, p);\n"
+ + "}\n"
+ + "a['$instOf_' + n] = true;\n"
+ + "return a;"
+ )
+ private static T create(AnnotationImpl a, String n, Object values) {
+ return null;
+ }
+ public static T create(Class annoClass, Object values) {
+ return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
+ }
+
+ public static Annotation[] create(Object anno) {
+ String[] names = findNames(anno);
+ Annotation[] ret = new Annotation[names.length];
+ for (int i = 0; i < names.length; i++) {
+ String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
+ ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
+ }
+ return ret;
+ }
+ @JavaScriptBody(args = "anno", body =
+ "var arr = new Array();"
+ + "var props = Object.getOwnPropertyNames(anno);\n"
+ + "for (var i = 0; i < props.length; i++) {\n"
+ + " var p = props[i];\n"
+ + " arr.push(p);"
+ + "}"
+ + "return arr;"
+ )
+ private static String[] findNames(Object anno) {
+ throw new UnsupportedOperationException();
+ }
+
+ @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
+ private static Object findData(Object anno, String p) {
+ throw new UnsupportedOperationException();
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.apidesign.bck2brwsr.emul;
+
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/** Utilities to work on methods.
+ *
+ * @author Jaroslav Tulach
+ */
+public abstract class MethodImpl {
+ public static MethodImpl INSTANCE;
+ static {
+ try {
+ Class.forName(Method.class.getName());
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ protected abstract Method create(Class> declaringClass, String name, Object data, String sig);
+
+
+ //
+ // bck2brwsr implementation
+ //
+
+ @JavaScriptBody(args = {"clazz", "prefix"},
+ body = ""
+ + "var c = clazz.cnstr.prototype;"
+ + "var arr = new Array();\n"
+ + "for (m in c) {\n"
+ + " if (m.indexOf(prefix) === 0) {\n"
+ + " arr.push(m);\n"
+ + " arr.push(c[m]);\n"
+ + " }"
+ + "}\n"
+ + "return arr;")
+ private static native Object[] findMethodData(
+ Class> clazz, String prefix);
+
+ public static Method findMethod(
+ Class> clazz, String name, Class>... parameterTypes) {
+ Object[] data = findMethodData(clazz, name + "__");
+ BIG: for (int i = 0; i < data.length; i += 2) {
+ String sig = ((String) data[0]).substring(name.length() + 2);
+ Method tmp = INSTANCE.create(clazz, name, data[1], sig);
+ Class>[] tmpParms = tmp.getParameterTypes();
+ if (parameterTypes.length != tmpParms.length) {
+ continue;
+ }
+ for (int j = 0; j < tmpParms.length; j++) {
+ if (!parameterTypes[j].equals(tmpParms[j])) {
+ continue BIG;
+ }
+ }
+ return tmp;
+ }
+ return null;
+ }
+
+ public static Method[] findMethods(Class> clazz, int mask) {
+ Object[] namesAndData = findMethodData(clazz, "");
+ int cnt = 0;
+ for (int i = 0; i < namesAndData.length; i += 2) {
+ String sig = (String) namesAndData[i];
+ Object data = namesAndData[i + 1];
+ int middle = sig.indexOf("__");
+ if (middle == -1) {
+ continue;
+ }
+ String name = sig.substring(0, middle);
+ sig = sig.substring(middle + 2);
+ final Method m = INSTANCE.create(clazz, name, data, sig);
+ if ((m.getModifiers() & mask) == 0) {
+ continue;
+ }
+ namesAndData[cnt++] = m;
+ }
+ Method[] arr = new Method[cnt];
+ for (int i = 0; i < cnt; i++) {
+ arr[i] = (Method) namesAndData[i];
+ }
+ return arr;
+ }
+
+ public static int signatureElements(String sig) {
+ Enumeration en = signatureParser(sig);
+ int cnt = 0;
+ while (en.hasMoreElements()) {
+ en.nextElement();
+ cnt++;
+ }
+ return cnt;
+ }
+
+ public static Enumeration signatureParser(final String sig) {
+ class E implements Enumeration {
+ int pos;
+
+ public boolean hasMoreElements() {
+ return pos < sig.length();
+ }
+
+ public Class nextElement() {
+ switch (sig.charAt(pos++)) {
+ case 'I':
+ return Integer.TYPE;
+ case 'J':
+ return Long.TYPE;
+ case 'D':
+ return Double.TYPE;
+ case 'F':
+ return Float.TYPE;
+ case 'B':
+ return Byte.TYPE;
+ case 'Z':
+ return Boolean.TYPE;
+ case 'S':
+ return Short.TYPE;
+ case 'V':
+ return Void.TYPE;
+ case 'C':
+ return Character.TYPE;
+ case 'L':
+ try {
+ int up = sig.indexOf("_2");
+ String type = sig.substring(1, up);
+ pos = up + 2;
+ return Class.forName(type);
+ } catch (ClassNotFoundException ex) {
+ // should not happen
+ }
+ }
+ throw new UnsupportedOperationException(sig + " at " + pos);
+ }
+ }
+ return new E();
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,9 @@
+// empty line needed here
+Number.prototype.add32 = function(x) { return (this + x) | 0; };
+Number.prototype.sub32 = function(x) { return (this - x) | 0; };
+Number.prototype.mul32 = function(x) {
+ return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
+};
+
+Number.prototype.toInt8 = function() { return (this << 24) >> 24; };
+Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
\ No newline at end of file
diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js
--- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Thu Oct 11 06:15:22 2012 -0700
+++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Wed Jan 23 20:16:48 2013 +0100
@@ -1,2658 +1,26 @@
-/* */
+// initialize methods on arrays and String constants
+vm.java_lang_reflect_Array(false);
+vm.java_lang_String(false);
-
-function java_lang_String_consVAC(arg0,arg1) {
- arg0.r = arg1.join("");
-}
-
-function java_lang_String_consVACII(self, charArr, off, cnt) {
- self.r = charArr.slice(off, off + cnt).join("");
-}
-
-function java_lang_String_charAtCI(arg0,arg1) {
- return arg0.toString().charAt(arg1);
-}
-function java_lang_String_lengthI(arg0) {
- return arg0.toString().length;
-}
-function java_lang_String_isEmptyZ(arg0) {
- return arg0.toString().length === 0;
-}
-
-/*
-function java_lang_String_codePointAtII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11
- case 4: stack.push(arg1); // 27
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() > stack.pop()) { gt = 21; continue; } // 161 0 12
- case 12: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 15: stack.push(stack[stack.length - 1]); // 89
- case 16: stack.push(arg1); // 27
- case 17: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 20: // 191
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().value); // 180 1 100
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().offset); // 180 1 99
- case 29: stack.push(arg1); // 27
- case 30: stack.push(stack.pop() + stack.pop()); // 96
- case 31: stack.push(arg0); // 42
- case 32: stack.push(stack.pop().offset); // 180 1 99
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().count); // 180 1 97
- case 39: stack.push(stack.pop() + stack.pop()); // 96
- case 40: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointAtImplAIACAIAI(v0, v1, v2)); } // 184 1 113
- case 43: return stack.pop(); // 172
+Array.prototype.at = function(indx, value) {
+ if (indx < 0 || indx > this.length) {
+ var e = vm.java_lang_ArrayIndexOutOfBoundsException(true);
+ e.constructor.cons__VLjava_lang_String_2.call(e, indx.toString());
+ throw e;
}
-}
-function java_lang_String_codePointBeforeII(arg0,arg1) {
- var arg2;
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: stack.push(1); // 4
- case 2: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 3: arg2 = stack.pop(); // 61
- case 4: stack.push(arg2); // 28
- case 5: if (stack.pop() < 0) { gt = 16; continue; } // 155 0 11
- case 8: stack.push(arg2); // 28
- case 9: stack.push(arg0); // 42
- case 10: stack.push(stack.pop().count); // 180 1 97
- case 13: if (stack.pop() > stack.pop()) { gt = 25; continue; } // 161 0 12
- case 16: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 19: stack.push(stack[stack.length - 1]); // 89
- case 20: stack.push(arg1); // 27
- case 21: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 24: // 191
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().value); // 180 1 100
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: stack.push(arg1); // 27
- case 34: stack.push(stack.pop() + stack.pop()); // 96
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointBeforeImplAIACAIAI(v0, v1, v2)); } // 184 1 114
- case 42: return stack.pop(); // 172
+ if (arguments.length === 2) {
+ this[indx] = value;
}
-}
-function java_lang_String_codePointCountIII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 17; continue; } // 155 0 16
- case 4: stack.push(arg2); // 28
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() < stack.pop()) { gt = 17; continue; } // 163 0 8
- case 12: stack.push(arg1); // 27
- case 13: stack.push(arg2); // 28
- case 14: if (stack.pop() >= stack.pop()) { gt = 25; continue; } // 164 0 11
- case 17: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194
- case 20: stack.push(stack[stack.length - 1]); // 89
- case 21: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124
- case 24: // 191
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().value); // 180 1 100
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: stack.push(arg1); // 27
- case 34: stack.push(stack.pop() + stack.pop()); // 96
- case 35: stack.push(arg2); // 28
- case 36: stack.push(arg1); // 27
- case 37: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 38: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointCountImplAIACAIAI(v0, v1, v2)); } // 184 1 115
- case 41: return stack.pop(); // 172
+ return this[indx];
+};
+Array.prototype.getClass__Ljava_lang_Class_2 = function() {
+ return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2(this.jvmName);
+};
+Array.prototype.clone__Ljava_lang_Object_2 = function() {
+ var s = this.length;
+ var ret = new Array(s);
+ for (var i = 0; i < s; i++) {
+ ret[i] = this[i];
}
-}
-function java_lang_String_offsetByCodePointsIII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11
- case 4: stack.push(arg1); // 27
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() >= stack.pop()) { gt = 20; continue; } // 164 0 11
- case 12: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194
- case 15: stack.push(stack[stack.length - 1]); // 89
- case 16: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124
- case 19: // 191
- case 20: stack.push(arg0); // 42
- case 21: stack.push(stack.pop().value); // 180 1 100
- case 24: stack.push(arg0); // 42
- case 25: stack.push(stack.pop().offset); // 180 1 99
- case 28: stack.push(arg0); // 42
- case 29: stack.push(stack.pop().count); // 180 1 97
- case 32: stack.push(arg0); // 42
- case 33: stack.push(stack.pop().offset); // 180 1 99
- case 36: stack.push(arg1); // 27
- case 37: stack.push(stack.pop() + stack.pop()); // 96
- case 38: stack.push(arg2); // 28
- case 39: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_offsetByCodePointsImplAIACAIAIAIAI(v0, v1, v2, v3, v4)); } // 184 1 116
- case 42: stack.push(arg0); // 42
- case 43: stack.push(stack.pop().offset); // 180 1 99
- case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 47: return stack.pop(); // 172
- }
-}
-*/
-
-// public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
-function java_lang_String_getCharsVIIACAI(arg0,arg1,arg2,arg3,arg4) {
- var s = arg0.toString();
- while (arg1 < arg2) {
- arg3[arg4++] = s[arg1++];
- }
-}
-
-/*
-function java_lang_String_getBytesVIIABI(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12
- case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: stack.push(arg1); // 27
- case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 12: // 191
- case 13: stack.push(arg2); // 28
- case 14: stack.push(arg0); // 42
- case 15: stack.push(stack.pop().count); // 180 1 97
- case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg2); // 28
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg1); // 27
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14
- case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 38: stack.push(stack[stack.length - 1]); // 89
- case 39: stack.push(arg2); // 28
- case 40: stack.push(arg1); // 27
- case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 45: // 191
- case 46: stack.push(arg4); // 21 4
- case 48: arg5 = stack.pop() // 54 5
- case 50: stack.push(arg0); // 42
- case 51: stack.push(stack.pop().offset); // 180 1 99
- case 54: stack.push(arg2); // 28
- case 55: stack.push(stack.pop() + stack.pop()); // 96
- case 56: arg6 = stack.pop() // 54 6
- case 58: stack.push(arg0); // 42
- case 59: stack.push(stack.pop().offset); // 180 1 99
- case 62: stack.push(arg1); // 27
- case 63: stack.push(stack.pop() + stack.pop()); // 96
- case 64: arg7 = stack.pop() // 54 7
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().value); // 180 1 100
- case 70: arg8 = stack.pop() // 58 8
- case 72: stack.push(arg7); // 21 7
- case 74: stack.push(arg6); // 21 6
- case 76: if (stack.pop() <= stack.pop()) { gt = 98; continue; } // 162 0 22
- case 79: stack.push(arg3); // 45
- case 80: stack.push(arg5); // 21 5
- case 82: arg5++; // 132 5 1
- case 85: stack.push(arg8); // 25 8
- case 87: stack.push(arg7); // 21 7
- case 89: arg7++; // 132 7 1
- case 92: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 93: // number conversion // 145
- case 94: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 84
- case 95: gt = 72; continue; // 167 255 233
- case 98: return; // 177
- }
-}
-function java_lang_String_getBytesABLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(arg1); // 43
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().offset); // 180 1 99
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().count); // 180 1 97
- case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_lang_StringACAIAI(v0, v1, v2, v3)); } // 184 1 166
- case 28: return stack.pop(); // 176
- }
-}
-function java_lang_String_getBytesABLjava_nio_charset_Charset(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(arg1); // 43
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().offset); // 180 1 99
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().count); // 180 1 97
- case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_nio_charset_CharsetACAIAI(v0, v1, v2, v3)); } // 184 1 168
- case 28: return stack.pop(); // 176
- }
-}
-function java_lang_String_getBytesAB(arg0) {
- var arg1;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABACAIAI(v0, v1, v2)); } // 184 1 164
- case 15: return stack.pop(); // 176
- }
-}
-function java_lang_String_equalsZLjava_lang_Object(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: // 166
- case 3: // 0
- case 4: stack.push(2); // 5
- case 5: stack.push(1); // 4
- case 6: return stack.pop(); // 172
- case 7: stack.push(arg1); // 43
- case 8: stack.push(stack.pop().$instOf_java_lang_String ? 1 : 0); // 193 0 200
- case 11: if (stack.pop() == 0) { gt = 86; continue; } // 153 0 75
- case 14: stack.push(arg1); // 43
- case 15: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200
- case 18: arg2 = stack.pop(); // 77
- case 19: stack.push(arg0); // 42
- case 20: stack.push(stack.pop().count); // 180 1 97
- case 23: arg3 = stack.pop(); // 62
- case 24: stack.push(arg3); // 29
- case 25: stack.push(arg2); // 44
- case 26: stack.push(stack.pop().count); // 180 1 97
- case 29: if (stack.pop() != stack.pop()) { gt = 86; continue; } // 160 0 57
- case 32: stack.push(arg0); // 42
- case 33: stack.push(stack.pop().value); // 180 1 100
- case 36: arg4 = stack.pop() // 58 4
- case 38: stack.push(arg2); // 44
- case 39: stack.push(stack.pop().value); // 180 1 100
- case 42: arg5 = stack.pop() // 58 5
- case 44: stack.push(arg0); // 42
- case 45: stack.push(stack.pop().offset); // 180 1 99
- case 48: arg6 = stack.pop() // 54 6
- case 50: stack.push(arg2); // 44
- case 51: stack.push(stack.pop().offset); // 180 1 99
- case 54: arg7 = stack.pop() // 54 7
- case 56: stack.push(arg3); // 29
- case 57: arg3 += 255; // 132 3 255
- case 60: if (stack.pop() == 0) { gt = 84; continue; } // 153 0 24
- case 63: stack.push(arg4); // 25 4
- case 65: stack.push(arg6); // 21 6
- case 67: arg6++; // 132 6 1
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: stack.push(arg5); // 25 5
- case 73: stack.push(arg7); // 21 7
- case 75: arg7++; // 132 7 1
- case 78: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 79: if (stack.pop() == stack.pop()) { gt = 56; continue; } // 159 255 233
- case 82: stack.push(0); // 3
- case 83: return stack.pop(); // 172
- case 84: stack.push(1); // 4
- case 85: return stack.pop(); // 172
- case 86: stack.push(0); // 3
- case 87: return stack.pop(); // 172
- }
-}
-function java_lang_String_contentEqualsZLjava_lang_StringBuffer(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: stack.push(stack[stack.length - 1]); // 89
- case 2: arg2 = stack.pop(); // 77
- case 3: // 194
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 43
- case 6: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.contentEqualsZLjava_lang_CharSequence(self, v0)); } // 182 1 146
- case 9: stack.push(arg2); // 44
- case 10: // 195
- case 11: return stack.pop(); // 172
- case 12: arg3 = stack.pop(); // 78
- case 13: stack.push(arg2); // 44
- case 14: // 195
- case 15: stack.push(arg3); // 45
- case 16: // 191
- }
-}
-function java_lang_String_contentEqualsZLjava_lang_CharSequence(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: stack.push(arg1); // 43
- case 5: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 185 1 188
- case 8: // 1
- case 9: // 0
- case 10: if (stack.pop() == stack.pop()) { gt = 15; continue; } // 159 0 5
- case 13: stack.push(0); // 3
- case 14: return stack.pop(); // 172
- case 15: stack.push(arg1); // 43
- case 16: stack.push(stack.pop().$instOf_java_lang_AbstractStringBuilder ? 1 : 0); // 193 0 186
- case 19: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 58
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: arg2 = stack.pop(); // 77
- case 27: stack.push(arg1); // 43
- case 28: if(stack[stack.length - 1].$instOf_java_lang_AbstractStringBuilder != 1) throw {}; // 192 0 186
- case 31: { var self = stack.pop(); stack.push(self.getValueAC(self)); } // 182 1 103
- case 34: arg3 = stack.pop(); // 78
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: arg4 = stack.pop() // 54 4
- case 41: stack.push(0); // 3
- case 42: arg5 = stack.pop() // 54 5
- case 44: stack.push(arg0); // 42
- case 45: stack.push(stack.pop().count); // 180 1 97
- case 48: arg6 = stack.pop() // 54 6
- case 50: stack.push(arg6); // 21 6
- case 52: arg6 += 255; // 132 6 255
- case 55: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 22
- case 58: stack.push(arg2); // 44
- case 59: stack.push(arg4); // 21 4
- case 61: arg4++; // 132 4 1
- case 64: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 65: stack.push(arg3); // 45
- case 66: stack.push(arg5); // 21 5
- case 68: arg5++; // 132 5 1
- case 71: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 72: if (stack.pop() == stack.pop()) { gt = 50; continue; } // 159 255 234
- case 75: stack.push(0); // 3
- case 76: return stack.pop(); // 172
- case 77: stack.push(arg1); // 43
- case 78: stack.push(arg0); // 42
- case 79: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.equalsZLjava_lang_Object(self, v0)); } // 182 1 131
- case 82: if (stack.pop() == 0) { gt = 87; continue; } // 153 0 5
- case 85: stack.push(1); // 4
- case 86: return stack.pop(); // 172
- case 87: stack.push(arg0); // 42
- case 88: stack.push(stack.pop().value); // 180 1 100
- case 91: arg2 = stack.pop(); // 77
- case 92: stack.push(arg0); // 42
- case 93: stack.push(stack.pop().offset); // 180 1 99
- case 96: arg3 = stack.pop(); // 62
- case 97: stack.push(0); // 3
- case 98: arg4 = stack.pop() // 54 4
- case 100: stack.push(arg0); // 42
- case 101: stack.push(stack.pop().count); // 180 1 97
- case 104: arg5 = stack.pop() // 54 5
- case 106: stack.push(arg5); // 21 5
- case 108: arg5 += 255; // 132 5 255
- case 111: if (stack.pop() == 0) { gt = 136; continue; } // 153 0 25
- case 114: stack.push(arg2); // 44
- case 115: stack.push(arg3); // 29
- case 116: arg3++; // 132 3 1
- case 119: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 120: stack.push(arg1); // 43
- case 121: stack.push(arg4); // 21 4
- case 123: arg4++; // 132 4 1
- case 126: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.charAtCI(self, v0)); } // 185 1 189
- case 129: // 2
- case 130: // 0
- case 131: if (stack.pop() == stack.pop()) { gt = 106; continue; } // 159 255 231
- case 134: stack.push(0); // 3
- case 135: return stack.pop(); // 172
- case 136: stack.push(1); // 4
- case 137: return stack.pop(); // 172
- }
-}
-function java_lang_String_equalsIgnoreCaseZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: // 166
- case 3: // 0
- case 4: stack.push(4); // 7
- case 5: stack.push(1); // 4
- case 6: gt = 44; continue; // 167 0 38
- case 9: stack.push(arg1); // 43
- case 10: if (!stack.pop()) { gt = 43; continue; } // 198 0 33
- case 13: stack.push(arg1); // 43
- case 14: stack.push(stack.pop().count); // 180 1 97
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().count); // 180 1 97
- case 21: if (stack.pop() != stack.pop()) { gt = 43; continue; } // 160 0 22
- case 24: stack.push(arg0); // 42
- case 25: stack.push(1); // 4
- case 26: stack.push(0); // 3
- case 27: stack.push(arg1); // 43
- case 28: stack.push(0); // 3
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().count); // 180 1 97
- case 33: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.regionMatchesZZILjava_lang_StringII(self, v0, v1, v2, v3, v4)); } // 182 1 153
- case 36: if (stack.pop() == 0) { gt = 43; continue; } // 153 0 7
- case 39: stack.push(1); // 4
- case 40: gt = 44; continue; // 167 0 4
- case 43: stack.push(0); // 3
- case 44: return stack.pop(); // 172
- }
-}
-function java_lang_String_compareToILjava_lang_String(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: arg2 = stack.pop(); // 61
- case 5: stack.push(arg1); // 43
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg3 = stack.pop(); // 62
- case 10: stack.push(arg2); // 28
- case 11: stack.push(arg3); // 29
- case 12: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127
- case 15: arg4 = stack.pop() // 54 4
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().value); // 180 1 100
- case 21: arg5 = stack.pop() // 58 5
- case 23: stack.push(arg1); // 43
- case 24: stack.push(stack.pop().value); // 180 1 100
- case 27: arg6 = stack.pop() // 58 6
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: arg7 = stack.pop() // 54 7
- case 35: stack.push(arg1); // 43
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: arg8 = stack.pop() // 54 8
- case 41: stack.push(arg7); // 21 7
- case 43: stack.push(arg8); // 21 8
- case 45: if (stack.pop() != stack.pop()) { gt = 102; continue; } // 160 0 57
- case 48: stack.push(arg7); // 21 7
- case 50: arg9 = stack.pop() // 54 9
- case 52: stack.push(arg4); // 21 4
- case 54: stack.push(arg7); // 21 7
- case 56: stack.push(stack.pop() + stack.pop()); // 96
- case 57: arg10 = stack.pop() // 54 10
- case 59: stack.push(arg9); // 21 9
- case 61: stack.push(arg10); // 21 10
- case 63: if (stack.pop() <= stack.pop()) { gt = 99; continue; } // 162 0 36
- case 66: stack.push(arg5); // 25 5
- case 68: stack.push(arg9); // 21 9
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: arg11 = stack.pop() // 54 11
- case 73: stack.push(arg6); // 25 6
- case 75: stack.push(arg9); // 21 9
- case 77: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 78: arg12 = stack.pop() // 54 12
- case 80: stack.push(arg11); // 21 11
- case 82: stack.push(arg12); // 21 12
- case 84: if (stack.pop() == stack.pop()) { gt = 93; continue; } // 159 0 9
- case 87: stack.push(arg11); // 21 11
- case 89: stack.push(arg12); // 21 12
- case 91: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 92: return stack.pop(); // 172
- case 93: arg9++; // 132 9 1
- case 96: gt = 59; continue; // 167 255 219
- case 99: gt = 146; continue; // 167 0 47
- case 102: stack.push(arg4); // 21 4
- case 104: arg4 += 255; // 132 4 255
- case 107: if (stack.pop() == 0) { gt = 146; continue; } // 153 0 39
- case 110: stack.push(arg5); // 25 5
- case 112: stack.push(arg7); // 21 7
- case 114: arg7++; // 132 7 1
- case 117: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 118: arg9 = stack.pop() // 54 9
- case 120: stack.push(arg6); // 25 6
- case 122: stack.push(arg8); // 21 8
- case 124: arg8++; // 132 8 1
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: arg10 = stack.pop() // 54 10
- case 130: stack.push(arg9); // 21 9
- case 132: stack.push(arg10); // 21 10
- case 134: if (stack.pop() == stack.pop()) { gt = 143; continue; } // 159 0 9
- case 137: stack.push(arg9); // 21 9
- case 139: stack.push(arg10); // 21 10
- case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 142: return stack.pop(); // 172
- case 143: gt = 102; continue; // 167 255 215
- case 146: stack.push(arg2); // 28
- case 147: stack.push(arg3); // 29
- case 148: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 149: return stack.pop(); // 172
- }
-}
-function java_lang_String_compareToIgnoreCaseILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(java_lang_String_CASE_INSENSITIVE_ORDER); // 178 1 102
- case 3: stack.push(arg0); // 42
- case 4: stack.push(arg1); // 43
- case 5: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareILjava_lang_ObjectLjava_lang_Object(self, v0, v1)); } // 185 1 190
- case 8: stack.push(0); // 3
- case 9: // 0
- case 10: return stack.pop(); // 172
- }
-}
-function java_lang_String_regionMatchesZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg5 = stack.pop() // 58 5
- case 6: stack.push(arg0); // 42
- case 7: stack.push(stack.pop().offset); // 180 1 99
- case 10: stack.push(arg1); // 27
- case 11: stack.push(stack.pop() + stack.pop()); // 96
- case 12: arg6 = stack.pop() // 54 6
- case 14: stack.push(arg2); // 44
- case 15: stack.push(stack.pop().value); // 180 1 100
- case 18: arg7 = stack.pop() // 58 7
- case 20: stack.push(arg2); // 44
- case 21: stack.push(stack.pop().offset); // 180 1 99
- case 24: stack.push(arg3); // 29
- case 25: stack.push(stack.pop() + stack.pop()); // 96
- case 26: arg8 = stack.pop() // 54 8
- case 28: stack.push(arg3); // 29
- case 29: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 37
- case 32: stack.push(arg1); // 27
- case 33: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 33
- case 36: stack.push(arg1); // 27
- case 37: // number conversion // 133
- case 38: stack.push(arg0); // 42
- case 39: stack.push(stack.pop().count); // 180 1 97
- case 42: // number conversion // 133
- case 43: stack.push(arg4); // 21 4
- case 45: // number conversion // 133
- case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 47: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 48: if (stack.pop() > 0) { gt = 66; continue; } // 157 0 18
- case 51: stack.push(arg3); // 29
- case 52: // number conversion // 133
- case 53: stack.push(arg2); // 44
- case 54: stack.push(stack.pop().count); // 180 1 97
- case 57: // number conversion // 133
- case 58: stack.push(arg4); // 21 4
- case 60: // number conversion // 133
- case 61: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 62: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 63: if (stack.pop() <= 0) { gt = 68; continue; } // 158 0 5
- case 66: stack.push(0); // 3
- case 67: return stack.pop(); // 172
- case 68: stack.push(arg4); // 21 4
- case 70: arg4 += 255; // 132 4 255
- case 73: if (stack.pop() <= 0) { gt = 97; continue; } // 158 0 24
- case 76: stack.push(arg5); // 25 5
- case 78: stack.push(arg6); // 21 6
- case 80: arg6++; // 132 6 1
- case 83: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 84: stack.push(arg7); // 25 7
- case 86: stack.push(arg8); // 21 8
- case 88: arg8++; // 132 8 1
- case 91: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 92: if (stack.pop() == stack.pop()) { gt = 68; continue; } // 159 255 232
- case 95: stack.push(0); // 3
- case 96: return stack.pop(); // 172
- case 97: stack.push(1); // 4
- case 98: return stack.pop(); // 172
- }
-}
-function java_lang_String_regionMatchesZZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4,arg5) {
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg6 = stack.pop() // 58 6
- case 6: stack.push(arg0); // 42
- case 7: stack.push(stack.pop().offset); // 180 1 99
- case 10: stack.push(arg2); // 28
- case 11: stack.push(stack.pop() + stack.pop()); // 96
- case 12: arg7 = stack.pop() // 54 7
- case 14: stack.push(arg3); // 45
- case 15: stack.push(stack.pop().value); // 180 1 100
- case 18: arg8 = stack.pop() // 58 8
- case 20: stack.push(arg3); // 45
- case 21: stack.push(stack.pop().offset); // 180 1 99
- case 24: stack.push(arg4); // 21 4
- case 26: stack.push(stack.pop() + stack.pop()); // 96
- case 27: arg9 = stack.pop() // 54 9
- case 29: stack.push(arg4); // 21 4
- case 31: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 38
- case 34: stack.push(arg2); // 28
- case 35: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 34
- case 38: stack.push(arg2); // 28
- case 39: // number conversion // 133
- case 40: stack.push(arg0); // 42
- case 41: stack.push(stack.pop().count); // 180 1 97
- case 44: // number conversion // 133
- case 45: stack.push(arg5); // 21 5
- case 47: // number conversion // 133
- case 48: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 49: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 50: if (stack.pop() > 0) { gt = 69; continue; } // 157 0 19
- case 53: stack.push(arg4); // 21 4
- case 55: // number conversion // 133
- case 56: stack.push(arg3); // 45
- case 57: stack.push(stack.pop().count); // 180 1 97
- case 60: // number conversion // 133
- case 61: stack.push(arg5); // 21 5
- case 63: // number conversion // 133
- case 64: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 65: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 66: if (stack.pop() <= 0) { gt = 71; continue; } // 158 0 5
- case 69: stack.push(0); // 3
- case 70: return stack.pop(); // 172
- case 71: stack.push(arg5); // 21 5
- case 73: arg5 += 255; // 132 5 255
- case 76: if (stack.pop() <= 0) { gt = 155; continue; } // 158 0 79
- case 79: stack.push(arg6); // 25 6
- case 81: stack.push(arg7); // 21 7
- case 83: arg7++; // 132 7 1
- case 86: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 87: arg10 = stack.pop() // 54 10
- case 89: stack.push(arg8); // 25 8
- case 91: stack.push(arg9); // 21 9
- case 93: arg9++; // 132 9 1
- case 96: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 97: arg11 = stack.pop() // 54 11
- case 99: stack.push(arg10); // 21 10
- case 101: stack.push(arg11); // 21 11
- case 103: if (stack.pop() != stack.pop()) { gt = 109; continue; } // 160 0 6
- case 106: gt = 71; continue; // 167 255 221
- case 109: stack.push(arg1); // 27
- case 110: if (stack.pop() == 0) { gt = 153; continue; } // 153 0 43
- case 113: stack.push(arg10); // 21 10
- case 115: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105
- case 118: arg12 = stack.pop() // 54 12
- case 120: stack.push(arg11); // 21 11
- case 122: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105
- case 125: arg13 = stack.pop() // 54 13
- case 127: stack.push(arg12); // 21 12
- case 129: stack.push(arg13); // 21 13
- case 131: if (stack.pop() != stack.pop()) { gt = 137; continue; } // 160 0 6
- case 134: gt = 71; continue; // 167 255 193
- case 137: stack.push(arg12); // 21 12
- case 139: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 142: stack.push(arg13); // 21 13
- case 144: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 147: if (stack.pop() != stack.pop()) { gt = 153; continue; } // 160 0 6
- case 150: gt = 71; continue; // 167 255 177
- case 153: stack.push(0); // 3
- case 154: return stack.pop(); // 172
- case 155: stack.push(1); // 4
- case 156: return stack.pop(); // 172
- }
-}
-function java_lang_String_startsWithZLjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg3 = stack.pop(); // 78
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().offset); // 180 1 99
- case 9: stack.push(arg2); // 28
- case 10: stack.push(stack.pop() + stack.pop()); // 96
- case 11: arg4 = stack.pop() // 54 4
- case 13: stack.push(arg1); // 43
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: arg5 = stack.pop() // 58 5
- case 19: stack.push(arg1); // 43
- case 20: stack.push(stack.pop().offset); // 180 1 99
- case 23: arg6 = stack.pop() // 54 6
- case 25: stack.push(arg1); // 43
- case 26: stack.push(stack.pop().count); // 180 1 97
- case 29: arg7 = stack.pop() // 54 7
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() < 0) { gt = 46; continue; } // 155 0 14
- case 35: stack.push(arg2); // 28
- case 36: stack.push(arg0); // 42
- case 37: stack.push(stack.pop().count); // 180 1 97
- case 40: stack.push(arg7); // 21 7
- case 42: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 43: if (stack.pop() >= stack.pop()) { gt = 48; continue; } // 164 0 5
- case 46: stack.push(0); // 3
- case 47: return stack.pop(); // 172
- case 48: arg7 += 255; // 132 7 255
- case 51: stack.push(arg7); // 21 7
- case 53: if (stack.pop() < 0) { gt = 76; continue; } // 155 0 23
- case 56: stack.push(arg3); // 45
- case 57: stack.push(arg4); // 21 4
- case 59: arg4++; // 132 4 1
- case 62: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 63: stack.push(arg5); // 25 5
- case 65: stack.push(arg6); // 21 6
- case 67: arg6++; // 132 6 1
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: if (stack.pop() == stack.pop()) { gt = 48; continue; } // 159 255 233
- case 74: stack.push(0); // 3
- case 75: return stack.pop(); // 172
- case 76: stack.push(1); // 4
- case 77: return stack.pop(); // 172
- }
-}
-function java_lang_String_startsWithZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_endsWithZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: stack.push(arg1); // 43
- case 7: stack.push(stack.pop().count); // 180 1 97
- case 10: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 11: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152
- case 14: return stack.pop(); // 172
- }
-}
-function java_lang_String_hashCodeI(arg0) {
- var arg1;
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().hash); // 180 1 98
- case 4: arg1 = stack.pop(); // 60
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg2 = stack.pop(); // 61
- case 10: stack.push(arg1); // 27
- case 11: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 51
- case 14: stack.push(arg2); // 28
- case 15: if (stack.pop() <= 0) { gt = 62; continue; } // 158 0 47
- case 18: stack.push(arg0); // 42
- case 19: stack.push(stack.pop().offset); // 180 1 99
- case 22: arg3 = stack.pop(); // 62
- case 23: stack.push(arg0); // 42
- case 24: stack.push(stack.pop().value); // 180 1 100
- case 27: arg4 = stack.pop() // 58 4
- case 29: stack.push(0); // 3
- case 30: arg5 = stack.pop() // 54 5
- case 32: stack.push(arg5); // 21 5
- case 34: stack.push(arg2); // 28
- case 35: if (stack.pop() <= stack.pop()) { gt = 57; continue; } // 162 0 22
- case 38: stack.push(31); // 16 31
- case 40: stack.push(arg1); // 27
- case 41: stack.push(stack.pop() * stack.pop()); // 104
- case 42: stack.push(arg4); // 25 4
- case 44: stack.push(arg3); // 29
- case 45: arg3++; // 132 3 1
- case 48: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 49: stack.push(stack.pop() + stack.pop()); // 96
- case 50: arg1 = stack.pop(); // 60
- case 51: arg5++; // 132 5 1
- case 54: gt = 32; continue; // 167 255 234
- case 57: stack.push(arg0); // 42
- case 58: stack.push(arg1); // 27
- case 59: { var v = stack.pop(); stack.pop().hash = v; } // 181 1 98
- case 62: stack.push(arg1); // 27
- case 63: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfIII(self, v0, v1)); } // 182 1 135
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfIII(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().offset); // 180 1 99
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().count); // 180 1 97
- case 8: stack.push(stack.pop() + stack.pop()); // 96
- case 9: arg3 = stack.pop(); // 62
- case 10: stack.push(arg0); // 42
- case 11: stack.push(stack.pop().value); // 180 1 100
- case 14: arg4 = stack.pop() // 58 4
- case 16: stack.push(arg2); // 28
- case 17: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 8
- case 20: stack.push(0); // 3
- case 21: arg2 = stack.pop(); // 61
- case 22: gt = 35; continue; // 167 0 13
- case 25: stack.push(arg2); // 28
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().count); // 180 1 97
- case 30: if (stack.pop() > stack.pop()) { gt = 35; continue; } // 161 0 5
- case 33: // 2
- case 34: return stack.pop(); // 172
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: stack.push(arg2); // 28
- case 40: stack.push(stack.pop() + stack.pop()); // 96
- case 41: arg5 = stack.pop() // 54 5
- case 43: stack.push(arg1); // 27
- case 44: stack.push(65536); // 18 3
- case 46: if (stack.pop() <= stack.pop()) { gt = 80; continue; } // 162 0 34
- case 49: stack.push(arg5); // 21 5
- case 51: stack.push(arg3); // 29
- case 52: if (stack.pop() <= stack.pop()) { gt = 78; continue; } // 162 0 26
- case 55: stack.push(arg4); // 25 4
- case 57: stack.push(arg5); // 21 5
- case 59: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 60: stack.push(arg1); // 27
- case 61: if (stack.pop() != stack.pop()) { gt = 72; continue; } // 160 0 11
- case 64: stack.push(arg5); // 21 5
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().offset); // 180 1 99
- case 70: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 71: return stack.pop(); // 172
- case 72: arg5++; // 132 5 1
- case 75: gt = 49; continue; // 167 255 230
- case 78: // 2
- case 79: return stack.pop(); // 172
- case 80: stack.push(arg1); // 27
- case 81: stack.push(1114111); // 18 4
- case 83: if (stack.pop() < stack.pop()) { gt = 149; continue; } // 163 0 66
- case 86: stack.push(arg1); // 27
- case 87: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 90: arg6 = stack.pop() // 58 6
- case 92: stack.push(arg5); // 21 5
- case 94: stack.push(arg3); // 29
- case 95: if (stack.pop() <= stack.pop()) { gt = 149; continue; } // 162 0 54
- case 98: stack.push(arg4); // 25 4
- case 100: stack.push(arg5); // 21 5
- case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 103: stack.push(arg6); // 25 6
- case 105: stack.push(0); // 3
- case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 107: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 36
- case 110: stack.push(arg5); // 21 5
- case 112: stack.push(1); // 4
- case 113: stack.push(stack.pop() + stack.pop()); // 96
- case 114: stack.push(arg3); // 29
- case 115: if (stack.pop() != stack.pop()) { gt = 121; continue; } // 160 0 6
- case 118: gt = 149; continue; // 167 0 31
- case 121: stack.push(arg4); // 25 4
- case 123: stack.push(arg5); // 21 5
- case 125: stack.push(1); // 4
- case 126: stack.push(stack.pop() + stack.pop()); // 96
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: stack.push(arg6); // 25 6
- case 130: stack.push(1); // 4
- case 131: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 132: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 11
- case 135: stack.push(arg5); // 21 5
- case 137: stack.push(arg0); // 42
- case 138: stack.push(stack.pop().offset); // 180 1 99
- case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 142: return stack.pop(); // 172
- case 143: arg5++; // 132 5 1
- case 146: gt = 92; continue; // 167 255 202
- case 149: // 2
- case 150: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: stack.push(1); // 4
- case 7: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 8: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfIII(self, v0, v1)); } // 182 1 136
- case 11: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfIII(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().offset); // 180 1 99
- case 4: arg3 = stack.pop(); // 62
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().value); // 180 1 100
- case 9: arg4 = stack.pop() // 58 4
- case 11: stack.push(arg0); // 42
- case 12: stack.push(stack.pop().offset); // 180 1 99
- case 15: stack.push(arg2); // 28
- case 16: stack.push(arg0); // 42
- case 17: stack.push(stack.pop().count); // 180 1 97
- case 20: if (stack.pop() > stack.pop()) { gt = 32; continue; } // 161 0 12
- case 23: stack.push(arg0); // 42
- case 24: stack.push(stack.pop().count); // 180 1 97
- case 27: stack.push(1); // 4
- case 28: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 29: gt = 33; continue; // 167 0 4
- case 32: stack.push(arg2); // 28
- case 33: stack.push(stack.pop() + stack.pop()); // 96
- case 34: arg5 = stack.pop() // 54 5
- case 36: stack.push(arg1); // 27
- case 37: stack.push(65536); // 18 3
- case 39: if (stack.pop() <= stack.pop()) { gt = 73; continue; } // 162 0 34
- case 42: stack.push(arg5); // 21 5
- case 44: stack.push(arg3); // 29
- case 45: if (stack.pop() > stack.pop()) { gt = 71; continue; } // 161 0 26
- case 48: stack.push(arg4); // 25 4
- case 50: stack.push(arg5); // 21 5
- case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 53: stack.push(arg1); // 27
- case 54: if (stack.pop() != stack.pop()) { gt = 65; continue; } // 160 0 11
- case 57: stack.push(arg5); // 21 5
- case 59: stack.push(arg0); // 42
- case 60: stack.push(stack.pop().offset); // 180 1 99
- case 63: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 64: return stack.pop(); // 172
- case 65: arg5 += 255; // 132 5 255
- case 68: gt = 42; continue; // 167 255 230
- case 71: // 2
- case 72: return stack.pop(); // 172
- case 73: stack.push(arg0); // 42
- case 74: stack.push(stack.pop().offset); // 180 1 99
- case 77: stack.push(arg0); // 42
- case 78: stack.push(stack.pop().count); // 180 1 97
- case 81: stack.push(stack.pop() + stack.pop()); // 96
- case 82: arg6 = stack.pop() // 54 6
- case 84: stack.push(arg1); // 27
- case 85: stack.push(1114111); // 18 4
- case 87: if (stack.pop() < stack.pop()) { gt = 154; continue; } // 163 0 67
- case 90: stack.push(arg1); // 27
- case 91: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 94: arg7 = stack.pop() // 58 7
- case 96: stack.push(arg5); // 21 5
- case 98: stack.push(arg3); // 29
- case 99: if (stack.pop() > stack.pop()) { gt = 154; continue; } // 161 0 55
- case 102: stack.push(arg4); // 25 4
- case 104: stack.push(arg5); // 21 5
- case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 107: stack.push(arg7); // 25 7
- case 109: stack.push(0); // 3
- case 110: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 111: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 37
- case 114: stack.push(arg5); // 21 5
- case 116: stack.push(1); // 4
- case 117: stack.push(stack.pop() + stack.pop()); // 96
- case 118: stack.push(arg6); // 21 6
- case 120: if (stack.pop() != stack.pop()) { gt = 126; continue; } // 160 0 6
- case 123: gt = 154; continue; // 167 0 31
- case 126: stack.push(arg4); // 25 4
- case 128: stack.push(arg5); // 21 5
- case 130: stack.push(1); // 4
- case 131: stack.push(stack.pop() + stack.pop()); // 96
- case 132: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 133: stack.push(arg7); // 25 7
- case 135: stack.push(1); // 4
- case 136: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 137: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 11
- case 140: stack.push(arg5); // 21 5
- case 142: stack.push(arg0); // 42
- case 143: stack.push(stack.pop().offset); // 180 1 99
- case 146: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 147: return stack.pop(); // 172
- case 148: arg5 += 255; // 132 5 255
- case 151: gt = 96; continue; // 167 255 201
- case 154: // 2
- case 155: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 150
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfILjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(7);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: stack.push(arg1); // 43
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: stack.push(arg1); // 43
- case 17: stack.push(stack.pop().offset); // 180 1 99
- case 20: stack.push(arg1); // 43
- case 21: stack.push(stack.pop().count); // 180 1 97
- case 24: stack.push(arg2); // 28
- case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_indexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 144
- case 28: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) {
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg6); // 21 6
- case 2: stack.push(arg2); // 28
- case 3: if (stack.pop() > stack.pop()) { gt = 17; continue; } // 161 0 14
- case 6: stack.push(arg5); // 21 5
- case 8: if (stack.pop() != 0) { gt = 15; continue; } // 154 0 7
- case 11: stack.push(arg2); // 28
- case 12: gt = 16; continue; // 167 0 4
- case 15: // 2
- case 16: return stack.pop(); // 172
- case 17: stack.push(arg6); // 21 6
- case 19: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 6
- case 22: stack.push(0); // 3
- case 23: arg6 = stack.pop() // 54 6
- case 25: stack.push(arg5); // 21 5
- case 27: if (stack.pop() != 0) { gt = 33; continue; } // 154 0 6
- case 30: stack.push(arg6); // 21 6
- case 32: return stack.pop(); // 172
- case 33: stack.push(arg3); // 45
- case 34: stack.push(arg4); // 21 4
- case 36: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 37: arg7 = stack.pop() // 54 7
- case 39: stack.push(arg1); // 27
- case 40: stack.push(arg2); // 28
- case 41: stack.push(arg5); // 21 5
- case 43: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 44: stack.push(stack.pop() + stack.pop()); // 96
- case 45: arg8 = stack.pop() // 54 8
- case 47: stack.push(arg1); // 27
- case 48: stack.push(arg6); // 21 6
- case 50: stack.push(stack.pop() + stack.pop()); // 96
- case 51: arg9 = stack.pop() // 54 9
- case 53: stack.push(arg9); // 21 9
- case 55: stack.push(arg8); // 21 8
- case 57: if (stack.pop() < stack.pop()) { gt = 164; continue; } // 163 0 107
- case 60: stack.push(arg0); // 42
- case 61: stack.push(arg9); // 21 9
- case 63: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 64: stack.push(arg7); // 21 7
- case 66: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 25
- case 69: arg9++; // 132 9 1
- case 72: stack.push(arg9); // 21 9
- case 74: stack.push(arg8); // 21 8
- case 76: if (stack.pop() < stack.pop()) { gt = 91; continue; } // 163 0 15
- case 79: stack.push(arg0); // 42
- case 80: stack.push(arg9); // 21 9
- case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 83: stack.push(arg7); // 21 7
- case 85: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 6
- case 88: gt = 69; continue; // 167 255 237
- case 91: stack.push(arg9); // 21 9
- case 93: stack.push(arg8); // 21 8
- case 95: if (stack.pop() < stack.pop()) { gt = 158; continue; } // 163 0 63
- case 98: stack.push(arg9); // 21 9
- case 100: stack.push(1); // 4
- case 101: stack.push(stack.pop() + stack.pop()); // 96
- case 102: arg10 = stack.pop() // 54 10
- case 104: stack.push(arg10); // 21 10
- case 106: stack.push(arg5); // 21 5
- case 108: stack.push(stack.pop() + stack.pop()); // 96
- case 109: stack.push(1); // 4
- case 110: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 111: arg11 = stack.pop() // 54 11
- case 113: stack.push(arg4); // 21 4
- case 115: stack.push(1); // 4
- case 116: stack.push(stack.pop() + stack.pop()); // 96
- case 117: arg12 = stack.pop() // 54 12
- case 119: stack.push(arg10); // 21 10
- case 121: stack.push(arg11); // 21 11
- case 123: if (stack.pop() <= stack.pop()) { gt = 146; continue; } // 162 0 23
- case 126: stack.push(arg0); // 42
- case 127: stack.push(arg10); // 21 10
- case 129: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 130: stack.push(arg3); // 45
- case 131: stack.push(arg12); // 21 12
- case 133: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 134: if (stack.pop() != stack.pop()) { gt = 146; continue; } // 160 0 12
- case 137: arg10++; // 132 10 1
- case 140: arg12++; // 132 12 1
- case 143: gt = 119; continue; // 167 255 232
- case 146: stack.push(arg10); // 21 10
- case 148: stack.push(arg11); // 21 11
- case 150: if (stack.pop() != stack.pop()) { gt = 158; continue; } // 160 0 8
- case 153: stack.push(arg9); // 21 9
- case 155: stack.push(arg1); // 27
- case 156: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 157: return stack.pop(); // 172
- case 158: arg9++; // 132 9 1
- case 161: gt = 53; continue; // 167 255 148
- case 164: // 2
- case 165: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 151
- case 9: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfILjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(7);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: stack.push(arg1); // 43
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: stack.push(arg1); // 43
- case 17: stack.push(stack.pop().offset); // 180 1 99
- case 20: stack.push(arg1); // 43
- case 21: stack.push(stack.pop().count); // 180 1 97
- case 24: stack.push(arg2); // 28
- case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_lastIndexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 145
- case 28: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) {
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg2); // 28
- case 1: stack.push(arg5); // 21 5
- case 3: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 4: arg7 = stack.pop() // 54 7
- case 6: stack.push(arg6); // 21 6
- case 8: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 5
- case 11: // 2
- case 12: return stack.pop(); // 172
- case 13: stack.push(arg6); // 21 6
- case 15: stack.push(arg7); // 21 7
- case 17: if (stack.pop() >= stack.pop()) { gt = 24; continue; } // 164 0 7
- case 20: stack.push(arg7); // 21 7
- case 22: arg6 = stack.pop() // 54 6
- case 24: stack.push(arg5); // 21 5
- case 26: if (stack.pop() != 0) { gt = 32; continue; } // 154 0 6
- case 29: stack.push(arg6); // 21 6
- case 31: return stack.pop(); // 172
- case 32: stack.push(arg4); // 21 4
- case 34: stack.push(arg5); // 21 5
- case 36: stack.push(stack.pop() + stack.pop()); // 96
- case 37: stack.push(1); // 4
- case 38: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 39: arg8 = stack.pop() // 54 8
- case 41: stack.push(arg3); // 45
- case 42: stack.push(arg8); // 21 8
- case 44: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 45: arg9 = stack.pop() // 54 9
- case 47: stack.push(arg1); // 27
- case 48: stack.push(arg5); // 21 5
- case 50: stack.push(stack.pop() + stack.pop()); // 96
- case 51: stack.push(1); // 4
- case 52: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 53: arg10 = stack.pop() // 54 10
- case 55: stack.push(arg10); // 21 10
- case 57: stack.push(arg6); // 21 6
- case 59: stack.push(stack.pop() + stack.pop()); // 96
- case 60: arg11 = stack.pop() // 54 11
- case 62: stack.push(arg11); // 21 11
- case 64: stack.push(arg10); // 21 10
- case 66: if (stack.pop() > stack.pop()) { gt = 84; continue; } // 161 0 18
- case 69: stack.push(arg0); // 42
- case 70: stack.push(arg11); // 21 11
- case 72: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 73: stack.push(arg9); // 21 9
- case 75: if (stack.pop() == stack.pop()) { gt = 84; continue; } // 159 0 9
- case 78: arg11 += 255; // 132 11 255
- case 81: gt = 62; continue; // 167 255 237
- case 84: stack.push(arg11); // 21 11
- case 86: stack.push(arg10); // 21 10
- case 88: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 5
- case 91: // 2
- case 92: return stack.pop(); // 172
- case 93: stack.push(arg11); // 21 11
- case 95: stack.push(1); // 4
- case 96: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 97: arg12 = stack.pop() // 54 12
- case 99: stack.push(arg12); // 21 12
- case 101: stack.push(arg5); // 21 5
- case 103: stack.push(1); // 4
- case 104: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 105: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 106: arg13 = stack.pop() // 54 13
- case 108: stack.push(arg8); // 21 8
- case 110: stack.push(1); // 4
- case 111: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 112: arg14 = stack.pop() // 54 14
- case 114: stack.push(arg12); // 21 12
- case 116: stack.push(arg13); // 21 13
- case 118: if (stack.pop() >= stack.pop()) { gt = 144; continue; } // 164 0 26
- case 121: stack.push(arg0); // 42
- case 122: stack.push(arg12); // 21 12
- case 124: arg12 += 255; // 132 12 255
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: stack.push(arg3); // 45
- case 129: stack.push(arg14); // 21 14
- case 131: arg14 += 255; // 132 14 255
- case 134: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 135: if (stack.pop() == stack.pop()) { gt = 114; continue; } // 159 255 235
- case 138: arg11 += 255; // 132 11 255
- case 141: gt = 62; continue; // 167 255 177
- case 144: stack.push(arg13); // 21 13
- case 146: stack.push(arg1); // 27
- case 147: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 148: stack.push(1); // 4
- case 149: stack.push(stack.pop() + stack.pop()); // 96
- case 150: return stack.pop(); // 172
- }
-}
-function java_lang_String_substringLjava_lang_StringI(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 9: return stack.pop(); // 176
- }
-}
-function java_lang_String_substringLjava_lang_StringII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12
- case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: stack.push(arg1); // 27
- case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 12: // 191
- case 13: stack.push(arg2); // 28
- case 14: stack.push(arg0); // 42
- case 15: stack.push(stack.pop().count); // 180 1 97
- case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg2); // 28
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg1); // 27
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14
- case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 38: stack.push(stack[stack.length - 1]); // 89
- case 39: stack.push(arg2); // 28
- case 40: stack.push(arg1); // 27
- case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 45: // 191
- case 46: stack.push(arg1); // 27
- case 47: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 15
- case 50: stack.push(arg2); // 28
- case 51: stack.push(arg0); // 42
- case 52: stack.push(stack.pop().count); // 180 1 97
- case 55: if (stack.pop() != stack.pop()) { gt = 62; continue; } // 160 0 7
- case 58: stack.push(arg0); // 42
- case 59: gt = 82; continue; // 167 0 23
- case 62: stack.push(new java_lang_String); // 187 0 200
- case 65: stack.push(stack[stack.length - 1]); // 89
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().offset); // 180 1 99
- case 70: stack.push(arg1); // 27
- case 71: stack.push(stack.pop() + stack.pop()); // 96
- case 72: stack.push(arg2); // 28
- case 73: stack.push(arg1); // 27
- case 74: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 75: stack.push(arg0); // 42
- case 76: stack.push(stack.pop().value); // 180 1 100
- case 79: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 82: return stack.pop(); // 176
- }
-}
-function java_lang_String_subSequenceLjava_lang_CharSequenceII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg2); // 28
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_concatLjava_lang_StringLjava_lang_String(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 182 1 133
- case 4: arg2 = stack.pop(); // 61
- case 5: stack.push(arg2); // 28
- case 6: if (stack.pop() != 0) { gt = 11; continue; } // 154 0 5
- case 9: stack.push(arg0); // 42
- case 10: return stack.pop(); // 176
- case 11: stack.push(arg0); // 42
- case 12: stack.push(stack.pop().count); // 180 1 97
- case 15: stack.push(arg2); // 28
- case 16: stack.push(stack.pop() + stack.pop()); // 96
- case 17: stack.push(new Array(stack.pop())); // 188 5
- case 19: arg3 = stack.pop(); // 78
- case 20: stack.push(arg0); // 42
- case 21: stack.push(0); // 3
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().count); // 180 1 97
- case 26: stack.push(arg3); // 45
- case 27: stack.push(0); // 3
- case 28: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 31: stack.push(arg1); // 43
- case 32: stack.push(0); // 3
- case 33: stack.push(arg2); // 28
- case 34: stack.push(arg3); // 45
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().count); // 180 1 97
- case 39: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 42: stack.push(new java_lang_String); // 187 0 200
- case 45: stack.push(stack[stack.length - 1]); // 89
- case 46: stack.push(0); // 3
- case 47: stack.push(arg0); // 42
- case 48: stack.push(stack.pop().count); // 180 1 97
- case 51: stack.push(arg2); // 28
- case 52: stack.push(stack.pop() + stack.pop()); // 96
- case 53: stack.push(arg3); // 45
- case 54: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 57: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: stack.push(arg2); // 28
- case 2: if (stack.pop() == stack.pop()) { gt = 140; continue; } // 159 0 138
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg3 = stack.pop(); // 62
- case 10: // 2
- case 11: arg4 = stack.pop() // 54 4
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: arg5 = stack.pop() // 58 5
- case 19: stack.push(arg0); // 42
- case 20: stack.push(stack.pop().offset); // 180 1 99
- case 23: arg6 = stack.pop() // 54 6
- case 25: arg4++; // 132 4 1
- case 28: stack.push(arg4); // 21 4
- case 30: stack.push(arg3); // 29
- case 31: if (stack.pop() <= stack.pop()) { gt = 49; continue; } // 162 0 18
- case 34: stack.push(arg5); // 25 5
- case 36: stack.push(arg6); // 21 6
- case 38: stack.push(arg4); // 21 4
- case 40: stack.push(stack.pop() + stack.pop()); // 96
- case 41: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 42: stack.push(arg1); // 27
- case 43: if (stack.pop() != stack.pop()) { gt = 25; continue; } // 160 255 238
- case 46: gt = 49; continue; // 167 0 3
- case 49: stack.push(arg4); // 21 4
- case 51: stack.push(arg3); // 29
- case 52: if (stack.pop() <= stack.pop()) { gt = 140; continue; } // 162 0 88
- case 55: stack.push(arg3); // 29
- case 56: stack.push(new Array(stack.pop())); // 188 5
- case 58: arg7 = stack.pop() // 58 7
- case 60: stack.push(0); // 3
- case 61: arg8 = stack.pop() // 54 8
- case 63: stack.push(arg8); // 21 8
- case 65: stack.push(arg4); // 21 4
- case 67: if (stack.pop() <= stack.pop()) { gt = 89; continue; } // 162 0 22
- case 70: stack.push(arg7); // 25 7
- case 72: stack.push(arg8); // 21 8
- case 74: stack.push(arg5); // 25 5
- case 76: stack.push(arg6); // 21 6
- case 78: stack.push(arg8); // 21 8
- case 80: stack.push(stack.pop() + stack.pop()); // 96
- case 81: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 82: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 83: arg8++; // 132 8 1
- case 86: gt = 63; continue; // 167 255 233
- case 89: stack.push(arg4); // 21 4
- case 91: stack.push(arg3); // 29
- case 92: if (stack.pop() <= stack.pop()) { gt = 128; continue; } // 162 0 36
- case 95: stack.push(arg5); // 25 5
- case 97: stack.push(arg6); // 21 6
- case 99: stack.push(arg4); // 21 4
- case 101: stack.push(stack.pop() + stack.pop()); // 96
- case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 103: arg8 = stack.pop() // 54 8
- case 105: stack.push(arg7); // 25 7
- case 107: stack.push(arg4); // 21 4
- case 109: stack.push(arg8); // 21 8
- case 111: stack.push(arg1); // 27
- case 112: if (stack.pop() != stack.pop()) { gt = 119; continue; } // 160 0 7
- case 115: stack.push(arg2); // 28
- case 116: gt = 121; continue; // 167 0 5
- case 119: stack.push(arg8); // 21 8
- case 121: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 122: arg4++; // 132 4 1
- case 125: gt = 89; continue; // 167 255 220
- case 128: stack.push(new java_lang_String); // 187 0 200
- case 131: stack.push(stack[stack.length - 1]); // 89
- case 132: stack.push(0); // 3
- case 133: stack.push(arg3); // 29
- case 134: stack.push(arg7); // 25 7
- case 136: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 139: return stack.pop(); // 176
- case 140: stack.push(arg0); // 42
- case 141: return stack.pop(); // 176
- }
-}
-function java_lang_String_matchesZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: stack.push(arg0); // 42
- case 2: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_matchesZLjava_lang_StringLjava_lang_CharSequence(v0, v1)); } // 184 1 183
- case 5: return stack.pop(); // 172
- }
-}
-function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_String(self, v0)); } // 182 1 149
- case 8: // 2
- case 9: if (stack.pop() >= stack.pop()) { gt = 16; continue; } // 164 0 7
- case 12: stack.push(1); // 4
- case 13: gt = 17; continue; // 167 0 4
- case 16: stack.push(0); // 3
- case 17: return stack.pop(); // 172
- }
-}
-function java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 8: stack.push(arg2); // 44
- case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceFirstLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 182
- case 12: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 8: stack.push(arg2); // 44
- case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181
- case 12: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 4: stack.push(16); // 16 16
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_StringI(v0, v1)); } // 184 1 187
- case 9: stack.push(arg0); // 42
- case 10: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 13: stack.push(arg2); // 44
- case 14: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 17: { var v0 = stack.pop(); stack.push(java_util_regex_Matcher_quoteReplacementLjava_lang_StringLjava_lang_String(v0)); } // 184 1 180
- case 20: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181
- case 23: return stack.pop(); // 176
- }
-}
-function java_lang_String_splitALjava_lang_StringLjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg2); // 28
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_CharSequenceI(self, v0, v1)); } // 182 1 184
- case 9: return stack.pop(); // 176
- }
-}
-function java_lang_String_splitALjava_lang_StringLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_StringI(self, v0, v1)); } // 182 1 157
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(0); // 3
- case 13: arg2 = stack.pop(); // 61
- case 14: stack.push(arg2); // 28
- case 15: stack.push(arg0); // 42
- case 16: stack.push(stack.pop().count); // 180 1 97
- case 19: if (stack.pop() <= stack.pop()) { gt = 94; continue; } // 162 0 75
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: stack.push(arg2); // 28
- case 31: stack.push(stack.pop() + stack.pop()); // 96
- case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 33: arg3 = stack.pop(); // 62
- case 34: stack.push(arg3); // 29
- case 35: stack.push(55296); // 18 1
- case 37: if (stack.pop() > stack.pop()) { gt = 77; continue; } // 161 0 40
- case 40: stack.push(arg3); // 29
- case 41: stack.push(56319); // 18 2
- case 43: if (stack.pop() < stack.pop()) { gt = 77; continue; } // 163 0 34
- case 46: stack.push(arg0); // 42
- case 47: stack.push(arg2); // 28
- case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 51: arg4 = stack.pop() // 54 4
- case 53: stack.push(arg4); // 21 4
- case 55: stack.push(arg4); // 21 4
- case 57: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107
- case 60: if (stack.pop() == stack.pop()) { gt = 66; continue; } // 159 0 6
- case 63: gt = 96; continue; // 167 0 33
- case 66: stack.push(arg2); // 28
- case 67: stack.push(arg4); // 21 4
- case 69: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 72: stack.push(stack.pop() + stack.pop()); // 96
- case 73: arg2 = stack.pop(); // 61
- case 74: gt = 91; continue; // 167 0 17
- case 77: stack.push(arg3); // 29
- case 78: stack.push(arg3); // 29
- case 79: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 82: if (stack.pop() == stack.pop()) { gt = 88; continue; } // 159 0 6
- case 85: gt = 96; continue; // 167 0 11
- case 88: arg2++; // 132 2 1
- case 91: gt = 14; continue; // 167 255 179
- case 94: stack.push(arg0); // 42
- case 95: return stack.pop(); // 176
- case 96: stack.push(arg0); // 42
- case 97: stack.push(stack.pop().count); // 180 1 97
- case 100: stack.push(new Array(stack.pop())); // 188 5
- case 102: arg3 = stack.pop(); // 78
- case 103: stack.push(0); // 3
- case 104: arg4 = stack.pop() // 54 4
- case 106: stack.push(arg0); // 42
- case 107: stack.push(stack.pop().value); // 180 1 100
- case 110: stack.push(arg0); // 42
- case 111: stack.push(stack.pop().offset); // 180 1 99
- case 114: stack.push(arg3); // 45
- case 115: stack.push(0); // 3
- case 116: stack.push(arg2); // 28
- case 117: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 120: stack.push(arg1); // 43
- case 121: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178
- case 124: arg5 = stack.pop() // 58 5
- case 126: stack.push(arg5); // 25 5
- case 128: stack.push("tr"); // 18 11
- case 130: // 165
- case 131: // 0
- case 132: stack.push(6405); // 17 25 5
- case 135: stack.push("az"); // 18 5
- case 137: // 165
- case 138: // 0
- case 139: stack.push(1); // 10
- case 140: stack.push(arg5); // 25 5
- case 142: stack.push("lt"); // 18 9
- case 144: // 166
- case 145: // 0
- case 146: stack.push(4); // 7
- case 147: stack.push(1); // 4
- case 148: gt = 152; continue; // 167 0 4
- case 151: stack.push(0); // 3
- case 152: arg6 = stack.pop() // 54 6
- case 154: stack.push(arg2); // 28
- case 155: arg11 = stack.pop() // 54 11
- case 157: stack.push(arg11); // 21 11
- case 159: stack.push(arg0); // 42
- case 160: stack.push(stack.pop().count); // 180 1 97
- case 163: if (stack.pop() <= stack.pop()) { gt = 419; continue; } // 162 1 0
- case 166: stack.push(arg0); // 42
- case 167: stack.push(stack.pop().value); // 180 1 100
- case 170: stack.push(arg0); // 42
- case 171: stack.push(stack.pop().offset); // 180 1 99
- case 174: stack.push(arg11); // 21 11
- case 176: stack.push(stack.pop() + stack.pop()); // 96
- case 177: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 178: arg9 = stack.pop() // 54 9
- case 180: stack.push(arg9); // 21 9
- case 182: // number conversion // 146
- case 183: stack.push(55296); // 18 1
- case 185: if (stack.pop() > stack.pop()) { gt = 214; continue; } // 161 0 29
- case 188: stack.push(arg9); // 21 9
- case 190: // number conversion // 146
- case 191: stack.push(56319); // 18 2
- case 193: if (stack.pop() < stack.pop()) { gt = 214; continue; } // 163 0 21
- case 196: stack.push(arg0); // 42
- case 197: stack.push(arg11); // 21 11
- case 199: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 202: arg9 = stack.pop() // 54 9
- case 204: stack.push(arg9); // 21 9
- case 206: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 209: arg10 = stack.pop() // 54 10
- case 211: gt = 217; continue; // 167 0 6
- case 214: stack.push(1); // 4
- case 215: arg10 = stack.pop() // 54 10
- case 217: stack.push(arg6); // 21 6
- case 219: if (stack.pop() != 0) { gt = 230; continue; } // 154 0 11
- case 222: stack.push(arg9); // 21 9
- case 224: stack.push(931); // 17 3 163
- case 227: if (stack.pop() != stack.pop()) { gt = 242; continue; } // 160 0 15
- case 230: stack.push(arg0); // 42
- case 231: stack.push(arg11); // 21 11
- case 233: stack.push(arg1); // 43
- case 234: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 117
- case 237: arg8 = stack.pop() // 54 8
- case 239: gt = 249; continue; // 167 0 10
- case 242: stack.push(arg9); // 21 9
- case 244: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107
- case 247: arg8 = stack.pop() // 54 8
- case 249: stack.push(arg8); // 21 8
- case 251: // 2
- case 252: if (stack.pop() == stack.pop()) { gt = 262; continue; } // 159 0 10
- case 255: stack.push(arg8); // 21 8
- case 257: stack.push(65536); // 18 3
- case 259: if (stack.pop() > stack.pop()) { gt = 399; continue; } // 161 0 140
- case 262: stack.push(arg8); // 21 8
- case 264: // 2
- case 265: if (stack.pop() != stack.pop()) { gt = 280; continue; } // 160 0 15
- case 268: stack.push(arg0); // 42
- case 269: stack.push(arg11); // 21 11
- case 271: stack.push(arg1); // 43
- case 272: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 119
- case 275: arg7 = stack.pop() // 58 7
- case 277: gt = 315; continue; // 167 0 38
- case 280: stack.push(arg10); // 21 10
- case 282: stack.push(2); // 5
- case 283: if (stack.pop() != stack.pop()) { gt = 308; continue; } // 160 0 25
- case 286: stack.push(arg4); // 21 4
- case 288: stack.push(arg8); // 21 8
- case 290: stack.push(arg3); // 45
- case 291: stack.push(arg11); // 21 11
- case 293: stack.push(arg4); // 21 4
- case 295: stack.push(stack.pop() + stack.pop()); // 96
- case 296: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111
- case 299: stack.push(arg10); // 21 10
- case 301: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 302: stack.push(stack.pop() + stack.pop()); // 96
- case 303: arg4 = stack.pop() // 54 4
- case 305: gt = 409; continue; // 167 0 104
- case 308: stack.push(arg8); // 21 8
- case 310: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 313: arg7 = stack.pop() // 58 7
- case 315: stack.push(arg7); // 25 7
- case 317: stack.push(stack.pop().length); // 190
- case 318: arg12 = stack.pop() // 54 12
- case 320: stack.push(arg12); // 21 12
- case 322: stack.push(arg10); // 21 10
- case 324: if (stack.pop() >= stack.pop()) { gt = 355; continue; } // 164 0 31
- case 327: stack.push(arg3); // 45
- case 328: stack.push(stack.pop().length); // 190
- case 329: stack.push(arg12); // 21 12
- case 331: stack.push(stack.pop() + stack.pop()); // 96
- case 332: stack.push(arg10); // 21 10
- case 334: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 335: stack.push(new Array(stack.pop())); // 188 5
- case 337: arg13 = stack.pop() // 58 13
- case 339: stack.push(arg3); // 45
- case 340: stack.push(0); // 3
- case 341: stack.push(arg13); // 25 13
- case 343: stack.push(0); // 3
- case 344: stack.push(arg11); // 21 11
- case 346: stack.push(arg4); // 21 4
- case 348: stack.push(stack.pop() + stack.pop()); // 96
- case 349: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 352: stack.push(arg13); // 25 13
- case 354: arg3 = stack.pop(); // 78
- case 355: stack.push(0); // 3
- case 356: arg13 = stack.pop() // 54 13
- case 358: stack.push(arg13); // 21 13
- case 360: stack.push(arg12); // 21 12
- case 362: if (stack.pop() <= stack.pop()) { gt = 386; continue; } // 162 0 24
- case 365: stack.push(arg3); // 45
- case 366: stack.push(arg11); // 21 11
- case 368: stack.push(arg4); // 21 4
- case 370: stack.push(stack.pop() + stack.pop()); // 96
- case 371: stack.push(arg13); // 21 13
- case 373: stack.push(stack.pop() + stack.pop()); // 96
- case 374: stack.push(arg7); // 25 7
- case 376: stack.push(arg13); // 21 13
- case 378: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 379: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 380: arg13++; // 132 13 1
- case 383: gt = 358; continue; // 167 255 231
- case 386: stack.push(arg4); // 21 4
- case 388: stack.push(arg12); // 21 12
- case 390: stack.push(arg10); // 21 10
- case 392: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 393: stack.push(stack.pop() + stack.pop()); // 96
- case 394: arg4 = stack.pop() // 54 4
- case 396: gt = 409; continue; // 167 0 13
- case 399: stack.push(arg3); // 45
- case 400: stack.push(arg11); // 21 11
- case 402: stack.push(arg4); // 21 4
- case 404: stack.push(stack.pop() + stack.pop()); // 96
- case 405: stack.push(arg8); // 21 8
- case 407: // number conversion // 146
- case 408: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 409: stack.push(arg11); // 21 11
- case 411: stack.push(arg10); // 21 10
- case 413: stack.push(stack.pop() + stack.pop()); // 96
- case 414: arg11 = stack.pop() // 54 11
- case 416: gt = 157; continue; // 167 254 253
- case 419: stack.push(new java_lang_String); // 187 0 200
- case 422: stack.push(stack[stack.length - 1]); // 89
- case 423: stack.push(0); // 3
- case 424: stack.push(arg0); // 42
- case 425: stack.push(stack.pop().count); // 180 1 97
- case 428: stack.push(arg4); // 21 4
- case 430: stack.push(stack.pop() + stack.pop()); // 96
- case 431: stack.push(arg3); // 45
- case 432: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 435: return stack.pop(); // 176
- }
-}
-function java_lang_String_toLowerCaseLjava_lang_String(arg0) {
- var arg1;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179
- case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toLowerCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 158
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(0); // 3
- case 13: arg2 = stack.pop(); // 61
- case 14: stack.push(arg2); // 28
- case 15: stack.push(arg0); // 42
- case 16: stack.push(stack.pop().count); // 180 1 97
- case 19: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 74
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: stack.push(arg2); // 28
- case 31: stack.push(stack.pop() + stack.pop()); // 96
- case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 33: arg3 = stack.pop(); // 62
- case 34: stack.push(arg3); // 29
- case 35: stack.push(55296); // 18 1
- case 37: if (stack.pop() > stack.pop()) { gt = 61; continue; } // 161 0 24
- case 40: stack.push(arg3); // 29
- case 41: stack.push(56319); // 18 2
- case 43: if (stack.pop() < stack.pop()) { gt = 61; continue; } // 163 0 18
- case 46: stack.push(arg0); // 42
- case 47: stack.push(arg2); // 28
- case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 51: arg3 = stack.pop(); // 62
- case 52: stack.push(arg3); // 29
- case 53: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 56: arg4 = stack.pop() // 54 4
- case 58: gt = 64; continue; // 167 0 6
- case 61: stack.push(1); // 4
- case 62: arg4 = stack.pop() // 54 4
- case 64: stack.push(arg3); // 29
- case 65: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108
- case 68: arg5 = stack.pop() // 54 5
- case 70: stack.push(arg5); // 21 5
- case 72: // 2
- case 73: if (stack.pop() == stack.pop()) { gt = 95; continue; } // 159 0 22
- case 76: stack.push(arg3); // 29
- case 77: stack.push(arg5); // 21 5
- case 79: if (stack.pop() == stack.pop()) { gt = 85; continue; } // 159 0 6
- case 82: gt = 95; continue; // 167 0 13
- case 85: stack.push(arg2); // 28
- case 86: stack.push(arg4); // 21 4
- case 88: stack.push(stack.pop() + stack.pop()); // 96
- case 89: arg2 = stack.pop(); // 61
- case 90: gt = 14; continue; // 167 255 180
- case 93: stack.push(arg0); // 42
- case 94: return stack.pop(); // 176
- case 95: stack.push(arg0); // 42
- case 96: stack.push(stack.pop().count); // 180 1 97
- case 99: stack.push(new Array(stack.pop())); // 188 5
- case 101: arg3 = stack.pop(); // 78
- case 102: stack.push(0); // 3
- case 103: arg4 = stack.pop() // 54 4
- case 105: stack.push(arg0); // 42
- case 106: stack.push(stack.pop().value); // 180 1 100
- case 109: stack.push(arg0); // 42
- case 110: stack.push(stack.pop().offset); // 180 1 99
- case 113: stack.push(arg3); // 45
- case 114: stack.push(0); // 3
- case 115: stack.push(arg2); // 28
- case 116: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 119: stack.push(arg1); // 43
- case 120: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178
- case 123: arg5 = stack.pop() // 58 5
- case 125: stack.push(arg5); // 25 5
- case 127: stack.push("tr"); // 18 11
- case 129: // 165
- case 130: // 0
- case 131: stack.push(6405); // 17 25 5
- case 134: stack.push("az"); // 18 5
- case 136: // 165
- case 137: // 0
- case 138: stack.push(1); // 10
- case 139: stack.push(arg5); // 25 5
- case 141: stack.push("lt"); // 18 9
- case 143: // 166
- case 144: // 0
- case 145: stack.push(4); // 7
- case 146: stack.push(1); // 4
- case 147: gt = 151; continue; // 167 0 4
- case 150: stack.push(0); // 3
- case 151: arg6 = stack.pop() // 54 6
- case 153: stack.push(arg2); // 28
- case 154: arg11 = stack.pop() // 54 11
- case 156: stack.push(arg11); // 21 11
- case 158: stack.push(arg0); // 42
- case 159: stack.push(stack.pop().count); // 180 1 97
- case 162: if (stack.pop() <= stack.pop()) { gt = 425; continue; } // 162 1 7
- case 165: stack.push(arg0); // 42
- case 166: stack.push(stack.pop().value); // 180 1 100
- case 169: stack.push(arg0); // 42
- case 170: stack.push(stack.pop().offset); // 180 1 99
- case 173: stack.push(arg11); // 21 11
- case 175: stack.push(stack.pop() + stack.pop()); // 96
- case 176: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 177: arg9 = stack.pop() // 54 9
- case 179: stack.push(arg9); // 21 9
- case 181: // number conversion // 146
- case 182: stack.push(55296); // 18 1
- case 184: if (stack.pop() > stack.pop()) { gt = 213; continue; } // 161 0 29
- case 187: stack.push(arg9); // 21 9
- case 189: // number conversion // 146
- case 190: stack.push(56319); // 18 2
- case 192: if (stack.pop() < stack.pop()) { gt = 213; continue; } // 163 0 21
- case 195: stack.push(arg0); // 42
- case 196: stack.push(arg11); // 21 11
- case 198: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 201: arg9 = stack.pop() // 54 9
- case 203: stack.push(arg9); // 21 9
- case 205: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 208: arg10 = stack.pop() // 54 10
- case 210: gt = 216; continue; // 167 0 6
- case 213: stack.push(1); // 4
- case 214: arg10 = stack.pop() // 54 10
- case 216: stack.push(arg6); // 21 6
- case 218: if (stack.pop() == 0) { gt = 233; continue; } // 153 0 15
- case 221: stack.push(arg0); // 42
- case 222: stack.push(arg11); // 21 11
- case 224: stack.push(arg1); // 43
- case 225: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 118
- case 228: arg8 = stack.pop() // 54 8
- case 230: gt = 240; continue; // 167 0 10
- case 233: stack.push(arg9); // 21 9
- case 235: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108
- case 238: arg8 = stack.pop() // 54 8
- case 240: stack.push(arg8); // 21 8
- case 242: // 2
- case 243: if (stack.pop() == stack.pop()) { gt = 253; continue; } // 159 0 10
- case 246: stack.push(arg8); // 21 8
- case 248: stack.push(65536); // 18 3
- case 250: if (stack.pop() > stack.pop()) { gt = 405; continue; } // 161 0 155
- case 253: stack.push(arg8); // 21 8
- case 255: // 2
- case 256: if (stack.pop() != stack.pop()) { gt = 286; continue; } // 160 0 30
- case 259: stack.push(arg6); // 21 6
- case 261: if (stack.pop() == 0) { gt = 276; continue; } // 153 0 15
- case 264: stack.push(arg0); // 42
- case 265: stack.push(arg11); // 21 11
- case 267: stack.push(arg1); // 43
- case 268: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 120
- case 271: arg7 = stack.pop() // 58 7
- case 273: gt = 321; continue; // 167 0 48
- case 276: stack.push(arg9); // 21 9
- case 278: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCharArrayACI(v0)); } // 184 1 110
- case 281: arg7 = stack.pop() // 58 7
- case 283: gt = 321; continue; // 167 0 38
- case 286: stack.push(arg10); // 21 10
- case 288: stack.push(2); // 5
- case 289: if (stack.pop() != stack.pop()) { gt = 314; continue; } // 160 0 25
- case 292: stack.push(arg4); // 21 4
- case 294: stack.push(arg8); // 21 8
- case 296: stack.push(arg3); // 45
- case 297: stack.push(arg11); // 21 11
- case 299: stack.push(arg4); // 21 4
- case 301: stack.push(stack.pop() + stack.pop()); // 96
- case 302: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111
- case 305: stack.push(arg10); // 21 10
- case 307: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 308: stack.push(stack.pop() + stack.pop()); // 96
- case 309: arg4 = stack.pop() // 54 4
- case 311: gt = 415; continue; // 167 0 104
- case 314: stack.push(arg8); // 21 8
- case 316: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 319: arg7 = stack.pop() // 58 7
- case 321: stack.push(arg7); // 25 7
- case 323: stack.push(stack.pop().length); // 190
- case 324: arg12 = stack.pop() // 54 12
- case 326: stack.push(arg12); // 21 12
- case 328: stack.push(arg10); // 21 10
- case 330: if (stack.pop() >= stack.pop()) { gt = 361; continue; } // 164 0 31
- case 333: stack.push(arg3); // 45
- case 334: stack.push(stack.pop().length); // 190
- case 335: stack.push(arg12); // 21 12
- case 337: stack.push(stack.pop() + stack.pop()); // 96
- case 338: stack.push(arg10); // 21 10
- case 340: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 341: stack.push(new Array(stack.pop())); // 188 5
- case 343: arg13 = stack.pop() // 58 13
- case 345: stack.push(arg3); // 45
- case 346: stack.push(0); // 3
- case 347: stack.push(arg13); // 25 13
- case 349: stack.push(0); // 3
- case 350: stack.push(arg11); // 21 11
- case 352: stack.push(arg4); // 21 4
- case 354: stack.push(stack.pop() + stack.pop()); // 96
- case 355: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 358: stack.push(arg13); // 25 13
- case 360: arg3 = stack.pop(); // 78
- case 361: stack.push(0); // 3
- case 362: arg13 = stack.pop() // 54 13
- case 364: stack.push(arg13); // 21 13
- case 366: stack.push(arg12); // 21 12
- case 368: if (stack.pop() <= stack.pop()) { gt = 392; continue; } // 162 0 24
- case 371: stack.push(arg3); // 45
- case 372: stack.push(arg11); // 21 11
- case 374: stack.push(arg4); // 21 4
- case 376: stack.push(stack.pop() + stack.pop()); // 96
- case 377: stack.push(arg13); // 21 13
- case 379: stack.push(stack.pop() + stack.pop()); // 96
- case 380: stack.push(arg7); // 25 7
- case 382: stack.push(arg13); // 21 13
- case 384: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 385: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 386: arg13++; // 132 13 1
- case 389: gt = 364; continue; // 167 255 231
- case 392: stack.push(arg4); // 21 4
- case 394: stack.push(arg12); // 21 12
- case 396: stack.push(arg10); // 21 10
- case 398: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 399: stack.push(stack.pop() + stack.pop()); // 96
- case 400: arg4 = stack.pop() // 54 4
- case 402: gt = 415; continue; // 167 0 13
- case 405: stack.push(arg3); // 45
- case 406: stack.push(arg11); // 21 11
- case 408: stack.push(arg4); // 21 4
- case 410: stack.push(stack.pop() + stack.pop()); // 96
- case 411: stack.push(arg8); // 21 8
- case 413: // number conversion // 146
- case 414: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 415: stack.push(arg11); // 21 11
- case 417: stack.push(arg10); // 21 10
- case 419: stack.push(stack.pop() + stack.pop()); // 96
- case 420: arg11 = stack.pop() // 54 11
- case 422: gt = 156; continue; // 167 254 246
- case 425: stack.push(new java_lang_String); // 187 0 200
- case 428: stack.push(stack[stack.length - 1]); // 89
- case 429: stack.push(0); // 3
- case 430: stack.push(arg0); // 42
- case 431: stack.push(stack.pop().count); // 180 1 97
- case 434: stack.push(arg4); // 21 4
- case 436: stack.push(stack.pop() + stack.pop()); // 96
- case 437: stack.push(arg3); // 45
- case 438: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 441: return stack.pop(); // 176
- }
-}
-function java_lang_String_toUpperCaseLjava_lang_String(arg0) {
- var arg1;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179
- case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toUpperCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 159
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_trimLjava_lang_String(arg0) {
- var arg1;
- var arg2;
- var arg3;
- var arg4;
- var arg5;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: arg1 = stack.pop(); // 60
- case 5: stack.push(0); // 3
- case 6: arg2 = stack.pop(); // 61
- case 7: stack.push(arg0); // 42
- case 8: stack.push(stack.pop().offset); // 180 1 99
- case 11: arg3 = stack.pop(); // 62
- case 12: stack.push(arg0); // 42
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: arg4 = stack.pop() // 58 4
- case 18: stack.push(arg2); // 28
- case 19: stack.push(arg1); // 27
- case 20: if (stack.pop() <= stack.pop()) { gt = 40; continue; } // 162 0 20
- case 23: stack.push(arg4); // 25 4
- case 25: stack.push(arg3); // 29
- case 26: stack.push(arg2); // 28
- case 27: stack.push(stack.pop() + stack.pop()); // 96
- case 28: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 29: stack.push(32); // 16 32
- case 31: if (stack.pop() < stack.pop()) { gt = 40; continue; } // 163 0 9
- case 34: arg2++; // 132 2 1
- case 37: gt = 18; continue; // 167 255 237
- case 40: stack.push(arg2); // 28
- case 41: stack.push(arg1); // 27
- case 42: if (stack.pop() <= stack.pop()) { gt = 64; continue; } // 162 0 22
- case 45: stack.push(arg4); // 25 4
- case 47: stack.push(arg3); // 29
- case 48: stack.push(arg1); // 27
- case 49: stack.push(stack.pop() + stack.pop()); // 96
- case 50: stack.push(1); // 4
- case 51: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 53: stack.push(32); // 16 32
- case 55: if (stack.pop() < stack.pop()) { gt = 64; continue; } // 163 0 9
- case 58: arg1 += 255; // 132 1 255
- case 61: gt = 40; continue; // 167 255 235
- case 64: stack.push(arg2); // 28
- case 65: if (stack.pop() > 0) { gt = 76; continue; } // 157 0 11
- case 68: stack.push(arg1); // 27
- case 69: stack.push(arg0); // 42
- case 70: stack.push(stack.pop().count); // 180 1 97
- case 73: if (stack.pop() <= stack.pop()) { gt = 85; continue; } // 162 0 12
- case 76: stack.push(arg0); // 42
- case 77: stack.push(arg2); // 28
- case 78: stack.push(arg1); // 27
- case 79: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 82: gt = 86; continue; // 167 0 4
- case 85: stack.push(arg0); // 42
- case 86: return stack.pop(); // 176
- }
-}
-*/
-function java_lang_String_toStringLjava_lang_String(arg0) {
- return arg0.toString();
-}
-/*
-function java_lang_String_toCharArrayAC(arg0) {
- var arg1;
- var arg2;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: stack.push(new Array(stack.pop())); // 188 5
- case 6: arg1 = stack.pop(); // 76
- case 7: stack.push(arg0); // 42
- case 8: stack.push(0); // 3
- case 9: stack.push(arg0); // 42
- case 10: stack.push(stack.pop().count); // 180 1 97
- case 13: stack.push(arg1); // 43
- case 14: stack.push(0); // 3
- case 15: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 18: stack.push(arg1); // 43
- case 19: return stack.pop(); // 176
- }
-}
-function java_lang_String_formatLjava_lang_StringLjava_lang_StringLjava_lang_Object(arg0,arg1) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_util_Formatter); // 187 0 211
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: { java_util_Formatter_consV(stack.pop()); } // 183 1 174
- case 7: stack.push(arg0); // 42
- case 8: stack.push(arg1); // 43
- case 9: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177
- case 12: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175
- case 15: return stack.pop(); // 176
- }
-}
-function java_lang_String_formatLjava_lang_StringLjava_util_LocaleLjava_lang_StringLjava_lang_Object(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_util_Formatter); // 187 0 211
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); java_util_Formatter_consVLjava_util_Locale(stack.pop(), v0); } // 183 1 176
- case 8: stack.push(arg1); // 43
- case 9: stack.push(arg2); // 44
- case 10: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177
- case 13: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175
- case 16: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringLjava_lang_Object(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: if (stack.pop()) { gt = 9; continue; } // 199 0 8
- case 4: stack.push("null"); // 18 10
- case 6: gt = 13; continue; // 167 0 7
- case 9: stack.push(arg0); // 42
- case 10: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 13: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringAC(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); java_lang_String_consVAC(stack.pop(), v0); } // 183 1 142
- case 8: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringACII(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 27
- case 6: stack.push(arg2); // 28
- case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143
- case 10: return stack.pop(); // 176
- }
-}
-function java_lang_String_copyValueOfLjava_lang_StringACII(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 27
- case 6: stack.push(arg2); // 28
- case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143
- case 10: return stack.pop(); // 176
- }
-}
-function java_lang_String_copyValueOfLjava_lang_StringAC(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(0); // 3
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().length); // 190
- case 4: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_copyValueOfALjava_lang_StringACAIAI(v0, v1, v2)); } // 184 1 155
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringZ(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 26
- case 1: if (stack.pop() == 0) { gt = 9; continue; } // 153 0 8
- case 4: stack.push("true"); // 18 12
- case 6: gt = 11; continue; // 167 0 5
- case 9: stack.push("false"); // 18 8
- case 11: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringC(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(1); // 4
- case 1: stack.push(new Array(stack.pop())); // 188 5
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(0); // 3
- case 5: stack.push(arg0); // 26
- case 6: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 7: arg1 = stack.pop(); // 76
- case 8: stack.push(new java_lang_String); // 187 0 200
- case 11: stack.push(stack[stack.length - 1]); // 89
- case 12: stack.push(0); // 3
- case 13: stack.push(1); // 4
- case 14: stack.push(arg1); // 43
- case 15: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 18: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringI(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 26
- case 1: stack.push(10); // 16 10
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Integer_toStringLjava_lang_StringII(v0, v1)); } // 184 1 125
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringJ(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 30
- case 1: stack.push(10); // 16 10
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Long_toStringLjava_lang_StringJI(v0, v1)); } // 184 1 126
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringF(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 34
- case 1: { var v0 = stack.pop(); stack.push(java_lang_Float_toStringLjava_lang_StringF(v0)); } // 184 1 122
- case 4: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringD(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 38
- case 1: { var v0 = stack.pop(); stack.push(java_lang_Double_toStringLjava_lang_StringD(v0)); } // 184 1 121
- case 4: return stack.pop(); // 176
- }
-}
-function java_lang_String_internLjava_lang_String(arg0) {
- // no code found for null
-}
-function java_lang_String_compareToILjava_lang_Object(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareToILjava_lang_String(self, v0)); } // 182 1 148
- case 8: return stack.pop(); // 172
- }
-}
-function java_lang_String_classV() {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(0); // 3
- case 1: stack.push(new Array(stack.pop())); // 189 0 183
- case 4: java_lang_String_serialPersistentFields = stack.pop(); // 179 1 101
- case 7: stack.push(new java_lang_String$CaseInsensitiveComparator); // 187 0 202
- case 10: stack.push(stack[stack.length - 1]); // 89
- case 11: // 1
- case 12: { var v0 = stack.pop(); java_lang_String$CaseInsensitiveComparator_consVLjava_lang_String$1(stack.pop(), v0); } // 183 1 160
- case 15: java_lang_String_CASE_INSENSITIVE_ORDER = stack.pop(); // 179 1 102
- case 18: return; // 177
- }
-}
-*/
-var java_lang_String_serialVersionUID = 0;
-var java_lang_String_serialPersistentFields = 0;
-var java_lang_String_CASE_INSENSITIVE_ORDER = 0;
-function java_lang_String() {
- /** the real value of this 'string' we delegate to */
- this.r = '';
-
- var self = this;
- /*
- this.value = 0;
- this.offset = 0;
- this.count = 0;
- this.hash = 0;
- */
- this.toString = function() { return self.r; };
-}
-java_lang_String.prototype = new String;
-//java_lang_String_classV();
-
-/* new method for JavaScript String */
-String.prototype.charAtCI = java_lang_String_charAtCI;
-String.prototype.lengthI = java_lang_String_lengthI;
-String.prototype.isEmptyZ = java_lang_String_isEmptyZ;
-String.prototype.getCharsVIIACI = java_lang_String_getCharsVIIACAI;
-String.prototype.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
-String.prototype.$instOf_java_lang_String = true;
-String.prototype.$instOf_java_io_Serializable = true;
-String.prototype.$instOf_java_lang_Comparable = true;
-String.prototype.$instOf_java_lang_CharSequence = true;
-
-/*
- this.lengthI = java_lang_String_lengthI;
- this.isEmptyZ = java_lang_String_isEmptyZ;
- this.charAtCI = java_lang_String_charAtCI;
- this.codePointAtII = java_lang_String_codePointAtII;
- this.codePointBeforeII = java_lang_String_codePointBeforeII;
- this.codePointCountIII = java_lang_String_codePointCountIII;
- this.offsetByCodePointsIII = java_lang_String_offsetByCodePointsIII;
- this.getCharsVACI = java_lang_String_getCharsVACI;
- this.getCharsVIIACI = java_lang_String_getCharsVIIACI;
- this.getBytesVIIABI = java_lang_String_getBytesVIIABI;
- this.getBytesABLjava_lang_String = java_lang_String_getBytesABLjava_lang_String;
- this.getBytesABLjava_nio_charset_Charset = java_lang_String_getBytesABLjava_nio_charset_Charset;
- this.getBytesAB = java_lang_String_getBytesAB;
- this.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object;
- this.contentEqualsZLjava_lang_StringBuffer = java_lang_String_contentEqualsZLjava_lang_StringBuffer;
- this.contentEqualsZLjava_lang_CharSequence = java_lang_String_contentEqualsZLjava_lang_CharSequence;
- this.equalsIgnoreCaseZLjava_lang_String = java_lang_String_equalsIgnoreCaseZLjava_lang_String;
- this.compareToILjava_lang_String = java_lang_String_compareToILjava_lang_String;
- this.compareToIgnoreCaseILjava_lang_String = java_lang_String_compareToIgnoreCaseILjava_lang_String;
- this.regionMatchesZILjava_lang_StringII = java_lang_String_regionMatchesZILjava_lang_StringII;
- this.regionMatchesZZILjava_lang_StringII = java_lang_String_regionMatchesZZILjava_lang_StringII;
- this.startsWithZLjava_lang_StringI = java_lang_String_startsWithZLjava_lang_StringI;
- this.startsWithZLjava_lang_String = java_lang_String_startsWithZLjava_lang_String;
- this.endsWithZLjava_lang_String = java_lang_String_endsWithZLjava_lang_String;
- this.hashCodeI = java_lang_String_hashCodeI;
- this.indexOfII = java_lang_String_indexOfII;
- this.indexOfIII = java_lang_String_indexOfIII;
- this.lastIndexOfII = java_lang_String_lastIndexOfII;
- this.lastIndexOfIII = java_lang_String_lastIndexOfIII;
- this.indexOfILjava_lang_String = java_lang_String_indexOfILjava_lang_String;
- this.indexOfILjava_lang_StringI = java_lang_String_indexOfILjava_lang_StringI;
- this.lastIndexOfILjava_lang_String = java_lang_String_lastIndexOfILjava_lang_String;
- this.lastIndexOfILjava_lang_StringI = java_lang_String_lastIndexOfILjava_lang_StringI;
- this.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI;
- this.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII;
- this.subSequenceLjava_lang_CharSequenceII = java_lang_String_subSequenceLjava_lang_CharSequenceII;
- this.concatLjava_lang_StringLjava_lang_String = java_lang_String_concatLjava_lang_StringLjava_lang_String;
- this.replaceLjava_lang_StringCC = java_lang_String_replaceLjava_lang_StringCC;
- this.matchesZLjava_lang_String = java_lang_String_matchesZLjava_lang_String;
- this.containsZLjava_lang_CharSequence = java_lang_String_containsZLjava_lang_CharSequence;
- this.replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String;
- this.replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String;
- this.replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence = java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence;
- this.splitALjava_lang_StringLjava_lang_StringI = java_lang_String_splitALjava_lang_StringLjava_lang_StringI;
- this.splitALjava_lang_StringLjava_lang_String = java_lang_String_splitALjava_lang_StringLjava_lang_String;
- this.toLowerCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale;
- this.toLowerCaseLjava_lang_String = java_lang_String_toLowerCaseLjava_lang_String;
- this.toUpperCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale;
- this.toUpperCaseLjava_lang_String = java_lang_String_toUpperCaseLjava_lang_String;
- this.trimLjava_lang_String = java_lang_String_trimLjava_lang_String;
- this.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
- this.toCharArrayAC = java_lang_String_toCharArrayAC;
- this.internLjava_lang_String = java_lang_String_internLjava_lang_String;
- this.compareToILjava_lang_Object = java_lang_String_compareToILjava_lang_Object;
- */
-
-
-
+ return ret;
+};
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/pom.xml
--- a/htmlpage/pom.xml Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-
-
- 4.0.0
-
- org.apidesign
- bck2brwsr
- 1.0-SNAPSHOT
-
- org.apidesign
- htmlpage
- 1.0-SNAPSHOT
- htmlpage
- http://maven.apache.org
-
- UTF-8
-
-
-
- org.testng
- testng
- test
-
-
- junit
- junit
-
-
-
-
- org.netbeans.api
- org-openide-util-lookup
-
-
- org.apidesign.bck2brwsr
- core
- 1.0-SNAPSHOT
- jar
-
-
- org.apidesign.bck2brwsr
- emul
- 1.0-SNAPSHOT
- jar
-
-
- org.apidesign.bck2brwsr
- vm4brwsr
- 0.1-SNAPSHOT
- jar
- test
-
-
-
-
-
- com.mycila.maven-license-plugin
- maven-license-plugin
- 1.9.0
-
- ../vm/src/header.txt
-
-
-
-
-
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Locale;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
-import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
-import org.apidesign.bck2brwsr.htmlpage.api.Page;
-import org.openide.util.lookup.ServiceProvider;
-
-/** Annotation processor to process an XHTML page and generate appropriate
- * "id" file.
- *
- * @author Jaroslav Tulach
- */
-@ServiceProvider(service=Processor.class)
-@SupportedAnnotationTypes({
- "org.apidesign.bck2brwsr.htmlpage.api.Page",
- "org.apidesign.bck2brwsr.htmlpage.api.OnClick"
-})
-public final class PageProcessor extends AbstractProcessor {
- @Override
- public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
- for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
- Page p = e.getAnnotation(Page.class);
- PackageElement pe = (PackageElement)e.getEnclosingElement();
- String pkg = pe.getQualifiedName().toString();
-
- ProcessPage pp;
- try {
- InputStream is = openStream(pkg, p.xhtml());
- pp = ProcessPage.readPage(is);
- is.close();
- } catch (IOException iOException) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
- return false;
- }
- Writer w;
- try {
- FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + p.name(), e);
- w = new OutputStreamWriter(java.openOutputStream());
- try {
- w.append("package " + pkg + ";\n");
- w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
- w.append("class ").append(p.name()).append(" {\n");
- for (String id : pp.ids()) {
- String tag = pp.tagNameForId(id);
- String type = type(tag);
- w.append(" ").append("public static final ").
- append(type).append(' ').append(cnstnt(id)).append(" = new ").
- append(type).append("(\"").append(id).append("\");\n");
- }
- w.append(" static {\n");
- if (!initializeOnClick(pe, w, pp)) {
- return false;
- }
- w.append(" }\n");
- w.append("}\n");
- } finally {
- w.close();
- }
- } catch (IOException ex) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + p.name() + ".java", e);
- return false;
- }
- }
- return true;
- }
-
- private InputStream openStream(String pkg, String name) throws IOException {
- FileObject fo = processingEnv.getFiler().getResource(
- StandardLocation.SOURCE_PATH, pkg, name);
- try {
- return fo.openInputStream();
- } catch (IOException ex) {
- return processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, name).openInputStream();
- }
- }
-
- private static String type(String tag) {
- if (tag.equals("title")) {
- return "Title";
- }
- if (tag.equals("button")) {
- return "Button";
- }
- if (tag.equals("input")) {
- return "Input";
- }
- return "Element";
- }
-
- private static String cnstnt(String id) {
- return id.toUpperCase(Locale.ENGLISH).replace('.', '_');
- }
-
- private boolean initializeOnClick(PackageElement pe, Writer w, ProcessPage pp) throws IOException {
- for (Element clazz : pe.getEnclosedElements()) {
- if (clazz.getKind() != ElementKind.CLASS) {
- continue;
- }
- TypeElement type = (TypeElement)clazz;
- for (Element method : clazz.getEnclosedElements()) {
- OnClick oc = method.getAnnotation(OnClick.class);
- if (oc != null) {
- if (pp.tagNameForId(oc.id()) == null) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + oc.id() + " does not exist in the HTML page. Found only " + pp.ids(), method);
- return false;
- }
- ExecutableElement ee = (ExecutableElement)method;
- if (!ee.getParameters().isEmpty()) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't take arguments", ee);
- return false;
- }
- if (!ee.getModifiers().contains(Modifier.STATIC)) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method has to be static", ee);
- return false;
- }
- if (ee.getModifiers().contains(Modifier.PRIVATE)) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't be private", ee);
- return false;
- }
- w.append(" ").append(cnstnt(oc.id())).
- append(".addOnClick(new Runnable() { public void run() {\n");
- w.append(" ").append(type.getSimpleName().toString()).
- append('.').append(ee.getSimpleName()).append("();\n");
- w.append(" }});\n");
- }
- }
- }
- return true;
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-class ProcessPage {
- private final Map ids2Elems = new TreeMap();
-
- public Set ids() {
- return Collections.unmodifiableSet(ids2Elems.keySet());
- }
-
- public String tagNameForId(String id) {
- return ids2Elems.get(id);
- }
-
- public static ProcessPage readPage(InputStream is) throws IOException {
- DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
- f.setValidating(false);
- f.setIgnoringComments(true);
-
- Document doc = null;
- try {
- DocumentBuilder b = f.newDocumentBuilder();
- doc = b.parse(is);
- } catch (IOException ex) {
- throw ex;
- } catch (Exception e) {
- throw new IOException(e);
- }
- Element root = doc.getDocumentElement();
-
- ProcessPage pp = new ProcessPage();
- pp.seekForIds(root);
- return pp;
- }
-
- private void seekForIds(Element e) {
- String val = e.getAttribute("id");
- if (val != null && !val.isEmpty()) {
- String prev = ids2Elems.put(val, e.getTagName());
- }
- NodeList arr = e.getChildNodes();
- for (int i = 0; i < arr.getLength(); i++) {
- final Node n = arr.item(i);
- if (n instanceof Element) {
- seekForIds((Element)n);
- }
- }
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-/**
- *
- * @author Jaroslav Tulach
- */
-public final class Button extends Element {
- public Button(String id) {
- super(id);
- }
-
- @Override
- void dontSubclass() {
- }
-
- public void setDisabled(boolean state) {
- setAttribute(this, "disabled", state);
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-import org.apidesign.bck2brwsr.core.JavaScriptBody;
-
-/** Represents a generic HTML element.
- *
- * @author Jaroslav Tulach
- */
-public abstract class Element {
- private final String id;
-
- public Element(String id) {
- this.id = id;
- }
-
- abstract void dontSubclass();
-
- @JavaScriptBody(
- args={"el", "property", "value"},
- body="var e = window.document.getElementById(el.id);\n"
- + "e[property] = value;\n"
- )
- static void setAttribute(Element el, String property, Object value) {
- throw new UnsupportedOperationException("Needs JavaScript!");
- }
-
- @JavaScriptBody(
- args={"el", "property"},
- body="var e = window.document.getElementById(el.id);\n"
- + "return e[property];\n"
- )
- static Object getAttribute(Element el, String property) {
- throw new UnsupportedOperationException("Needs JavaScript!");
- }
-
- /** Executes given runnable when user performs a "click" on the given
- * element.
- * @param r the runnable to execute, never null
- */
- @JavaScriptBody(
- args={"el", "r"},
- body="var e = window.document.getElementById(el.id);\n"
- + "e.onclick = function() { r.runV(); };\n"
- )
- public final void addOnClick(Runnable r) {
- throw new UnsupportedOperationException("Needs JavaScript!");
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-/**
- *
- * @author Jaroslav Tulach
- */
-public final class Input extends Element {
- public Input(String id) {
- super(id);
- }
-
- @Override
- void dontSubclass() {
- }
-
- public void setAutocomplete(boolean state) {
- Element.setAttribute(this, "autocomplete", state);
- }
-
- public final String getValue() {
- return (String)Element.getAttribute(this, "value");
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/** Adds an onClick handler to an element identified by given id.
- * Apply on a public static void method with no arguments.
- *
- * @author Jaroslav Tulach
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target(ElementType.METHOD)
-public @interface OnClick {
- String id();
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/** Converts an XHTML page into a Java class that contains
- * references to all IDs.
- *
- * @author Jaroslav Tulach
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target(ElementType.TYPE)
-public @interface Page {
- /** Path to the XHTML page to read in */
- String xhtml();
- /** Name of a Java class to generate. It will contain constants for all
- * found elements with IDs.
- */
- String name();
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java
--- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage.api;
-
-/**
- *
- * @author Jaroslav Tulach
- */
-public class Title extends Element {
- public Title(String id) {
- super(id);
- }
-
- @Override
- void dontSubclass() {
- }
-
- public final void setText(String text) {
- Element.setAttribute(this, "innerHTML", text);
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java
--- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-package org.apidesign.bck2brwsr.htmlpage;
-
-import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
-import org.apidesign.bck2brwsr.htmlpage.api.Page;
-
-/** Trivial demo for the bck2brwsr project. First of all start
- * with your XHTML page. Include there
- * a script that will boot Java in your browser.
- *
- * Then use @Page annotation to
- * generate a Java representation of elements with IDs in that page.
- * Depending on the type of the elements, they will have different
- * methods (e.g. PG_TITLE has setText, etc.).
- * Use @OnClick annotation to associate behavior
- * with existing elements. Use the generated elements
- * (PG_TITLE, PG_TEXT) to modify the page.
- *
- * Everything is type-safe. As soon as somebody modifies the page and
- * removes the IDs or re-assigns them to wrong elements. Java compiler
- * will emit an error.
- *
- * Welcome to the type-safe HTML5 world!
- *
- * @author Jaroslav Tulach
- */
-@Page(xhtml="TestPage.html", name="TestPage")
-public class PageController {
- @OnClick(id="pg.button")
- static void updateTitle() {
- TestPage.PG_TITLE.setText(TestPage.PG_TEXT.getValue());
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java
--- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. Look for COPYING file in the top folder.
- * If not, see http://opensource.org/licenses/GPL-2.0.
- */
-package org.apidesign.bck2brwsr.htmlpage;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.util.Set;
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-public class ProcessPageTest {
-
-
- @Test public void findsThreeIds() throws IOException {
- InputStream is = ProcessPageTest.class.getResourceAsStream("TestPage.html");
- assertNotNull(is, "Sample HTML page found");
- ProcessPage res = ProcessPage.readPage(is);
- final Set ids = res.ids();
- assertEquals(ids.size(), 3, "Three ids found: " + ids);
-
- assertEquals(res.tagNameForId("pg.title"), "title");
- assertEquals(res.tagNameForId("pg.button"), "button");
- assertEquals(res.tagNameForId("pg.text"), "input");
- }
-
- @Test public void testCompileAndRunPageController() throws Exception {
- StringBuilder sb = new StringBuilder();
- sb.append(
- "var window = new Object();\n"
- + "var doc = new Object();\n"
- + "doc.button = new Object();\n"
- + "doc.title = new Object();\n"
- + "doc.title.innerHTML = 'nothing';\n"
- + "doc.text = new Object();\n"
- + "doc.text.value = 'something';\n"
- + "doc.getElementById = function(id) {\n"
- + " switch(id) {\n"
- + " case 'pg.button': return doc.button;\n"
- + " case 'pg.title': return doc.title;\n"
- + " case 'pg.text': return doc.text;\n"
- + " }\n"
- + " throw id;\n"
- + " }\n"
- + "\n"
- + "function clickAndCheck() {\n"
- + " doc.button.onclick();\n"
- + " return doc.title.innerHTML.toString();\n"
- + "};\n"
- + "\n"
- + "window.document = doc;\n"
- );
- Invocable i = compileClass(sb, "org/apidesign/bck2brwsr/htmlpage/PageController");
-
- Object ret = null;
- try {
- ret = i.invokeFunction("clickAndCheck");
- } catch (ScriptException ex) {
- fail("Execution failed in " + sb, ex);
- } catch (NoSuchMethodException ex) {
- fail("Cannot find method in " + sb, ex);
- }
- assertEquals(ret, "something", "We expect that the JavaCode performs all the wiring");
- }
-
- static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
- if (sb == null) {
- sb = new StringBuilder();
- }
- try {
- Method m;
- Class> genJS = Class.forName("org.apidesign.vm4brwsr.GenJS");
- m = genJS.getDeclaredMethod("compile", Appendable.class, String[].class);
- m.setAccessible(true);
- m.invoke(null, sb, names);
- } catch (Exception exception) {
- throw new IOException(exception);
- }
- ScriptEngineManager sem = new ScriptEngineManager();
- ScriptEngine js = sem.getEngineByExtension("js");
- try {
- Object res = js.eval(sb.toString());
- assertTrue(js instanceof Invocable, "It is invocable object: " + res);
- return (Invocable) js;
- } catch (ScriptException ex) {
- fail("Could not compile:\n" + sb, ex);
- return null;
- }
- }
-}
diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html
--- a/htmlpage/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-
-
-
-
-
- Default Title
-
-
- New title:
-
-
-
diff -r 029e6eed60e9 -r 388e48c0a37a javap/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+ org.apidesign
+ bck2brwsr
+ 0.3-SNAPSHOT
+
+ org.apidesign.bck2brwsr
+ javap
+ 0.3-SNAPSHOT
+ javap
+ http://maven.apache.org
+
+ UTF-8
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.5.1
+
+
+
+
+
+ 1.6
+
+
+
+
+
+
+ org.apidesign.bck2brwsr
+ emul
+ 0.3-SNAPSHOT
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/AnnotationParser.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.apidesign.javap;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/** An abstract parser for annotation definitions. Analyses the bytes and
+ * performs some callbacks to the overriden parser methods.
+ *
+ * @author Jaroslav Tulach
+ */
+public class AnnotationParser {
+ private final boolean textual;
+
+ protected AnnotationParser(boolean textual) {
+ this.textual = textual;
+ }
+
+ protected void visitAnnotationStart(String type) throws IOException {
+ }
+
+ protected void visitAnnotationEnd(String type) throws IOException {
+ }
+
+ protected void visitAttr(
+ String annoType, String attr, String attrType, String value
+ ) throws IOException {
+ }
+
+ /** Initialize the parsing with constant pool from cd.
+ *
+ * @param attr the attribute defining annotations
+ * @param cd constant pool
+ * @throws IOException in case I/O fails
+ */
+ public final void parse(byte[] attr, ClassData cd) throws IOException {
+ ByteArrayInputStream is = new ByteArrayInputStream(attr);
+ DataInputStream dis = new DataInputStream(is);
+ try {
+ read(dis, cd);
+ } finally {
+ is.close();
+ }
+ }
+
+ private void read(DataInputStream dis, ClassData cd) throws IOException {
+ int cnt = dis.readUnsignedShort();
+ for (int i = 0; i < cnt; i++) {
+ readAnno(dis, cd);
+ }
+ }
+
+ private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
+ int type = dis.readUnsignedShort();
+ String typeName = cd.StringValue(type);
+ visitAnnotationStart(typeName);
+ int cnt = dis.readUnsignedShort();
+ for (int i = 0; i < cnt; i++) {
+ String attrName = cd.StringValue(dis.readUnsignedShort());
+ readValue(dis, cd, typeName, attrName);
+ }
+ visitAnnotationEnd(typeName);
+ if (cnt == 0) {
+ visitAttr(typeName, null, null, null);
+ }
+ }
+
+ private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName)
+ throws IOException {
+ char type = (char)dis.readByte();
+ if (type == '@') {
+ readAnno(dis, cd);
+ } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
+ int primitive = dis.readUnsignedShort();
+ String val = cd.stringValue(primitive, textual);
+ String attrType;
+ if (type == 's') {
+ attrType = "Ljava_lang_String_2";
+ if (textual) {
+ val = '"' + val + '"';
+ }
+ } else {
+ attrType = "" + type;
+ }
+ visitAttr(typeName, attrName, attrType, val);
+ } else if (type == 'c') {
+ int cls = dis.readUnsignedShort();
+ } else if (type == '[') {
+ int cnt = dis.readUnsignedShort();
+ for (int i = 0; i < cnt; i++) {
+ readValue(dis, cd, typeName, attrName);
+ }
+ } else if (type == 'e') {
+ int enumT = dis.readUnsignedShort();
+ int enumN = dis.readUnsignedShort();
+ } else {
+ throw new IOException("Unknown type " + type);
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/AttrData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/AttrData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+
+/**
+ * Reads and stores attribute information.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class AttrData {
+ ClassData cls;
+ int name_cpx;
+ int datalen;
+ byte data[];
+
+ public AttrData (ClassData cls) {
+ this.cls=cls;
+ }
+
+ /**
+ * Reads unknown attribute.
+ */
+ public void read(int name_cpx, DataInputStream in) throws IOException {
+ this.name_cpx=name_cpx;
+ datalen=in.readInt();
+ data=new byte[datalen];
+ in.readFully(data);
+ }
+
+ /**
+ * Reads just the name of known attribute.
+ */
+ public void read(int name_cpx){
+ this.name_cpx=name_cpx;
+ }
+
+ /**
+ * Returns attribute name.
+ */
+ public String getAttrName(){
+ return cls.getString(name_cpx);
+ }
+
+ /**
+ * Returns attribute data.
+ */
+ public byte[] getData(){
+ return data;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/CPX.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/CPX.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+/**
+ * Stores constant pool entry information with one field.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class CPX {
+ int cpx;
+
+ CPX (int cpx) {
+ this.cpx=cpx;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/CPX2.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/CPX2.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+/**
+ * Stores constant pool entry information with two fields.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class CPX2 {
+ int cpx1,cpx2;
+
+ CPX2 (int cpx1, int cpx2) {
+ this.cpx1=cpx1;
+ this.cpx2=cpx2;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/ClassData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+
+/**
+ * Central data repository of the Java Disassembler.
+ * Stores all the information in java class file.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+public final class ClassData implements RuntimeConstants {
+
+ private int magic;
+ private int minor_version;
+ private int major_version;
+ private int cpool_count;
+ private Object cpool[];
+ private int access;
+ private int this_class = 0;;
+ private int super_class;
+ private int interfaces_count;
+ private int[] interfaces = new int[0];;
+ private int fields_count;
+ private FieldData[] fields;
+ private int methods_count;
+ private MethodData[] methods;
+ private InnerClassData[] innerClasses;
+ private int attributes_count;
+ private AttrData[] attrs;
+ private String classname;
+ private String superclassname;
+ private int source_cpx=0;
+ private byte tags[];
+ private Hashtable indexHashAscii = new Hashtable();
+ private String pkgPrefix="";
+ private int pkgPrefixLen=0;
+
+ /**
+ * Read classfile to disassemble.
+ */
+ public ClassData(InputStream infile) throws IOException {
+ this.read(new DataInputStream(infile));
+ }
+
+ /**
+ * Reads and stores class file information.
+ */
+ public void read(DataInputStream in) throws IOException {
+ // Read the header
+ magic = in.readInt();
+ if (magic != JAVA_MAGIC) {
+ throw new ClassFormatError("wrong magic: " +
+ toHex(magic) + ", expected " +
+ toHex(JAVA_MAGIC));
+ }
+ minor_version = in.readShort();
+ major_version = in.readShort();
+ if (major_version != JAVA_VERSION) {
+ }
+
+ // Read the constant pool
+ readCP(in);
+ access = in.readUnsignedShort();
+ this_class = in.readUnsignedShort();
+ super_class = in.readUnsignedShort();
+
+ //Read interfaces.
+ interfaces_count = in.readUnsignedShort();
+ if(interfaces_count > 0){
+ interfaces = new int[interfaces_count];
+ }
+ for (int i = 0; i < interfaces_count; i++) {
+ interfaces[i]=in.readShort();
+ }
+
+ // Read the fields
+ readFields(in);
+
+ // Read the methods
+ readMethods(in);
+
+ // Read the attributes
+ attributes_count = in.readUnsignedShort();
+ attrs=new AttrData[attributes_count];
+ for (int k = 0; k < attributes_count; k++) {
+ int name_cpx=in.readUnsignedShort();
+ if (getTag(name_cpx)==CONSTANT_UTF8
+ && getString(name_cpx).equals("SourceFile")
+ ){ if (in.readInt()!=2)
+ throw new ClassFormatError("invalid attr length");
+ source_cpx=in.readUnsignedShort();
+ AttrData attr=new AttrData(this);
+ attr.read(name_cpx);
+ attrs[k]=attr;
+
+ } else if (getTag(name_cpx)==CONSTANT_UTF8
+ && getString(name_cpx).equals("InnerClasses")
+ ){ int length=in.readInt();
+ int num=in.readUnsignedShort();
+ if (2+num*8 != length)
+ throw new ClassFormatError("invalid attr length");
+ innerClasses=new InnerClassData[num];
+ for (int j = 0; j < num; j++) {
+ InnerClassData innerClass=new InnerClassData(this);
+ innerClass.read(in);
+ innerClasses[j]=innerClass;
+ }
+ AttrData attr=new AttrData(this);
+ attr.read(name_cpx);
+ attrs[k]=attr;
+ } else {
+ AttrData attr=new AttrData(this);
+ attr.read(name_cpx, in);
+ attrs[k]=attr;
+ }
+ }
+ in.close();
+ } // end ClassData.read()
+
+ /**
+ * Reads and stores constant pool info.
+ */
+ void readCP(DataInputStream in) throws IOException {
+ cpool_count = in.readUnsignedShort();
+ tags = new byte[cpool_count];
+ cpool = new Object[cpool_count];
+ for (int i = 1; i < cpool_count; i++) {
+ byte tag = in.readByte();
+
+ switch(tags[i] = tag) {
+ case CONSTANT_UTF8:
+ String str=in.readUTF();
+ indexHashAscii.put(cpool[i] = str, new Integer(i));
+ break;
+ case CONSTANT_INTEGER:
+ cpool[i] = new Integer(in.readInt());
+ break;
+ case CONSTANT_FLOAT:
+ cpool[i] = new Float(in.readFloat());
+ break;
+ case CONSTANT_LONG:
+ cpool[i++] = new Long(in.readLong());
+ break;
+ case CONSTANT_DOUBLE:
+ cpool[i++] = new Double(in.readDouble());
+ break;
+ case CONSTANT_CLASS:
+ case CONSTANT_STRING:
+ cpool[i] = new CPX(in.readUnsignedShort());
+ break;
+
+ case CONSTANT_FIELD:
+ case CONSTANT_METHOD:
+ case CONSTANT_INTERFACEMETHOD:
+ case CONSTANT_NAMEANDTYPE:
+ cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
+ break;
+
+ case 0:
+ default:
+ throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
+ }
+ }
+ }
+
+ /**
+ * Reads and strores field info.
+ */
+ protected void readFields(DataInputStream in) throws IOException {
+ int fields_count = in.readUnsignedShort();
+ fields=new FieldData[fields_count];
+ for (int k = 0; k < fields_count; k++) {
+ FieldData field=new FieldData(this);
+ field.read(in);
+ fields[k]=field;
+ }
+ }
+
+ /**
+ * Reads and strores Method info.
+ */
+ protected void readMethods(DataInputStream in) throws IOException {
+ int methods_count = in.readUnsignedShort();
+ methods=new MethodData[methods_count];
+ for (int k = 0; k < methods_count ; k++) {
+ MethodData method=new MethodData(this);
+ method.read(in);
+ methods[k]=method;
+ }
+ }
+
+ /**
+ * get a string
+ */
+ public String getString(int n) {
+ if (n == 0) {
+ return null;
+ } else {
+ return (String)cpool[n];
+ }
+ }
+
+ /**
+ * get the type of constant given an index
+ */
+ public byte getTag(int n) {
+ try{
+ return tags[n];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return (byte)100;
+ }
+ }
+
+ static final String hexString="0123456789ABCDEF";
+
+ public static char hexTable[]=hexString.toCharArray();
+
+ static String toHex(long val, int width) {
+ StringBuffer s = new StringBuffer();
+ for (int i=width-1; i>=0; i--)
+ s.append(hexTable[((int)(val>>(4*i)))&0xF]);
+ return "0x"+s.toString();
+ }
+
+ static String toHex(long val) {
+ int width;
+ for (width=16; width>0; width--) {
+ if ((val>>(width-1)*4)!=0) break;
+ }
+ return toHex(val, width);
+ }
+
+ static String toHex(int val) {
+ int width;
+ for (width=8; width>0; width--) {
+ if ((val>>(width-1)*4)!=0) break;
+ }
+ return toHex(val, width);
+ }
+
+ /**
+ * Returns the name of this class.
+ */
+ public String getClassName() {
+ String res=null;
+ if (this_class==0) {
+ return res;
+ }
+ int tcpx;
+ try {
+ if (tags[this_class]!=CONSTANT_CLASS) {
+ return res; //" ";
+ }
+ tcpx=((CPX)cpool[this_class]).cpx;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "#"+cpx+"// invalid constant pool index";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+
+ try {
+ return (String)(cpool[tcpx]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "class #"+scpx+"// invalid constant pool index";
+ } catch (ClassCastException e) {
+ return res; // "class #"+scpx+"// invalid constant pool reference";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+
+ }
+
+ /**
+ * Returns the name of class at perticular index.
+ */
+ public String getClassName(int cpx) {
+ String res="#"+cpx;
+ if (cpx==0) {
+ return res;
+ }
+ int scpx;
+ try {
+ if (tags[cpx]!=CONSTANT_CLASS) {
+ return res; //" ";
+ }
+ scpx=((CPX)cpool[cpx]).cpx;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "#"+cpx+"// invalid constant pool index";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+ res="#"+scpx;
+ try {
+ return (String)(cpool[scpx]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "class #"+scpx+"// invalid constant pool index";
+ } catch (ClassCastException e) {
+ return res; // "class #"+scpx+"// invalid constant pool reference";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+ }
+
+ public int getAccessFlags() {
+ return access;
+ }
+
+ /**
+ * Returns true if it is a class
+ */
+ public boolean isClass() {
+ if((access & ACC_INTERFACE) == 0) return true;
+ return false;
+ }
+
+ /**
+ * Returns true if it is a interface.
+ */
+ public boolean isInterface(){
+ if((access & ACC_INTERFACE) != 0) return true;
+ return false;
+ }
+
+ /**
+ * Returns true if this member is public, false otherwise.
+ */
+ public boolean isPublic(){
+ return (access & ACC_PUBLIC) != 0;
+ }
+
+ /**
+ * Returns the access of this class or interface.
+ */
+ public String[] getAccess(){
+ Vector v = new Vector();
+ if ((access & ACC_PUBLIC) !=0) v.addElement("public");
+ if ((access & ACC_FINAL) !=0) v.addElement("final");
+ if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
+ String[] accflags = new String[v.size()];
+ v.copyInto(accflags);
+ return accflags;
+ }
+
+ /**
+ * Returns list of innerclasses.
+ */
+ public InnerClassData[] getInnerClasses(){
+ return innerClasses;
+ }
+
+ /**
+ * Returns list of attributes.
+ */
+ final AttrData[] getAttributes(){
+ return attrs;
+ }
+
+ public byte[] findAnnotationData(boolean classRetention) {
+ String n = classRetention ?
+ "RuntimeInvisibleAnnotations" : // NOI18N
+ "RuntimeVisibleAnnotations"; // NOI18N
+ return findAttr(n, attrs);
+ }
+
+ /**
+ * Returns true if superbit is set.
+ */
+ public boolean isSuperSet(){
+ if ((access & ACC_SUPER) !=0) return true;
+ return false;
+ }
+
+ /**
+ * Returns super class name.
+ */
+ public String getSuperClassName(){
+ String res=null;
+ if (super_class==0) {
+ return res;
+ }
+ int scpx;
+ try {
+ if (tags[super_class]!=CONSTANT_CLASS) {
+ return res; //" ";
+ }
+ scpx=((CPX)cpool[super_class]).cpx;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "#"+cpx+"// invalid constant pool index";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+
+ try {
+ return (String)(cpool[scpx]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return res; // "class #"+scpx+"// invalid constant pool index";
+ } catch (ClassCastException e) {
+ return res; // "class #"+scpx+"// invalid constant pool reference";
+ } catch (Throwable e) {
+ return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
+ }
+ }
+
+ /**
+ * Returns list of super interfaces.
+ */
+ public String[] getSuperInterfaces(){
+ String interfacenames[] = new String[interfaces.length];
+ int interfacecpx = -1;
+ for(int i = 0; i < interfaces.length; i++){
+ interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
+ interfacenames[i] = (String)(cpool[interfacecpx]);
+ }
+ return interfacenames;
+ }
+
+ /**
+ * Returns string at prticular constant pool index.
+ */
+ public String getStringValue(int cpoolx) {
+ try {
+ return ((String)cpool[cpoolx]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "//invalid constant pool index:"+cpoolx;
+ } catch (ClassCastException e) {
+ return "//invalid constant pool ref:"+cpoolx;
+ }
+ }
+
+ /**
+ * Returns list of field info.
+ */
+ public FieldData[] getFields(){
+ return fields;
+ }
+
+ /**
+ * Returns list of method info.
+ */
+ public MethodData[] getMethods(){
+ return methods;
+ }
+
+ /**
+ * Returns constant pool entry at that index.
+ */
+ public CPX2 getCpoolEntry(int cpx){
+ return ((CPX2)(cpool[cpx]));
+ }
+
+ public Object getCpoolEntryobj(int cpx){
+ return (cpool[cpx]);
+ }
+
+ /**
+ * Returns index of this class.
+ */
+ public int getthis_cpx(){
+ return this_class;
+ }
+
+ /**
+ * Returns string at that index.
+ */
+ public String StringValue(int cpx) {
+ return stringValue(cpx, false);
+ }
+ public String stringValue(int cpx, boolean textual) {
+ return stringValue(cpx, textual, null);
+ }
+ public String stringValue(int cpx, String[] classRefs) {
+ return stringValue(cpx, true, classRefs);
+ }
+ private String stringValue(int cpx, boolean textual, String[] refs) {
+ if (cpx==0) return "#0";
+ int tag;
+ Object x;
+ String suffix="";
+ try {
+ tag=tags[cpx];
+ x=cpool[cpx];
+ } catch (IndexOutOfBoundsException e) {
+ return "";
+ }
+
+ if (x==null) return "";
+ switch (tag) {
+ case CONSTANT_UTF8: {
+ if (!textual) {
+ return (String)x;
+ }
+ StringBuilder sb=new StringBuilder();
+ String s=(String)x;
+ for (int k=0; k";
+ } catch (ClassCastException e) {
+ return "";
+ }
+ }
+
+ /**
+ * Returns unqualified class name.
+ */
+ public String getShortClassName(int cpx) {
+ String classname=javaName(getClassName(cpx));
+ pkgPrefixLen=classname.lastIndexOf("/")+1;
+ if (pkgPrefixLen!=0) {
+ pkgPrefix=classname.substring(0,pkgPrefixLen);
+ if (classname.startsWith(pkgPrefix)) {
+ return classname.substring(pkgPrefixLen);
+ }
+ }
+ return classname;
+ }
+
+ /**
+ * Returns source file name.
+ */
+ public String getSourceName(){
+ return getName(source_cpx);
+ }
+
+ /**
+ * Returns package name.
+ */
+ public String getPkgName(){
+ String classname=getClassName(this_class);
+ pkgPrefixLen=classname.lastIndexOf("/")+1;
+ if (pkgPrefixLen!=0) {
+ pkgPrefix=classname.substring(0,pkgPrefixLen);
+ return("package "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
+ }else return null;
+ }
+
+ /**
+ * Returns total constant pool entry count.
+ */
+ public int getCpoolCount(){
+ return cpool_count;
+ }
+
+ /**
+ * Returns minor version of class file.
+ */
+ public int getMinor_version(){
+ return minor_version;
+ }
+
+ /**
+ * Returns major version of class file.
+ */
+ public int getMajor_version(){
+ return major_version;
+ }
+
+ private boolean isJavaIdentifierStart(int cp) {
+ return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
+ }
+
+ private boolean isJavaIdentifierPart(int cp) {
+ return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
+ }
+
+ public String[] getNameAndType(int indx) {
+ return getNameAndType(indx, 0, new String[2]);
+ }
+
+ private String[] getNameAndType(int indx, int at, String[] arr) {
+ CPX2 c2 = getCpoolEntry(indx);
+ arr[at] = StringValue(c2.cpx1);
+ arr[at + 1] = StringValue(c2.cpx2);
+ return arr;
+ }
+
+ public String[] getFieldInfoName(int indx) {
+ CPX2 c2 = getCpoolEntry(indx);
+ String[] arr = new String[3];
+ arr[0] = getClassName(c2.cpx1);
+ return getNameAndType(c2.cpx2, 1, arr);
+ }
+
+ static byte[] findAttr(String n, AttrData[] attrs) {
+ for (AttrData ad : attrs) {
+ if (n.equals(ad.getAttrName())) {
+ return ad.getData();
+ }
+ }
+ return null;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Constants.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/Constants.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.apidesign.javap;
+
+/**
+ * This interface defines constant that are used
+ * throughout the compiler. It inherits from RuntimeConstants,
+ * which is an autogenerated class that contains contstants
+ * defined in the interpreter.
+ */
+
+public
+interface Constants extends RuntimeConstants {
+
+ /**
+ * End of input
+ */
+ public static final int EOF = -1;
+
+ /*
+ * Flags
+ */
+ public static final int F_VERBOSE = 1 << 0;
+ public static final int F_DUMP = 1 << 1;
+ public static final int F_WARNINGS = 1 << 2;
+ public static final int F_DEBUG = 1 << 3;
+ public static final int F_OPTIMIZE = 1 << 4;
+ public static final int F_DEPENDENCIES = 1 << 5;
+
+ /*
+ * Type codes
+ */
+ public static final int TC_BOOLEAN = 0;
+ public static final int TC_BYTE = 1;
+ public static final int TC_CHAR = 2;
+ public static final int TC_SHORT = 3;
+ public static final int TC_INT = 4;
+ public static final int TC_LONG = 5;
+ public static final int TC_FLOAT = 6;
+ public static final int TC_DOUBLE = 7;
+ public static final int TC_NULL = 8;
+ public static final int TC_ARRAY = 9;
+ public static final int TC_CLASS = 10;
+ public static final int TC_VOID = 11;
+ public static final int TC_METHOD = 12;
+ public static final int TC_ERROR = 13;
+
+ /*
+ * Type Masks
+ */
+ public static final int TM_NULL = 1 << TC_NULL;
+ public static final int TM_VOID = 1 << TC_VOID;
+ public static final int TM_BOOLEAN = 1 << TC_BOOLEAN;
+ public static final int TM_BYTE = 1 << TC_BYTE;
+ public static final int TM_CHAR = 1 << TC_CHAR;
+ public static final int TM_SHORT = 1 << TC_SHORT;
+ public static final int TM_INT = 1 << TC_INT;
+ public static final int TM_LONG = 1 << TC_LONG;
+ public static final int TM_FLOAT = 1 << TC_FLOAT;
+ public static final int TM_DOUBLE = 1 << TC_DOUBLE;
+ public static final int TM_ARRAY = 1 << TC_ARRAY;
+ public static final int TM_CLASS = 1 << TC_CLASS;
+ public static final int TM_METHOD = 1 << TC_METHOD;
+ public static final int TM_ERROR = 1 << TC_ERROR;
+
+ public static final int TM_INT32 = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
+ public static final int TM_NUM32 = TM_INT32 | TM_FLOAT;
+ public static final int TM_NUM64 = TM_LONG | TM_DOUBLE;
+ public static final int TM_INTEGER = TM_INT32 | TM_LONG;
+ public static final int TM_REAL = TM_FLOAT | TM_DOUBLE;
+ public static final int TM_NUMBER = TM_INTEGER | TM_REAL;
+ public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
+
+ /*
+ * Class status
+ */
+ public static final int CS_UNDEFINED = 0;
+ public static final int CS_UNDECIDED = 1;
+ public static final int CS_BINARY = 2;
+ public static final int CS_SOURCE = 3;
+ public static final int CS_PARSED = 4;
+ public static final int CS_COMPILED = 5;
+ public static final int CS_NOTFOUND = 6;
+
+ /*
+ * Attributes
+ */
+ public static final int ATT_ALL = -1;
+ public static final int ATT_CODE = 1;
+
+ /*
+ * Number of bits used in file offsets
+ */
+ public static final int OFFSETBITS = 19;
+ public static final int MAXFILESIZE = (1 << OFFSETBITS) - 1;
+ public static final int MAXLINENUMBER = (1 << (32 - OFFSETBITS)) - 1;
+
+ /*
+ * Operators
+ */
+ public final int COMMA = 0;
+ public final int ASSIGN = 1;
+
+ public final int ASGMUL = 2;
+ public final int ASGDIV = 3;
+ public final int ASGREM = 4;
+ public final int ASGADD = 5;
+ public final int ASGSUB = 6;
+ public final int ASGLSHIFT = 7;
+ public final int ASGRSHIFT = 8;
+ public final int ASGURSHIFT = 9;
+ public final int ASGBITAND = 10;
+ public final int ASGBITOR = 11;
+ public final int ASGBITXOR = 12;
+
+ public final int COND = 13;
+ public final int OR = 14;
+ public final int AND = 15;
+ public final int BITOR = 16;
+ public final int BITXOR = 17;
+ public final int BITAND = 18;
+ public final int NE = 19;
+ public final int EQ = 20;
+ public final int GE = 21;
+ public final int GT = 22;
+ public final int LE = 23;
+ public final int LT = 24;
+ public final int INSTANCEOF = 25;
+ public final int LSHIFT = 26;
+ public final int RSHIFT = 27;
+ public final int URSHIFT = 28;
+ public final int ADD = 29;
+ public final int SUB = 30;
+ public final int DIV = 31;
+ public final int REM = 32;
+ public final int MUL = 33;
+ public final int CAST = 34; // (x)y
+ public final int POS = 35; // +x
+ public final int NEG = 36; // -x
+ public final int NOT = 37;
+ public final int BITNOT = 38;
+ public final int PREINC = 39; // ++x
+ public final int PREDEC = 40; // --x
+ public final int NEWARRAY = 41;
+ public final int NEWINSTANCE = 42;
+ public final int NEWFROMNAME = 43;
+ public final int POSTINC = 44; // x++
+ public final int POSTDEC = 45; // x--
+ public final int FIELD = 46;
+ public final int METHOD = 47; // x(y)
+ public final int ARRAYACCESS = 48; // x[y]
+ public final int NEW = 49;
+ public final int INC = 50;
+ public final int DEC = 51;
+
+ public final int CONVERT = 55; // implicit conversion
+ public final int EXPR = 56; // (x)
+ public final int ARRAY = 57; // {x, y, ...}
+ public final int GOTO = 58;
+
+ /*
+ * Value tokens
+ */
+ public final int IDENT = 60;
+ public final int BOOLEANVAL = 61;
+ public final int BYTEVAL = 62;
+ public final int CHARVAL = 63;
+ public final int SHORTVAL = 64;
+ public final int INTVAL = 65;
+ public final int LONGVAL = 66;
+ public final int FLOATVAL = 67;
+ public final int DOUBLEVAL = 68;
+ public final int STRINGVAL = 69;
+
+ /*
+ * Type keywords
+ */
+ public final int BYTE = 70;
+ public final int CHAR = 71;
+ public final int SHORT = 72;
+ public final int INT = 73;
+ public final int LONG = 74;
+ public final int FLOAT = 75;
+ public final int DOUBLE = 76;
+ public final int VOID = 77;
+ public final int BOOLEAN = 78;
+
+ /*
+ * Expression keywords
+ */
+ public final int TRUE = 80;
+ public final int FALSE = 81;
+ public final int THIS = 82;
+ public final int SUPER = 83;
+ public final int NULL = 84;
+
+ /*
+ * Statement keywords
+ */
+ public final int IF = 90;
+ public final int ELSE = 91;
+ public final int FOR = 92;
+ public final int WHILE = 93;
+ public final int DO = 94;
+ public final int SWITCH = 95;
+ public final int CASE = 96;
+ public final int DEFAULT = 97;
+ public final int BREAK = 98;
+ public final int CONTINUE = 99;
+ public final int RETURN = 100;
+ public final int TRY = 101;
+ public final int CATCH = 102;
+ public final int FINALLY = 103;
+ public final int THROW = 104;
+ public final int STAT = 105;
+ public final int EXPRESSION = 106;
+ public final int DECLARATION = 107;
+ public final int VARDECLARATION = 108;
+
+ /*
+ * Declaration keywords
+ */
+ public final int IMPORT = 110;
+ public final int CLASS = 111;
+ public final int EXTENDS = 112;
+ public final int IMPLEMENTS = 113;
+ public final int INTERFACE = 114;
+ public final int PACKAGE = 115;
+
+ /*
+ * Modifier keywords
+ */
+ public final int PRIVATE = 120;
+ public final int PUBLIC = 121;
+ public final int PROTECTED = 122;
+ public final int CONST = 123;
+ public final int STATIC = 124;
+ public final int TRANSIENT = 125;
+ public final int SYNCHRONIZED = 126;
+ public final int NATIVE = 127;
+ public final int FINAL = 128;
+ public final int VOLATILE = 129;
+ public final int ABSTRACT = 130;
+ public final int STRICT = 165;
+
+ /*
+ * Punctuation
+ */
+ public final int SEMICOLON = 135;
+ public final int COLON = 136;
+ public final int QUESTIONMARK = 137;
+ public final int LBRACE = 138;
+ public final int RBRACE = 139;
+ public final int LPAREN = 140;
+ public final int RPAREN = 141;
+ public final int LSQBRACKET = 142;
+ public final int RSQBRACKET = 143;
+ public final int THROWS = 144;
+
+ /*
+ * Special tokens
+ */
+ public final int ERROR = 145; // an error
+ public final int COMMENT = 146; // not used anymore.
+ public final int TYPE = 147;
+ public final int LENGTH = 148;
+ public final int INLINERETURN = 149;
+ public final int INLINEMETHOD = 150;
+ public final int INLINENEWINSTANCE = 151;
+
+ /*
+ * Added for jasm
+ */
+ public final int METHODREF = 152;
+ public final int FIELDREF = 153;
+ public final int STACK = 154;
+ public final int LOCAL = 155;
+ public final int CPINDEX = 156;
+ public final int CPNAME = 157;
+ public final int SIGN = 158;
+ public final int BITS = 159;
+ public final int INF = 160;
+ public final int NAN = 161;
+ public final int INNERCLASS = 162;
+ public final int OF = 163;
+ public final int SYNTHETIC = 164;
+// last used=165;
+
+ /*
+ * Operator precedence
+ */
+ public static final int opPrecedence[] = {
+ 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 12, 13, 14, 15, 16, 17, 18,
+ 18, 19, 19, 19, 19, 19, 20, 20, 20, 21,
+ 21, 22, 22, 22, 23, 24, 24, 24, 24, 24,
+ 24, 25, 25, 26, 26, 26, 26, 26, 26
+ };
+
+ /*
+ * Operator names
+ */
+ public static final String opNames[] = {
+ ",", "=", "*=", "/=", "%=",
+ "+=", "-=", "<<=", ">>=", "<<<=",
+ "&=", "|=", "^=", "?:", "||",
+ "&&", "|", "^", "&", "!=",
+ "==", ">=", ">", "<=", "<",
+ "instanceof", "<<", ">>", "<<<", "+",
+ "-", "/", "%", "*", "cast",
+ "+", "-", "!", "~", "++",
+ "--", "new", "new", "new", "++",
+ "--", "field", "method", "[]", "new",
+ "++", "--", null, null, null,
+
+ "convert", "expr", "array", "goto", null,
+
+ "Identifier", "Boolean", "Byte", "Char", "Short",
+ "Integer", "Long", "Float", "Double", "String",
+
+ "byte", "char", "short", "int", "long",
+ "float", "double", "void", "boolean", null,
+
+ "true", "false", "this", "super", "null",
+ null, null, null, null, null,
+
+ "if", "else", "for", "while", "do",
+ "switch", "case", "default", "break", "continue",
+ "return", "try", "catch", "finally", "throw",
+ "stat", "expression", "declaration", "declaration", null,
+
+ "import", "class", "extends", "implements", "interface",
+ "package", null, null, null, null,
+
+ "private", "public", "protected", "const", "static",
+ "transient", "synchronized", "native", "final", "volatile",
+ "abstract", null, null, null, null,
+
+ ";", ":", "?", "{", "}",
+ "(", ")", "[", "]", "throws",
+ "error", "comment", "type", "length", "inline-return",
+ "inline-method", "inline-new",
+ "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN",
+ "bits", "INF", "NaN", "InnerClass", "of", "synthetic"
+ };
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/FieldData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/FieldData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+
+/**
+ * Strores field data informastion.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+
+public class FieldData implements RuntimeConstants {
+
+ ClassData cls;
+ int access;
+ int name_index;
+ int descriptor_index;
+ int attributes_count;
+ int value_cpx=0;
+ boolean isSynthetic=false;
+ boolean isDeprecated=false;
+ Vector attrs;
+
+ public FieldData(ClassData cls){
+ this.cls=cls;
+ }
+
+ /**
+ * Read and store field info.
+ */
+ public void read(DataInputStream in) throws IOException {
+ access = in.readUnsignedShort();
+ name_index = in.readUnsignedShort();
+ descriptor_index = in.readUnsignedShort();
+ // Read the attributes
+ int attributes_count = in.readUnsignedShort();
+ attrs=new Vector(attributes_count);
+ for (int i = 0; i < attributes_count; i++) {
+ int attr_name_index=in.readUnsignedShort();
+ if (cls.getTag(attr_name_index)!=CONSTANT_UTF8) continue;
+ String attr_name=cls.getString(attr_name_index);
+ if (attr_name.equals("ConstantValue")){
+ if (in.readInt()!=2)
+ throw new ClassFormatError("invalid ConstantValue attr length");
+ value_cpx=in.readUnsignedShort();
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ } else if (attr_name.equals("Synthetic")){
+ if (in.readInt()!=0)
+ throw new ClassFormatError("invalid Synthetic attr length");
+ isSynthetic=true;
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ } else if (attr_name.equals("Deprecated")){
+ if (in.readInt()!=0)
+ throw new ClassFormatError("invalid Synthetic attr length");
+ isDeprecated = true;
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ } else {
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index, in);
+ attrs.addElement(attr);
+ }
+ }
+
+ } // end read
+
+ public boolean isStatic() {
+ return (access & ACC_STATIC) != 0;
+ }
+
+ /**
+ * Returns access of a field.
+ */
+ public String[] getAccess(){
+ Vector v = new Vector();
+ if ((access & ACC_PUBLIC) !=0) v.addElement("public");
+ if ((access & ACC_PRIVATE) !=0) v.addElement("private");
+ if ((access & ACC_PROTECTED) !=0) v.addElement("protected");
+ if ((access & ACC_STATIC) !=0) v.addElement("static");
+ if ((access & ACC_FINAL) !=0) v.addElement("final");
+ if ((access & ACC_VOLATILE) !=0) v.addElement("volatile");
+ if ((access & ACC_TRANSIENT) !=0) v.addElement("transient");
+ String[] accflags = new String[v.size()];
+ v.copyInto(accflags);
+ return accflags;
+ }
+
+ /**
+ * Returns name of a field.
+ */
+ public String getName(){
+ return cls.getStringValue(name_index);
+ }
+
+ /**
+ * Returns internal signature of a field
+ */
+ public String getInternalSig(){
+ return cls.getStringValue(descriptor_index);
+ }
+
+ /**
+ * Returns true if field is synthetic.
+ */
+ public boolean isSynthetic(){
+ return isSynthetic;
+ }
+
+ /**
+ * Returns true if field is deprecated.
+ */
+ public boolean isDeprecated(){
+ return isDeprecated;
+ }
+
+ /**
+ * Returns index of constant value in cpool.
+ */
+ public int getConstantValueIndex(){
+ return (value_cpx);
+ }
+
+ /**
+ * Returns list of attributes of field.
+ */
+ public Vector getAttributes(){
+ return attrs;
+ }
+
+ public byte[] findAnnotationData(boolean classRetention) {
+ String n = classRetention ?
+ "RuntimeInvisibleAnnotations" : // NOI18N
+ "RuntimeVisibleAnnotations"; // NOI18N
+ AttrData[] arr = new AttrData[attrs.size()];
+ attrs.copyInto(arr);
+ return ClassData.findAttr(n, arr);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Hashtable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/Hashtable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,94 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.javap;
+
+/** A JavaScript optimized replacement for Hashtable.
+ *
+ * @author Jaroslav Tulach
+ */
+final class Hashtable {
+ private Object[] keys;
+ private Object[] values;
+
+ Hashtable(int i) {
+ this();
+ }
+
+ Hashtable(int i, double d) {
+ this();
+ }
+
+ Hashtable() {
+ }
+
+ synchronized void put(Object key, Object val) {
+ int[] where = { -1, -1 };
+ Object found = get(key, where);
+ if (where[0] != -1) {
+ // key exists
+ values[where[0]] = val;
+ } else {
+ if (where[1] != -1) {
+ // null found
+ keys[where[1]] = key;
+ values[where[1]] = val;
+ } else {
+ if (keys == null) {
+ keys = new Object[11];
+ values = new Object[11];
+ keys[0] = key;
+ values[0] = val;
+ } else {
+ Object[] newKeys = new Object[keys.length * 2];
+ Object[] newValues = new Object[values.length * 2];
+ for (int i = 0; i < keys.length; i++) {
+ newKeys[i] = keys[i];
+ newValues[i] = values[i];
+ }
+ newKeys[keys.length] = key;
+ newValues[keys.length] = val;
+ keys = newKeys;
+ values = newValues;
+ }
+ }
+ }
+ }
+
+ Object get(Object key) {
+ return get(key, null);
+ }
+ private synchronized Object get(Object key, int[] foundAndNull) {
+ if (keys == null) {
+ return null;
+ }
+ for (int i = 0; i < keys.length; i++) {
+ if (keys[i] == null) {
+ if (foundAndNull != null) {
+ foundAndNull[1] = i;
+ }
+ } else if (keys[i].equals(key)) {
+ if (foundAndNull != null) {
+ foundAndNull[0] = i;
+ }
+ return values[i];
+ }
+ }
+ return null;
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/InnerClassData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/InnerClassData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Strores InnerClass data informastion.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class InnerClassData implements RuntimeConstants {
+ ClassData cls;
+
+
+ int inner_class_info_index
+ ,outer_class_info_index
+ ,inner_name_index
+ ,access
+ ;
+
+ public InnerClassData(ClassData cls) {
+ this.cls=cls;
+
+ }
+
+ /**
+ * Read Innerclass attribute data.
+ */
+ public void read(DataInputStream in) throws IOException {
+ inner_class_info_index = in.readUnsignedShort();
+ outer_class_info_index = in.readUnsignedShort();
+ inner_name_index = in.readUnsignedShort();
+ access = in.readUnsignedShort();
+ } // end read
+
+ /**
+ * Returns the access of this class or interface.
+ */
+ public String[] getAccess(){
+ Vector v = new Vector();
+ if ((access & ACC_PUBLIC) !=0) v.addElement("public");
+ if ((access & ACC_FINAL) !=0) v.addElement("final");
+ if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
+ String[] accflags = new String[v.size()];
+ v.copyInto(accflags);
+ return accflags;
+ }
+
+} // end InnerClassData
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/LineNumData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/LineNumData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Strores LineNumberTable data information.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class LineNumData {
+ short start_pc, line_number;
+
+ public LineNumData() {}
+
+ /**
+ * Read LineNumberTable attribute.
+ */
+ public LineNumData(DataInputStream in) throws IOException {
+ start_pc = in.readShort();
+ line_number=in.readShort();
+
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/LocVarData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/LocVarData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Strores LocalVariableTable data information.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+class LocVarData {
+ short start_pc, length, name_cpx, sig_cpx, slot;
+
+ public LocVarData() {
+ }
+
+ /**
+ * Read LocalVariableTable attribute.
+ */
+ public LocVarData(DataInputStream in) throws IOException {
+ start_pc = in.readShort();
+ length=in.readShort();
+ name_cpx=in.readShort();
+ sig_cpx=in.readShort();
+ slot=in.readShort();
+
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/MethodData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/MethodData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.apidesign.javap;
+
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import static org.apidesign.javap.RuntimeConstants.*;
+
+/**
+ * Strores method data informastion.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+public class MethodData {
+
+ ClassData cls;
+ int access;
+ int name_index;
+ int descriptor_index;
+ int attributes_count;
+ byte[] code;
+ Vector exception_table = new Vector(0);
+ Vector lin_num_tb = new Vector(0);
+ Vector loc_var_tb = new Vector(0);
+ StackMapTableData[] stackMapTable;
+ StackMapData[] stackMap;
+ int[] exc_index_table=null;
+ Vector attrs=new Vector(0);
+ Vector code_attrs=new Vector(0);
+ int max_stack, max_locals;
+ boolean isSynthetic=false;
+ boolean isDeprecated=false;
+
+ public MethodData(ClassData cls){
+ this.cls=cls;
+ }
+
+ /**
+ * Read method info.
+ */
+ public void read(DataInputStream in) throws IOException {
+ access = in.readUnsignedShort();
+ name_index=in.readUnsignedShort();
+ descriptor_index =in.readUnsignedShort();
+ int attributes_count = in.readUnsignedShort();
+ for (int i = 0; i < attributes_count; i++) {
+ int attr_name_index=in.readUnsignedShort();
+
+ readAttr: {
+ if (cls.getTag(attr_name_index)==CONSTANT_UTF8) {
+ String attr_name=cls.getString(attr_name_index);
+ if ( attr_name.equals("Code")){
+ readCode (in);
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ break readAttr;
+ } else if ( attr_name.equals("Exceptions")){
+ readExceptions(in);
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ break readAttr;
+ } else if (attr_name.equals("Synthetic")){
+ if (in.readInt()!=0)
+ throw new ClassFormatError("invalid Synthetic attr length");
+ isSynthetic=true;
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ break readAttr;
+ } else if (attr_name.equals("Deprecated")){
+ if (in.readInt()!=0)
+ throw new ClassFormatError("invalid Synthetic attr length");
+ isDeprecated = true;
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index);
+ attrs.addElement(attr);
+ break readAttr;
+ }
+ }
+ AttrData attr=new AttrData(cls);
+ attr.read(attr_name_index, in);
+ attrs.addElement(attr);
+ }
+ }
+ }
+
+ /**
+ * Read code attribute info.
+ */
+ public void readCode(DataInputStream in) throws IOException {
+
+ int attr_length = in.readInt();
+ max_stack=in.readUnsignedShort();
+ max_locals=in.readUnsignedShort();
+ int codelen=in.readInt();
+
+ code=new byte[codelen];
+ int totalread = 0;
+ while(totalread < codelen){
+ totalread += in.read(code, totalread, codelen-totalread);
+ }
+ // in.read(code, 0, codelen);
+ int clen = 0;
+ readExceptionTable(in);
+ int code_attributes_count = in.readUnsignedShort();
+
+ for (int k = 0 ; k < code_attributes_count ; k++) {
+ int table_name_index=in.readUnsignedShort();
+ int table_name_tag=cls.getTag(table_name_index);
+ AttrData attr=new AttrData(cls);
+ if (table_name_tag==CONSTANT_UTF8) {
+ String table_name_tstr=cls.getString(table_name_index);
+ if (table_name_tstr.equals("LineNumberTable")) {
+ readLineNumTable(in);
+ attr.read(table_name_index);
+ } else if (table_name_tstr.equals("LocalVariableTable")) {
+ readLocVarTable(in);
+ attr.read(table_name_index);
+ } else if (table_name_tstr.equals("StackMapTable")) {
+ readStackMapTable(in);
+ attr.read(table_name_index);
+ } else if (table_name_tstr.equals("StackMap")) {
+ readStackMap(in);
+ attr.read(table_name_index);
+ } else {
+ attr.read(table_name_index, in);
+ }
+ code_attrs.addElement(attr);
+ continue;
+ }
+
+ attr.read(table_name_index, in);
+ code_attrs.addElement(attr);
+ }
+ }
+
+ /**
+ * Read exception table info.
+ */
+ void readExceptionTable (DataInputStream in) throws IOException {
+ int exception_table_len=in.readUnsignedShort();
+ exception_table=new Vector(exception_table_len);
+ for (int l = 0; l < exception_table_len; l++) {
+ exception_table.addElement(new TrapData(in, l));
+ }
+ }
+
+ /**
+ * Read LineNumberTable attribute info.
+ */
+ void readLineNumTable (DataInputStream in) throws IOException {
+ int attr_len = in.readInt(); // attr_length
+ int lin_num_tb_len = in.readUnsignedShort();
+ lin_num_tb=new Vector(lin_num_tb_len);
+ for (int l = 0; l < lin_num_tb_len; l++) {
+ lin_num_tb.addElement(new LineNumData(in));
+ }
+ }
+
+ /**
+ * Read LocalVariableTable attribute info.
+ */
+ void readLocVarTable (DataInputStream in) throws IOException {
+ int attr_len=in.readInt(); // attr_length
+ int loc_var_tb_len = in.readUnsignedShort();
+ loc_var_tb = new Vector(loc_var_tb_len);
+ for (int l = 0; l < loc_var_tb_len; l++) {
+ loc_var_tb.addElement(new LocVarData(in));
+ }
+ }
+
+ /**
+ * Read Exception attribute info.
+ */
+ public void readExceptions(DataInputStream in) throws IOException {
+ int attr_len=in.readInt(); // attr_length in prog
+ int num_exceptions = in.readUnsignedShort();
+ exc_index_table=new int[num_exceptions];
+ for (int l = 0; l < num_exceptions; l++) {
+ int exc=in.readShort();
+ exc_index_table[l]=exc;
+ }
+ }
+
+ /**
+ * Read StackMapTable attribute info.
+ */
+ void readStackMapTable(DataInputStream in) throws IOException {
+ int attr_len = in.readInt(); //attr_length
+ int stack_map_tb_len = in.readUnsignedShort();
+ stackMapTable = new StackMapTableData[stack_map_tb_len];
+ for (int i=0; i".equals(getName());
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/RuntimeConstants.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/RuntimeConstants.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+public interface RuntimeConstants {
+
+ /* Signature Characters */
+ public static final char SIGC_VOID = 'V';
+ public static final String SIG_VOID = "V";
+ public static final char SIGC_BOOLEAN = 'Z';
+ public static final String SIG_BOOLEAN = "Z";
+ public static final char SIGC_BYTE = 'B';
+ public static final String SIG_BYTE = "B";
+ public static final char SIGC_CHAR = 'C';
+ public static final String SIG_CHAR = "C";
+ public static final char SIGC_SHORT = 'S';
+ public static final String SIG_SHORT = "S";
+ public static final char SIGC_INT = 'I';
+ public static final String SIG_INT = "I";
+ public static final char SIGC_LONG = 'J';
+ public static final String SIG_LONG = "J";
+ public static final char SIGC_FLOAT = 'F';
+ public static final String SIG_FLOAT = "F";
+ public static final char SIGC_DOUBLE = 'D';
+ public static final String SIG_DOUBLE = "D";
+ public static final char SIGC_ARRAY = '[';
+ public static final String SIG_ARRAY = "[";
+ public static final char SIGC_CLASS = 'L';
+ public static final String SIG_CLASS = "L";
+ public static final char SIGC_METHOD = '(';
+ public static final String SIG_METHOD = "(";
+ public static final char SIGC_ENDCLASS = ';';
+ public static final String SIG_ENDCLASS = ";";
+ public static final char SIGC_ENDMETHOD = ')';
+ public static final String SIG_ENDMETHOD = ")";
+ public static final char SIGC_PACKAGE = '/';
+ public static final String SIG_PACKAGE = "/";
+
+ /* Class File Constants */
+ public static final int JAVA_MAGIC = 0xcafebabe;
+ public static final int JAVA_VERSION = 45;
+ public static final int JAVA_MINOR_VERSION = 3;
+
+ /* Constant table */
+ public static final int CONSTANT_UTF8 = 1;
+ public static final int CONSTANT_UNICODE = 2;
+ public static final int CONSTANT_INTEGER = 3;
+ public static final int CONSTANT_FLOAT = 4;
+ public static final int CONSTANT_LONG = 5;
+ public static final int CONSTANT_DOUBLE = 6;
+ public static final int CONSTANT_CLASS = 7;
+ public static final int CONSTANT_STRING = 8;
+ public static final int CONSTANT_FIELD = 9;
+ public static final int CONSTANT_METHOD = 10;
+ public static final int CONSTANT_INTERFACEMETHOD = 11;
+ public static final int CONSTANT_NAMEANDTYPE = 12;
+
+ /* Access Flags */
+ public static final int ACC_PUBLIC = 0x00000001;
+ public static final int ACC_PRIVATE = 0x00000002;
+ public static final int ACC_PROTECTED = 0x00000004;
+ public static final int ACC_STATIC = 0x00000008;
+ public static final int ACC_FINAL = 0x00000010;
+ public static final int ACC_SYNCHRONIZED = 0x00000020;
+ public static final int ACC_SUPER = 0x00000020;
+ public static final int ACC_VOLATILE = 0x00000040;
+ public static final int ACC_TRANSIENT = 0x00000080;
+ public static final int ACC_NATIVE = 0x00000100;
+ public static final int ACC_INTERFACE = 0x00000200;
+ public static final int ACC_ABSTRACT = 0x00000400;
+ public static final int ACC_STRICT = 0x00000800;
+ public static final int ACC_EXPLICIT = 0x00001000;
+ public static final int ACC_SYNTHETIC = 0x00010000; // actually, this is an attribute
+
+ /* Type codes */
+ public static final int T_CLASS = 0x00000002;
+ public static final int T_BOOLEAN = 0x00000004;
+ public static final int T_CHAR = 0x00000005;
+ public static final int T_FLOAT = 0x00000006;
+ public static final int T_DOUBLE = 0x00000007;
+ public static final int T_BYTE = 0x00000008;
+ public static final int T_SHORT = 0x00000009;
+ public static final int T_INT = 0x0000000a;
+ public static final int T_LONG = 0x0000000b;
+
+ /* Type codes for StackMap attribute */
+ public static final int ITEM_Bogus =0; // an unknown or uninitialized value
+ public static final int ITEM_Integer =1; // a 32-bit integer
+ public static final int ITEM_Float =2; // not used
+ public static final int ITEM_Double =3; // not used
+ public static final int ITEM_Long =4; // a 64-bit integer
+ public static final int ITEM_Null =5; // the type of null
+ public static final int ITEM_InitObject =6; // "this" in constructor
+ public static final int ITEM_Object =7; // followed by 2-byte index of class name
+ public static final int ITEM_NewObject =8; // followed by 2-byte ref to "new"
+
+ /* Constants used in StackMapTable attribute */
+ public static final int SAME_FRAME_BOUND = 64;
+ public static final int SAME_LOCALS_1_STACK_ITEM_BOUND = 128;
+ public static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
+ public static final int SAME_FRAME_EXTENDED = 251;
+ public static final int FULL_FRAME = 255;
+
+ /* Opcodes */
+ public static final int opc_dead = -2;
+ public static final int opc_label = -1;
+ public static final int opc_nop = 0;
+ public static final int opc_aconst_null = 1;
+ public static final int opc_iconst_m1 = 2;
+ public static final int opc_iconst_0 = 3;
+ public static final int opc_iconst_1 = 4;
+ public static final int opc_iconst_2 = 5;
+ public static final int opc_iconst_3 = 6;
+ public static final int opc_iconst_4 = 7;
+ public static final int opc_iconst_5 = 8;
+ public static final int opc_lconst_0 = 9;
+ public static final int opc_lconst_1 = 10;
+ public static final int opc_fconst_0 = 11;
+ public static final int opc_fconst_1 = 12;
+ public static final int opc_fconst_2 = 13;
+ public static final int opc_dconst_0 = 14;
+ public static final int opc_dconst_1 = 15;
+ public static final int opc_bipush = 16;
+ public static final int opc_sipush = 17;
+ public static final int opc_ldc = 18;
+ public static final int opc_ldc_w = 19;
+ public static final int opc_ldc2_w = 20;
+ public static final int opc_iload = 21;
+ public static final int opc_lload = 22;
+ public static final int opc_fload = 23;
+ public static final int opc_dload = 24;
+ public static final int opc_aload = 25;
+ public static final int opc_iload_0 = 26;
+ public static final int opc_iload_1 = 27;
+ public static final int opc_iload_2 = 28;
+ public static final int opc_iload_3 = 29;
+ public static final int opc_lload_0 = 30;
+ public static final int opc_lload_1 = 31;
+ public static final int opc_lload_2 = 32;
+ public static final int opc_lload_3 = 33;
+ public static final int opc_fload_0 = 34;
+ public static final int opc_fload_1 = 35;
+ public static final int opc_fload_2 = 36;
+ public static final int opc_fload_3 = 37;
+ public static final int opc_dload_0 = 38;
+ public static final int opc_dload_1 = 39;
+ public static final int opc_dload_2 = 40;
+ public static final int opc_dload_3 = 41;
+ public static final int opc_aload_0 = 42;
+ public static final int opc_aload_1 = 43;
+ public static final int opc_aload_2 = 44;
+ public static final int opc_aload_3 = 45;
+ public static final int opc_iaload = 46;
+ public static final int opc_laload = 47;
+ public static final int opc_faload = 48;
+ public static final int opc_daload = 49;
+ public static final int opc_aaload = 50;
+ public static final int opc_baload = 51;
+ public static final int opc_caload = 52;
+ public static final int opc_saload = 53;
+ public static final int opc_istore = 54;
+ public static final int opc_lstore = 55;
+ public static final int opc_fstore = 56;
+ public static final int opc_dstore = 57;
+ public static final int opc_astore = 58;
+ public static final int opc_istore_0 = 59;
+ public static final int opc_istore_1 = 60;
+ public static final int opc_istore_2 = 61;
+ public static final int opc_istore_3 = 62;
+ public static final int opc_lstore_0 = 63;
+ public static final int opc_lstore_1 = 64;
+ public static final int opc_lstore_2 = 65;
+ public static final int opc_lstore_3 = 66;
+ public static final int opc_fstore_0 = 67;
+ public static final int opc_fstore_1 = 68;
+ public static final int opc_fstore_2 = 69;
+ public static final int opc_fstore_3 = 70;
+ public static final int opc_dstore_0 = 71;
+ public static final int opc_dstore_1 = 72;
+ public static final int opc_dstore_2 = 73;
+ public static final int opc_dstore_3 = 74;
+ public static final int opc_astore_0 = 75;
+ public static final int opc_astore_1 = 76;
+ public static final int opc_astore_2 = 77;
+ public static final int opc_astore_3 = 78;
+ public static final int opc_iastore = 79;
+ public static final int opc_lastore = 80;
+ public static final int opc_fastore = 81;
+ public static final int opc_dastore = 82;
+ public static final int opc_aastore = 83;
+ public static final int opc_bastore = 84;
+ public static final int opc_castore = 85;
+ public static final int opc_sastore = 86;
+ public static final int opc_pop = 87;
+ public static final int opc_pop2 = 88;
+ public static final int opc_dup = 89;
+ public static final int opc_dup_x1 = 90;
+ public static final int opc_dup_x2 = 91;
+ public static final int opc_dup2 = 92;
+ public static final int opc_dup2_x1 = 93;
+ public static final int opc_dup2_x2 = 94;
+ public static final int opc_swap = 95;
+ public static final int opc_iadd = 96;
+ public static final int opc_ladd = 97;
+ public static final int opc_fadd = 98;
+ public static final int opc_dadd = 99;
+ public static final int opc_isub = 100;
+ public static final int opc_lsub = 101;
+ public static final int opc_fsub = 102;
+ public static final int opc_dsub = 103;
+ public static final int opc_imul = 104;
+ public static final int opc_lmul = 105;
+ public static final int opc_fmul = 106;
+ public static final int opc_dmul = 107;
+ public static final int opc_idiv = 108;
+ public static final int opc_ldiv = 109;
+ public static final int opc_fdiv = 110;
+ public static final int opc_ddiv = 111;
+ public static final int opc_irem = 112;
+ public static final int opc_lrem = 113;
+ public static final int opc_frem = 114;
+ public static final int opc_drem = 115;
+ public static final int opc_ineg = 116;
+ public static final int opc_lneg = 117;
+ public static final int opc_fneg = 118;
+ public static final int opc_dneg = 119;
+ public static final int opc_ishl = 120;
+ public static final int opc_lshl = 121;
+ public static final int opc_ishr = 122;
+ public static final int opc_lshr = 123;
+ public static final int opc_iushr = 124;
+ public static final int opc_lushr = 125;
+ public static final int opc_iand = 126;
+ public static final int opc_land = 127;
+ public static final int opc_ior = 128;
+ public static final int opc_lor = 129;
+ public static final int opc_ixor = 130;
+ public static final int opc_lxor = 131;
+ public static final int opc_iinc = 132;
+ public static final int opc_i2l = 133;
+ public static final int opc_i2f = 134;
+ public static final int opc_i2d = 135;
+ public static final int opc_l2i = 136;
+ public static final int opc_l2f = 137;
+ public static final int opc_l2d = 138;
+ public static final int opc_f2i = 139;
+ public static final int opc_f2l = 140;
+ public static final int opc_f2d = 141;
+ public static final int opc_d2i = 142;
+ public static final int opc_d2l = 143;
+ public static final int opc_d2f = 144;
+ public static final int opc_i2b = 145;
+ public static final int opc_int2byte = 145;
+ public static final int opc_i2c = 146;
+ public static final int opc_int2char = 146;
+ public static final int opc_i2s = 147;
+ public static final int opc_int2short = 147;
+ public static final int opc_lcmp = 148;
+ public static final int opc_fcmpl = 149;
+ public static final int opc_fcmpg = 150;
+ public static final int opc_dcmpl = 151;
+ public static final int opc_dcmpg = 152;
+ public static final int opc_ifeq = 153;
+ public static final int opc_ifne = 154;
+ public static final int opc_iflt = 155;
+ public static final int opc_ifge = 156;
+ public static final int opc_ifgt = 157;
+ public static final int opc_ifle = 158;
+ public static final int opc_if_icmpeq = 159;
+ public static final int opc_if_icmpne = 160;
+ public static final int opc_if_icmplt = 161;
+ public static final int opc_if_icmpge = 162;
+ public static final int opc_if_icmpgt = 163;
+ public static final int opc_if_icmple = 164;
+ public static final int opc_if_acmpeq = 165;
+ public static final int opc_if_acmpne = 166;
+ public static final int opc_goto = 167;
+ public static final int opc_jsr = 168;
+ public static final int opc_ret = 169;
+ public static final int opc_tableswitch = 170;
+ public static final int opc_lookupswitch = 171;
+ public static final int opc_ireturn = 172;
+ public static final int opc_lreturn = 173;
+ public static final int opc_freturn = 174;
+ public static final int opc_dreturn = 175;
+ public static final int opc_areturn = 176;
+ public static final int opc_return = 177;
+ public static final int opc_getstatic = 178;
+ public static final int opc_putstatic = 179;
+ public static final int opc_getfield = 180;
+ public static final int opc_putfield = 181;
+ public static final int opc_invokevirtual = 182;
+ public static final int opc_invokenonvirtual = 183;
+ public static final int opc_invokespecial = 183;
+ public static final int opc_invokestatic = 184;
+ public static final int opc_invokeinterface = 185;
+// public static final int opc_xxxunusedxxx = 186;
+ public static final int opc_new = 187;
+ public static final int opc_newarray = 188;
+ public static final int opc_anewarray = 189;
+ public static final int opc_arraylength = 190;
+ public static final int opc_athrow = 191;
+ public static final int opc_checkcast = 192;
+ public static final int opc_instanceof = 193;
+ public static final int opc_monitorenter = 194;
+ public static final int opc_monitorexit = 195;
+ public static final int opc_wide = 196;
+ public static final int opc_multianewarray = 197;
+ public static final int opc_ifnull = 198;
+ public static final int opc_ifnonnull = 199;
+ public static final int opc_goto_w = 200;
+ public static final int opc_jsr_w = 201;
+ /* Pseudo-instructions */
+ public static final int opc_bytecode = 203;
+ public static final int opc_try = 204;
+ public static final int opc_endtry = 205;
+ public static final int opc_catch = 206;
+ public static final int opc_var = 207;
+ public static final int opc_endvar = 208;
+ public static final int opc_localsmap = 209;
+ public static final int opc_stackmap = 210;
+ /* PicoJava prefixes */
+ public static final int opc_nonpriv = 254;
+ public static final int opc_priv = 255;
+
+ /* Wide instructions */
+ public static final int opc_iload_w = (opc_wide<<8)|opc_iload;
+ public static final int opc_lload_w = (opc_wide<<8)|opc_lload;
+ public static final int opc_fload_w = (opc_wide<<8)|opc_fload;
+ public static final int opc_dload_w = (opc_wide<<8)|opc_dload;
+ public static final int opc_aload_w = (opc_wide<<8)|opc_aload;
+ public static final int opc_istore_w = (opc_wide<<8)|opc_istore;
+ public static final int opc_lstore_w = (opc_wide<<8)|opc_lstore;
+ public static final int opc_fstore_w = (opc_wide<<8)|opc_fstore;
+ public static final int opc_dstore_w = (opc_wide<<8)|opc_dstore;
+ public static final int opc_astore_w = (opc_wide<<8)|opc_astore;
+ public static final int opc_ret_w = (opc_wide<<8)|opc_ret;
+ public static final int opc_iinc_w = (opc_wide<<8)|opc_iinc;
+
+ /* Opcode Names */
+ public static final String opcNamesTab[] = {
+ "nop",
+ "aconst_null",
+ "iconst_m1",
+ "iconst_0",
+ "iconst_1",
+ "iconst_2",
+ "iconst_3",
+ "iconst_4",
+ "iconst_5",
+ "lconst_0",
+ "lconst_1",
+ "fconst_0",
+ "fconst_1",
+ "fconst_2",
+ "dconst_0",
+ "dconst_1",
+ "bipush",
+ "sipush",
+ "ldc",
+ "ldc_w",
+ "ldc2_w",
+ "iload",
+ "lload",
+ "fload",
+ "dload",
+ "aload",
+ "iload_0",
+ "iload_1",
+ "iload_2",
+ "iload_3",
+ "lload_0",
+ "lload_1",
+ "lload_2",
+ "lload_3",
+ "fload_0",
+ "fload_1",
+ "fload_2",
+ "fload_3",
+ "dload_0",
+ "dload_1",
+ "dload_2",
+ "dload_3",
+ "aload_0",
+ "aload_1",
+ "aload_2",
+ "aload_3",
+ "iaload",
+ "laload",
+ "faload",
+ "daload",
+ "aaload",
+ "baload",
+ "caload",
+ "saload",
+ "istore",
+ "lstore",
+ "fstore",
+ "dstore",
+ "astore",
+ "istore_0",
+ "istore_1",
+ "istore_2",
+ "istore_3",
+ "lstore_0",
+ "lstore_1",
+ "lstore_2",
+ "lstore_3",
+ "fstore_0",
+ "fstore_1",
+ "fstore_2",
+ "fstore_3",
+ "dstore_0",
+ "dstore_1",
+ "dstore_2",
+ "dstore_3",
+ "astore_0",
+ "astore_1",
+ "astore_2",
+ "astore_3",
+ "iastore",
+ "lastore",
+ "fastore",
+ "dastore",
+ "aastore",
+ "bastore",
+ "castore",
+ "sastore",
+ "pop",
+ "pop2",
+ "dup",
+ "dup_x1",
+ "dup_x2",
+ "dup2",
+ "dup2_x1",
+ "dup2_x2",
+ "swap",
+ "iadd",
+ "ladd",
+ "fadd",
+ "dadd",
+ "isub",
+ "lsub",
+ "fsub",
+ "dsub",
+ "imul",
+ "lmul",
+ "fmul",
+ "dmul",
+ "idiv",
+ "ldiv",
+ "fdiv",
+ "ddiv",
+ "irem",
+ "lrem",
+ "frem",
+ "drem",
+ "ineg",
+ "lneg",
+ "fneg",
+ "dneg",
+ "ishl",
+ "lshl",
+ "ishr",
+ "lshr",
+ "iushr",
+ "lushr",
+ "iand",
+ "land",
+ "ior",
+ "lor",
+ "ixor",
+ "lxor",
+ "iinc",
+ "i2l",
+ "i2f",
+ "i2d",
+ "l2i",
+ "l2f",
+ "l2d",
+ "f2i",
+ "f2l",
+ "f2d",
+ "d2i",
+ "d2l",
+ "d2f",
+ "i2b",
+ "i2c",
+ "i2s",
+ "lcmp",
+ "fcmpl",
+ "fcmpg",
+ "dcmpl",
+ "dcmpg",
+ "ifeq",
+ "ifne",
+ "iflt",
+ "ifge",
+ "ifgt",
+ "ifle",
+ "if_icmpeq",
+ "if_icmpne",
+ "if_icmplt",
+ "if_icmpge",
+ "if_icmpgt",
+ "if_icmple",
+ "if_acmpeq",
+ "if_acmpne",
+ "goto",
+ "jsr",
+ "ret",
+ "tableswitch",
+ "lookupswitch",
+ "ireturn",
+ "lreturn",
+ "freturn",
+ "dreturn",
+ "areturn",
+ "return",
+ "getstatic",
+ "putstatic",
+ "getfield",
+ "putfield",
+ "invokevirtual",
+ "invokespecial", // was "invokenonvirtual",
+ "invokestatic",
+ "invokeinterface",
+ "bytecode 186", //"xxxunusedxxx",
+ "new",
+ "newarray",
+ "anewarray",
+ "arraylength",
+ "athrow",
+ "checkcast",
+ "instanceof",
+ "monitorenter",
+ "monitorexit",
+ null, // "wide",
+ "multianewarray",
+ "ifnull",
+ "ifnonnull",
+ "goto_w",
+ "jsr_w",
+ "bytecode 202", // "breakpoint",
+ "bytecode",
+ "try",
+ "endtry",
+ "catch",
+ "var",
+ "endvar",
+ "locals_map",
+ "stack_map"
+ };
+
+ /* Opcode Lengths */
+ public static final int opcLengthsTab[] = {
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 3,
+ 2,
+ 3,
+ 3,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 3,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 2,
+ 99,
+ 99,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 3,
+ 5,
+ 0,
+ 3,
+ 2,
+ 3,
+ 1,
+ 1,
+ 3,
+ 3,
+ 1,
+ 1,
+ 0, // wide
+ 4,
+ 3,
+ 3,
+ 5,
+ 5,
+ 1,
+ 1, 0, 0, 0, 0, 0 // pseudo
+ };
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/StackMapData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/StackMapData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.util.*;
+import java.io.*;
+
+import static org.apidesign.javap.RuntimeConstants.*;
+
+/* represents one entry of StackMap attribute
+ */
+class StackMapData {
+ final int offset;
+ final int[] locals;
+ final int[] stack;
+
+ StackMapData(int offset, int[] locals, int[] stack) {
+ this.offset = offset;
+ this.locals = locals;
+ this.stack = stack;
+ }
+
+ StackMapData(DataInputStream in, MethodData method) throws IOException {
+ offset = in.readUnsignedShort();
+ int local_size = in.readUnsignedShort();
+ locals = readTypeArray(in, local_size, method);
+ int stack_size = in.readUnsignedShort();
+ stack = readTypeArray(in, stack_size, method);
+ }
+
+ static final int[] readTypeArray(DataInputStream in, int length, MethodData method) throws IOException {
+ int[] types = new int[length];
+ for (int i=0; i= (stackMapTable[nextFrameIndex].offsetDelta
+ + 1))) {
+ final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
+
+ lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
+ nextFrame.applyTo(localTypes, stackTypes);
+
+ ++nextFrameIndex;
+ }
+ }
+
+ public void advanceTo(final int nextByteCodeOffset) {
+ advanceBy(nextByteCodeOffset - byteCodeOffset);
+ }
+
+ private static TypeArray getArgTypes(final String methodSignature,
+ final boolean isStaticMethod) {
+ final TypeArray argTypes = new TypeArray();
+
+ if (!isStaticMethod) {
+ argTypes.add(ITEM_Object);
+ }
+
+ if (methodSignature.charAt(0) != '(') {
+ throw new IllegalArgumentException("Invalid method signature");
+ }
+
+ final int length = methodSignature.length();
+ boolean skipType = false;
+ int argType;
+ for (int i = 1; i < length; ++i) {
+ switch (methodSignature.charAt(i)) {
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ case 'I':
+ argType = ITEM_Integer;
+ break;
+ case 'J':
+ argType = ITEM_Long;
+ break;
+ case 'F':
+ argType = ITEM_Float;
+ break;
+ case 'D':
+ argType = ITEM_Double;
+ break;
+ case 'L': {
+ i = methodSignature.indexOf(';', i + 1);
+ if (i == -1) {
+ throw new IllegalArgumentException(
+ "Invalid method signature");
+ }
+ argType = ITEM_Object;
+ break;
+ }
+ case ')':
+ // not interested in the return value type
+ return argTypes;
+ case '[':
+ if (!skipType) {
+ argTypes.add(ITEM_Object);
+ skipType = true;
+ }
+ continue;
+
+ default:
+ throw new IllegalArgumentException(
+ "Invalid method signature");
+ }
+
+ if (!skipType) {
+ argTypes.add(argType);
+ } else {
+ skipType = false;
+ }
+ }
+
+ return argTypes;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/StackMapTableData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/StackMapTableData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+
+import static org.apidesign.javap.RuntimeConstants.*;
+
+/* represents one entry of StackMapTable attribute
+ */
+abstract class StackMapTableData {
+ final int frameType;
+ int offsetDelta;
+
+ StackMapTableData(int frameType) {
+ this.frameType = frameType;
+ }
+
+ abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
+
+ protected static String toString(
+ final String frameType,
+ final int offset,
+ final int[] localTypes,
+ final int[] stackTypes) {
+ final StringBuilder sb = new StringBuilder(frameType);
+
+ sb.append("(off: +").append(offset);
+ if (localTypes != null) {
+ sb.append(", locals: ");
+ appendTypes(sb, localTypes);
+ }
+ if (stackTypes != null) {
+ sb.append(", stack: ");
+ appendTypes(sb, stackTypes);
+ }
+ sb.append(')');
+
+ return sb.toString();
+ }
+
+ private static void appendTypes(final StringBuilder sb, final int[] types) {
+ sb.append('[');
+ if (types.length > 0) {
+ sb.append(TypeArray.typeString(types[0]));
+ for (int i = 1; i < types.length; ++i) {
+ sb.append(", ");
+ sb.append(TypeArray.typeString(types[i]));
+ }
+ }
+ sb.append(']');
+ }
+
+ static class SameFrame extends StackMapTableData {
+ SameFrame(int frameType, int offsetDelta) {
+ super(frameType);
+ this.offsetDelta = offsetDelta;
+ }
+
+ @Override
+ void applyTo(TypeArray localTypes, TypeArray stackTypes) {
+ stackTypes.clear();
+ }
+
+ @Override
+ public String toString() {
+ return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
+ ? "_FRAME_EXTENDED" : ""),
+ offsetDelta,
+ null, null);
+ }
+ }
+
+ static class SameLocals1StackItem extends StackMapTableData {
+ final int[] stack;
+ SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
+ super(frameType);
+ this.offsetDelta = offsetDelta;
+ this.stack = stack;
+ }
+
+ @Override
+ void applyTo(TypeArray localTypes, TypeArray stackTypes) {
+ stackTypes.setAll(stack);
+ }
+
+ @Override
+ public String toString() {
+ return toString(
+ "SAME_LOCALS_1_STACK_ITEM"
+ + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
+ ? "_EXTENDED" : ""),
+ offsetDelta,
+ null, stack);
+ }
+ }
+
+ static class ChopFrame extends StackMapTableData {
+ ChopFrame(int frameType, int offsetDelta) {
+ super(frameType);
+ this.offsetDelta = offsetDelta;
+ }
+
+ @Override
+ void applyTo(TypeArray localTypes, TypeArray stackTypes) {
+ localTypes.setSize(localTypes.getSize()
+ - (SAME_FRAME_EXTENDED - frameType));
+ stackTypes.clear();
+ }
+
+ @Override
+ public String toString() {
+ return toString("CHOP", offsetDelta, null, null);
+ }
+ }
+
+ static class AppendFrame extends StackMapTableData {
+ final int[] locals;
+ AppendFrame(int frameType, int offsetDelta, int[] locals) {
+ super(frameType);
+ this.offsetDelta = offsetDelta;
+ this.locals = locals;
+ }
+
+ @Override
+ void applyTo(TypeArray localTypes, TypeArray stackTypes) {
+ localTypes.addAll(locals);
+ stackTypes.clear();
+ }
+
+ @Override
+ public String toString() {
+ return toString("APPEND", offsetDelta, locals, null);
+ }
+ }
+
+ static class FullFrame extends StackMapTableData {
+ final int[] locals;
+ final int[] stack;
+ FullFrame(int offsetDelta, int[] locals, int[] stack) {
+ super(FULL_FRAME);
+ this.offsetDelta = offsetDelta;
+ this.locals = locals;
+ this.stack = stack;
+ }
+
+ @Override
+ void applyTo(TypeArray localTypes, TypeArray stackTypes) {
+ localTypes.setAll(locals);
+ stackTypes.setAll(stack);
+ }
+
+ @Override
+ public String toString() {
+ return toString("FULL", offsetDelta, locals, stack);
+ }
+ }
+
+ static StackMapTableData getInstance(DataInputStream in, MethodData method)
+ throws IOException {
+ int frameType = in.readUnsignedByte();
+
+ if (frameType < SAME_FRAME_BOUND) {
+ // same_frame
+ return new SameFrame(frameType, frameType);
+ } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
+ // same_locals_1_stack_item_frame
+ // read additional single stack element
+ return new SameLocals1StackItem(frameType,
+ (frameType - SAME_FRAME_BOUND),
+ StackMapData.readTypeArray(in, 1, method));
+ } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
+ // same_locals_1_stack_item_extended
+ return new SameLocals1StackItem(frameType,
+ in.readUnsignedShort(),
+ StackMapData.readTypeArray(in, 1, method));
+ } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType && frameType < SAME_FRAME_EXTENDED) {
+ // chop_frame or same_frame_extended
+ return new ChopFrame(frameType, in.readUnsignedShort());
+ } else if (frameType == SAME_FRAME_EXTENDED) {
+ // chop_frame or same_frame_extended
+ return new SameFrame(frameType, in.readUnsignedShort());
+ } else if (SAME_FRAME_EXTENDED < frameType && frameType < FULL_FRAME) {
+ // append_frame
+ return new AppendFrame(frameType, in.readUnsignedShort(),
+ StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
+ } else if (frameType == FULL_FRAME) {
+ // full_frame
+ int offsetDelta = in.readUnsignedShort();
+ int locals_size = in.readUnsignedShort();
+ int[] locals = StackMapData.readTypeArray(in, locals_size, method);
+ int stack_size = in.readUnsignedShort();
+ int[] stack = StackMapData.readTypeArray(in, stack_size, method);
+ return new FullFrame(offsetDelta, locals, stack);
+ } else {
+ throw new ClassFormatError("unrecognized frame_type in StackMapTable");
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TrapData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/TrapData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.apidesign.javap;
+
+import java.io.*;
+
+/**
+ * Stores exception table data in code attribute.
+ *
+ * @author Sucheta Dambalkar (Adopted code from jdis)
+ */
+public final class TrapData {
+ public final short start_pc;
+ public final short end_pc;
+ public final short handler_pc;
+ public final short catch_cpx;
+ final int num;
+
+
+ /**
+ * Read and store exception table data in code attribute.
+ */
+ TrapData(DataInputStream in, int num) throws IOException {
+ this.num=num;
+ start_pc = in.readShort();
+ end_pc=in.readShort();
+ handler_pc=in.readShort();
+ catch_cpx=in.readShort();
+ }
+
+ /**
+ * returns recommended identifier
+ */
+ public String ident() {
+ return "t"+num;
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TrapDataIterator.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/TrapDataIterator.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,114 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.javap;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class TrapDataIterator {
+ private final Hashtable exStart = new Hashtable();
+ private final Hashtable exStop = new Hashtable();
+ private TrapData[] current = new TrapData[10];
+ private int currentCount;
+
+ TrapDataIterator(Vector exceptionTable) {
+ for (int i=0 ; i < exceptionTable.size(); i++) {
+ final TrapData td = (TrapData)exceptionTable.elementAt(i);
+ put(exStart, td.start_pc, td);
+ put(exStop, td.end_pc, td);
+ }
+ }
+
+ private static void put(Hashtable h, short key, TrapData td) {
+ Short s = Short.valueOf((short)key);
+ Vector v = (Vector) h.get(s);
+ if (v == null) {
+ v = new Vector(1);
+ h.put(s, v);
+ }
+ v.add(td);
+ }
+
+ private boolean processAll(Hashtable h, Short key, boolean add) {
+ boolean change = false;
+ Vector v = (Vector)h.get(key);
+ if (v != null) {
+ int s = v.size();
+ for (int i = 0; i < s; i++) {
+ TrapData td = (TrapData)v.elementAt(i);
+ if (add) {
+ add(td);
+ change = true;
+ } else {
+ remove(td);
+ change = true;
+ }
+ }
+ }
+ return change;
+ }
+
+ public boolean advanceTo(int i) {
+ Short s = Short.valueOf((short)i);
+ boolean ch1 = processAll(exStart, s, true);
+ boolean ch2 = processAll(exStop, s, false);
+ return ch1 || ch2;
+ }
+
+ public boolean useTry() {
+ return currentCount > 0;
+ }
+
+ public TrapData[] current() {
+ TrapData[] copy = new TrapData[currentCount];
+ for (int i = 0; i < currentCount; i++) {
+ copy[i] = current[i];
+ }
+ return copy;
+ }
+
+ private void add(TrapData e) {
+ if (currentCount == current.length) {
+ TrapData[] data = new TrapData[currentCount * 2];
+ for (int i = 0; i < currentCount; i++) {
+ data[i] = current[i];
+ }
+ current = data;
+ }
+ current[currentCount++] = e;
+ }
+
+ private void remove(TrapData e) {
+ if (currentCount == 0) {
+ return;
+ }
+ int from = 0;
+ while (from < currentCount) {
+ if (e == current[from++]) {
+ break;
+ }
+ }
+ while (from < currentCount) {
+ current[from - 1] = current[from];
+ current[from] = null;
+ from++;
+ }
+ currentCount--;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TypeArray.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/TypeArray.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.apidesign.javap;
+
+import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
+import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
+import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
+import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
+
+public final class TypeArray {
+ private static final int CAPACITY_INCREMENT = 16;
+
+ private int[] types;
+ private int size;
+
+ public TypeArray() {
+ }
+
+ public TypeArray(final TypeArray initialTypes) {
+ setAll(initialTypes);
+ }
+
+ public void add(final int newType) {
+ ensureCapacity(size + 1);
+ types[size++] = newType;
+ }
+
+ public void addAll(final TypeArray newTypes) {
+ addAll(newTypes.types, 0, newTypes.size);
+ }
+
+ public void addAll(final int[] newTypes) {
+ addAll(newTypes, 0, newTypes.length);
+ }
+
+ public void addAll(final int[] newTypes,
+ final int offset,
+ final int count) {
+ if (count > 0) {
+ ensureCapacity(size + count);
+ arraycopy(newTypes, offset, types, size, count);
+ size += count;
+ }
+ }
+
+ public void set(final int index, final int newType) {
+ types[index] = newType;
+ }
+
+ public void setAll(final TypeArray newTypes) {
+ setAll(newTypes.types, 0, newTypes.size);
+ }
+
+ public void setAll(final int[] newTypes) {
+ setAll(newTypes, 0, newTypes.length);
+ }
+
+ public void setAll(final int[] newTypes,
+ final int offset,
+ final int count) {
+ if (count > 0) {
+ ensureCapacity(count);
+ arraycopy(newTypes, offset, types, 0, count);
+ size = count;
+ } else {
+ clear();
+ }
+ }
+
+ public void setSize(final int newSize) {
+ if (size != newSize) {
+ ensureCapacity(newSize);
+
+ for (int i = size; i < newSize; ++i) {
+ types[i] = 0;
+ }
+ size = newSize;
+ }
+ }
+
+ public void clear() {
+ size = 0;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int get(final int index) {
+ return types[index];
+ }
+
+ public static String typeString(final int type) {
+ switch (type & 0xff) {
+ case ITEM_Bogus:
+ return "_top_";
+ case ITEM_Integer:
+ return "_int_";
+ case ITEM_Float:
+ return "_float_";
+ case ITEM_Double:
+ return "_double_";
+ case ITEM_Long:
+ return "_long_";
+ case ITEM_Null:
+ return "_null_";
+ case ITEM_InitObject: // UninitializedThis
+ return "_init_";
+ case ITEM_Object:
+ return "_object_";
+ case ITEM_NewObject: // Uninitialized
+ return "_new_";
+ default:
+ throw new IllegalArgumentException("Unknown type");
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("[");
+ if (size > 0) {
+ sb.append(typeString(types[0]));
+ for (int i = 1; i < size; ++i) {
+ sb.append(", ");
+ sb.append(typeString(types[i]));
+ }
+ }
+
+ return sb.append(']').toString();
+ }
+
+ private void ensureCapacity(final int minCapacity) {
+ if ((minCapacity == 0)
+ || (types != null) && (minCapacity <= types.length)) {
+ return;
+ }
+
+ final int newCapacity =
+ ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT)
+ * CAPACITY_INCREMENT;
+ final int[] newTypes = new int[newCapacity];
+
+ if (size > 0) {
+ arraycopy(types, 0, newTypes, 0, size);
+ }
+
+ types = newTypes;
+ }
+
+ // no System.arraycopy
+ private void arraycopy(final int[] src, final int srcPos,
+ final int[] dest, final int destPos,
+ final int length) {
+ for (int i = 0; i < length; ++i) {
+ dest[destPos + i] = src[srcPos + i];
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Vector.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javap/src/main/java/org/apidesign/javap/Vector.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,89 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.javap;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
+
+/** A JavaScript ready replacement for java.util.Vector
+ *
+ * @author Jaroslav Tulach
+ */
+@JavaScriptPrototype(prototype = "new Array" )
+final class Vector {
+ private Object[] arr;
+
+ Vector() {
+ }
+
+ Vector(int i) {
+ }
+
+ void add(Object objectType) {
+ addElement(objectType);
+ }
+ @JavaScriptBody(args = { "obj" }, body =
+ "this.push(obj);"
+ )
+ void addElement(Object obj) {
+ final int s = size();
+ setSize(s + 1);
+ setElementAt(obj, s);
+ }
+
+ @JavaScriptBody(args = { }, body =
+ "return this.length;"
+ )
+ int size() {
+ return arr == null ? 0 : arr.length;
+ }
+
+ @JavaScriptBody(args = { "newArr" }, body =
+ "for (var i = 0; i < this.length; i++) {\n"
+ + " newArr[i] = this[i];\n"
+ + "}\n")
+ void copyInto(Object[] newArr) {
+ if (arr == null) {
+ return;
+ }
+ int min = Math.min(newArr.length, arr.length);
+ for (int i = 0; i < min; i++) {
+ newArr[i] = arr[i];
+ }
+ }
+
+ @JavaScriptBody(args = { "index" }, body =
+ "return this[index];"
+ )
+ Object elementAt(int index) {
+ return arr[index];
+ }
+
+ private void setSize(int len) {
+ Object[] newArr = new Object[len];
+ copyInto(newArr);
+ arr = newArr;
+ }
+
+ @JavaScriptBody(args = { "val", "index" }, body =
+ "this[index] = val;"
+ )
+ void setElementAt(Object val, int index) {
+ arr[index] = val;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+ org.apidesign.bck2brwsr
+ javaquery
+ 0.3-SNAPSHOT
+
+ org.apidesign.bck2brwsr
+ javaquery.api
+ 0.3-SNAPSHOT
+ JavaQuery API
+ http://maven.apache.org
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.6
+
+
+
+
+
+ UTF-8
+
+
+
+ org.testng
+ testng
+ test
+
+
+ junit
+ junit
+
+
+
+
+ org.netbeans.api
+ org-openide-util-lookup
+
+
+ org.apidesign.bck2brwsr
+ core
+ 0.3-SNAPSHOT
+ jar
+
+
+ org.apidesign.bck2brwsr
+ emul
+ 0.3-SNAPSHOT
+ jar
+ runtime
+
+
+ org.apidesign.bck2brwsr
+ vm4brwsr
+ 0.3-SNAPSHOT
+ jar
+ test
+
+
+ ${project.groupId}
+ vmtest
+ ${project.version}
+ test
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,93 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import java.lang.reflect.Method;
+import org.apidesign.bck2brwsr.core.ExtraJavaScript;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/** Provides binding between models and
+ *
+ * @author Jaroslav Tulach
+ */
+@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js")
+public class Knockout {
+ /** used by tests */
+ static Knockout next;
+
+ Knockout() {
+ }
+
+ public static Knockout applyBindings(
+ Class modelClass, M model, String[] propsGettersAndSetters
+ ) {
+ Knockout bindings = next;
+ next = null;
+ if (bindings == null) {
+ bindings = new Knockout();
+ }
+ for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
+ try {
+ Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
+ bind(bindings, model, propsGettersAndSetters[i],
+ propsGettersAndSetters[i + 1],
+ propsGettersAndSetters[i + 2],
+ getter.getReturnType().isPrimitive()
+ );
+ } catch (NoSuchMethodException ex) {
+ throw new IllegalStateException(ex.getMessage());
+ }
+ }
+ applyBindings(bindings);
+ return bindings;
+ }
+
+ @JavaScriptBody(args = { "prop" }, body =
+ "this[prop].valueHasMutated();"
+ )
+ public void valueHasMutated(String prop) {
+ }
+
+
+ @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));")
+ public static void triggerEvent(String id, String ev) {
+ }
+
+ @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body =
+ "var bnd = {\n"
+ + " read: function() {\n"
+ + " var v = model[getter]();\n"
+ + " return v;\n"
+ + " },\n"
+ + " owner: bindings\n"
+ + "};\n"
+ + "if (setter != null) {\n"
+ + " bnd.write = function(val) {\n"
+ + " model[setter](primitive ? new Number(val) : val);\n"
+ + " };\n"
+ + "}\n"
+ + "bindings[prop] = ko.computed(bnd);"
+ )
+ private static void bind(
+ Object bindings, Object model, String prop, String getter, String setter, boolean primitive
+ ) {
+ }
+
+ @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
+ private static void applyBindings(Object bindings) {}
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,435 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Completion;
+import javax.annotation.processing.Completions;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.MirroredTypeException;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
+import org.apidesign.bck2brwsr.htmlpage.api.On;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+import org.apidesign.bck2brwsr.htmlpage.api.Property;
+import org.openide.util.lookup.ServiceProvider;
+
+/** Annotation processor to process an XHTML page and generate appropriate
+ * "id" file.
+ *
+ * @author Jaroslav Tulach
+ */
+@ServiceProvider(service=Processor.class)
+@SupportedAnnotationTypes({
+ "org.apidesign.bck2brwsr.htmlpage.api.Page",
+ "org.apidesign.bck2brwsr.htmlpage.api.On"
+})
+public final class PageProcessor extends AbstractProcessor {
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
+ Page p = e.getAnnotation(Page.class);
+ if (p == null) {
+ continue;
+ }
+ PackageElement pe = (PackageElement)e.getEnclosingElement();
+ String pkg = pe.getQualifiedName().toString();
+
+ ProcessPage pp;
+ try {
+ InputStream is = openStream(pkg, p.xhtml());
+ pp = ProcessPage.readPage(is);
+ is.close();
+ } catch (IOException iOException) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
+ return false;
+ }
+ Writer w;
+ String className = p.className();
+ if (className.isEmpty()) {
+ int indx = p.xhtml().indexOf('.');
+ className = p.xhtml().substring(0, indx);
+ }
+ try {
+ FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
+ w = new OutputStreamWriter(java.openOutputStream());
+ try {
+ w.append("package " + pkg + ";\n");
+ w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
+ w.append("final class ").append(className).append(" {\n");
+ w.append(" private boolean locked;\n");
+ if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
+ return false;
+ }
+ for (String id : pp.ids()) {
+ String tag = pp.tagNameForId(id);
+ String type = type(tag);
+ w.append(" ").append("public final ").
+ append(type).append(' ').append(cnstnt(id)).append(" = new ").
+ append(type).append("(\"").append(id).append("\");\n");
+ }
+ List propsGetSet = new ArrayList();
+ Map> propsDeps = new HashMap>();
+ generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps);
+ generateProperties(w, p.properties(), propsGetSet, propsDeps);
+ w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
+ if (!propsGetSet.isEmpty()) {
+ w.write("public " + className + " applyBindings() {\n");
+ w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
+ w.write(className + ".class, this, ");
+ w.write("new String[] {\n");
+ String sep = "";
+ for (String n : propsGetSet) {
+ w.write(sep);
+ if (n == null) {
+ w.write(" null");
+ } else {
+ w.write(" \"" + n + "\"");
+ }
+ sep = ",\n";
+ }
+ w.write("\n });\n return this;\n}\n");
+
+ w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
+ w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
+ w.write("}\n");
+ }
+ w.append("}\n");
+ } finally {
+ w.close();
+ }
+ } catch (IOException ex) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private InputStream openStream(String pkg, String name) throws IOException {
+ try {
+ FileObject fo = processingEnv.getFiler().getResource(
+ StandardLocation.SOURCE_PATH, pkg, name);
+ return fo.openInputStream();
+ } catch (IOException ex) {
+ return processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, name).openInputStream();
+ }
+ }
+
+ private static String type(String tag) {
+ if (tag.equals("title")) {
+ return "Title";
+ }
+ if (tag.equals("button")) {
+ return "Button";
+ }
+ if (tag.equals("input")) {
+ return "Input";
+ }
+ if (tag.equals("canvas")) {
+ return "Canvas";
+ }
+ if (tag.equals("img")) {
+ return "Image";
+ }
+ return "Element";
+ }
+
+ private static String cnstnt(String id) {
+ return id.toUpperCase(Locale.ENGLISH).replace('.', '_').replace('-', '_');
+ }
+
+ private boolean initializeOnClick(
+ String className, TypeElement type, Writer w, ProcessPage pp
+ ) throws IOException {
+ TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
+ { //for (Element clazz : pe.getEnclosedElements()) {
+ // if (clazz.getKind() != ElementKind.CLASS) {
+ // continue;
+ // }
+ w.append(" public ").append(className).append("() {\n");
+ StringBuilder dispatch = new StringBuilder();
+ int dispatchCnt = 0;
+ for (Element method : type.getEnclosedElements()) {
+ On oc = method.getAnnotation(On.class);
+ if (oc != null) {
+ for (String id : oc.id()) {
+ if (pp.tagNameForId(id) == null) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
+ return false;
+ }
+ ExecutableElement ee = (ExecutableElement)method;
+ StringBuilder params = new StringBuilder();
+ {
+ boolean first = true;
+ for (VariableElement ve : ee.getParameters()) {
+ if (!first) {
+ params.append(", ");
+ }
+ first = false;
+ if (ve.asType() == stringType) {
+ params.append('"').append(id).append('"');
+ continue;
+ }
+ String rn = ve.asType().toString();
+ int last = rn.lastIndexOf('.');
+ if (last >= 0) {
+ rn = rn.substring(last + 1);
+ }
+ if (rn.equals(className)) {
+ params.append(className).append(".this");
+ continue;
+ }
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
+ "@On method can only accept String or " + className + " arguments",
+ ee
+ );
+ return false;
+ }
+ }
+ if (!ee.getModifiers().contains(Modifier.STATIC)) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
+ return false;
+ }
+ if (ee.getModifiers().contains(Modifier.PRIVATE)) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
+ return false;
+ }
+ w.append(" OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
+ append(").perform(new OnDispatch(" + dispatchCnt + "));\n");
+
+ dispatch.
+ append(" case ").append(dispatchCnt).append(": ").
+ append(type.getSimpleName().toString()).
+ append('.').append(ee.getSimpleName()).append("(").
+ append(params).
+ append("); break;\n");
+
+ dispatchCnt++;
+ }
+ }
+ }
+ w.append(" }\n");
+ if (dispatchCnt > 0) {
+ w.append("class OnDispatch implements Runnable {\n");
+ w.append(" private final int dispatch;\n");
+ w.append(" OnDispatch(int d) { dispatch = d; }\n");
+ w.append(" public void run() {\n");
+ w.append(" switch (dispatch) {\n");
+ w.append(dispatch);
+ w.append(" }\n");
+ w.append(" }\n");
+ w.append("}\n");
+ }
+
+
+ }
+ return true;
+ }
+
+ @Override
+ public Iterable extends Completion> getCompletions(
+ Element element, AnnotationMirror annotation,
+ ExecutableElement member, String userText
+ ) {
+ if (!userText.startsWith("\"")) {
+ return Collections.emptyList();
+ }
+
+ Element cls = findClass(element);
+ Page p = cls.getAnnotation(Page.class);
+ PackageElement pe = (PackageElement) cls.getEnclosingElement();
+ String pkg = pe.getQualifiedName().toString();
+ ProcessPage pp;
+ try {
+ InputStream is = openStream(pkg, p.xhtml());
+ pp = ProcessPage.readPage(is);
+ is.close();
+ } catch (IOException iOException) {
+ return Collections.emptyList();
+ }
+
+ List cc = new ArrayList();
+ userText = userText.substring(1);
+ for (String id : pp.ids()) {
+ if (id.startsWith(userText)) {
+ cc.add(Completions.of("\"" + id + "\"", id));
+ }
+ }
+ return cc;
+ }
+
+ private static Element findClass(Element e) {
+ if (e == null) {
+ return null;
+ }
+ Page p = e.getAnnotation(Page.class);
+ if (p != null) {
+ return e;
+ }
+ return e.getEnclosingElement();
+ }
+
+ private static void generateProperties(
+ Writer w, Property[] properties, Collection props,
+ Map> deps
+ ) throws IOException {
+ for (Property p : properties) {
+ final String tn = typeName(p);
+ String[] gs = toGetSet(p.name(), tn);
+
+ w.write("private " + tn + " prop_" + p.name() + ";\n");
+ w.write("public " + tn + " " + gs[0] + "() {\n");
+ w.write(" if (locked) throw new IllegalStateException();\n");
+ w.write(" return prop_" + p.name() + ";\n");
+ w.write("}\n");
+ w.write("public void " + gs[1] + "(" + tn + " v) {\n");
+ w.write(" if (locked) throw new IllegalStateException();\n");
+ w.write(" prop_" + p.name() + " = v;\n");
+ w.write(" if (ko != null) {\n");
+ w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n");
+ final Collection dependants = deps.get(p.name());
+ if (dependants != null) {
+ for (String depProp : dependants) {
+ w.write(" ko.valueHasMutated(\"" + depProp + "\");\n");
+ }
+ }
+ w.write(" }\n");
+ w.write("}\n");
+
+ props.add(p.name());
+ props.add(gs[2]);
+ props.add(gs[3]);
+ props.add(gs[0]);
+ }
+ }
+
+ private boolean generateComputedProperties(
+ Writer w, Collection extends Element> arr, Collection props,
+ Map> deps
+ ) throws IOException {
+ for (Element e : arr) {
+ if (e.getKind() != ElementKind.METHOD) {
+ continue;
+ }
+ if (e.getAnnotation(ComputedProperty.class) == null) {
+ continue;
+ }
+ ExecutableElement ee = (ExecutableElement)e;
+ final String tn = ee.getReturnType().toString();
+ final String sn = ee.getSimpleName().toString();
+ String[] gs = toGetSet(sn, tn);
+
+ w.write("public " + tn + " " + gs[0] + "() {\n");
+ w.write(" if (locked) throw new IllegalStateException();\n");
+ int arg = 0;
+ for (VariableElement pe : ee.getParameters()) {
+ final String dn = pe.getSimpleName().toString();
+ final String dt = pe.asType().toString();
+ String[] call = toGetSet(dn, dt);
+ w.write(" " + dt + " arg" + (++arg) + " = ");
+ w.write(call[0] + "();\n");
+
+ Collection depends = deps.get(dn);
+ if (depends == null) {
+ depends = new LinkedHashSet();
+ deps.put(dn, depends);
+ }
+ depends.add(sn);
+ }
+ w.write(" try {\n");
+ w.write(" locked = true;\n");
+ w.write(" return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
+ String sep = "";
+ for (int i = 1; i <= arg; i++) {
+ w.write(sep);
+ w.write("arg" + i);
+ sep = ", ";
+ }
+ w.write(");\n");
+ w.write(" } finally {\n");
+ w.write(" locked = false;\n");
+ w.write(" }\n");
+ w.write("}\n");
+
+ props.add(e.getSimpleName().toString());
+ props.add(gs[2]);
+ props.add(null);
+ props.add(gs[0]);
+ }
+
+ return true;
+ }
+
+ private static String[] toGetSet(String name, String type) {
+ String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
+ if ("int".equals(type)) {
+ bck2brwsrType = "I";
+ }
+ if ("double".equals(type)) {
+ bck2brwsrType = "D";
+ }
+ String pref = "get";
+ if ("boolean".equals(type)) {
+ pref = "is";
+ bck2brwsrType = "Z";
+ }
+ final String nu = n.replace('.', '_');
+ return new String[]{
+ pref + n,
+ "set" + n,
+ pref + nu + "__" + bck2brwsrType,
+ "set" + nu + "__V" + bck2brwsrType
+ };
+ }
+
+ private static String typeName(Property p) {
+ try {
+ return p.type().getName();
+ } catch (MirroredTypeException ex) {
+ return ex.getTypeMirror().toString();
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,78 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+class ProcessPage {
+ private final Map ids2Elems = new TreeMap();
+
+ public Set ids() {
+ return Collections.unmodifiableSet(ids2Elems.keySet());
+ }
+
+ public String tagNameForId(String id) {
+ return ids2Elems.get(id);
+ }
+
+ public static ProcessPage readPage(InputStream is) throws IOException {
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setValidating(false);
+ f.setIgnoringComments(true);
+
+ Document doc = null;
+ try {
+ DocumentBuilder b = f.newDocumentBuilder();
+ doc = b.parse(is);
+ } catch (IOException ex) {
+ throw ex;
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ Element root = doc.getDocumentElement();
+
+ ProcessPage pp = new ProcessPage();
+ pp.seekForIds(root);
+ return pp;
+ }
+
+ private void seekForIds(Element e) {
+ String val = e.getAttribute("id");
+ if (val != null && !val.isEmpty()) {
+ String prev = ids2Elems.put(val, e.getTagName());
+ }
+ NodeList arr = e.getChildNodes();
+ for (int i = 0; i < arr.getLength(); i++) {
+ final Node n = arr.item(i);
+ if (n instanceof Element) {
+ seekForIds((Element)n);
+ }
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,36 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class Button extends Element {
+ public Button(String id) {
+ super(id);
+ }
+
+ @Override
+ void dontSubclass() {
+ }
+
+ public void setDisabled(boolean state) {
+ setAttribute(this, "disabled", state);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,61 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class Canvas extends Element {
+
+ public Canvas(String id) {
+ super(id);
+ }
+
+ public void setHeight(int height) {
+ setAttribute(this, "height", height);
+ }
+
+ public int getHeight() {
+ return (Integer) getAttribute(this, "height");
+ }
+
+ public void setWidth(int width) {
+ setAttribute(this, "width", width);
+ }
+
+ public int getWidth() {
+ return (Integer) getAttribute(this, "width");
+ }
+
+ @JavaScriptBody(
+ args = {"el"},
+ body = "var e = window.document.getElementById(el.fld_id);\n"
+ + "return e.getContext('2d');\n")
+ private native static Object getContextImpl(Canvas el);
+
+ public GraphicsContext getContext() {
+ return new GraphicsContext(getContextImpl(this));
+ }
+
+ @Override
+ void dontSubclass() {
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,38 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Can be used in classes annotated with {@link Page} annotation to
+ * define a derived property. Value of derived property is based on values
+ * of {@link Property} as enumerated by {@link Page#properties()}.
+ *
+ * The name of the derived property is the name of the method. The arguments
+ * of the method define the property names (from {@link Page#properties()} list)
+ * the value of property depends on.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.METHOD)
+public @interface ComputedProperty {
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,95 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/** Represents a generic HTML element.
+ *
+ * @author Jaroslav Tulach
+ */
+public abstract class Element {
+ private final String id;
+
+ public Element(String id) {
+ this.id = id;
+ }
+
+ /** Id of the element in the document.
+ * @return the id for this element
+ */
+ public String getId() {
+ return id;
+ }
+
+ abstract void dontSubclass();
+
+ @JavaScriptBody(
+ args={"el", "property", "value"},
+ body="var e = window.document.getElementById(el.fld_id);\n"
+ + "e[property] = value;\n"
+ )
+ static native void setAttribute(Element el, String property, Object value);
+
+ @JavaScriptBody(
+ args={"el", "property"},
+ body="var e = window.document.getElementById(el.fld_id);\n"
+ + "return e[property];\n"
+ )
+ static native Object getAttribute(Element el, String property);
+
+ @JavaScriptBody(
+ args={"el"},
+ body="return window.document.getElementById(el.fld_id);"
+ )
+ static native Object getElementById(Element el);
+
+ /** Executes given runnable when user performs a "click" on the given
+ * element.
+ * @param r the runnable to execute, never null
+ */
+ @JavaScriptBody(
+ args={ "ev", "r" },
+ body="var e = window.document.getElementById(this.fld_id);\n"
+ + "e[ev.fld_id] = function() { r.run__V(); };\n"
+ )
+ final void on(OnEvent ev, Runnable r) {
+ }
+
+ /** Shows alert message dialog in a browser.
+ * @param msg the message to show
+ */
+ @JavaScriptBody(args = "msg", body = "alert(msg);")
+ public static native void alert(String msg);
+
+ /** Generic way to query any attribute of this element.
+ * @param property name of the attribute
+ */
+ public final Object getAttribute(String property) {
+ return getAttribute(this, property);
+ }
+
+ /** Generic way to change an attribute of this element.
+ *
+ * @param property name of the attribute
+ * @param value value to associate with the attribute
+ */
+ public final void setAttribute(String property, Object value) {
+ setAttribute(this, property, value);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,335 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class GraphicsContext {
+
+ Object context;
+
+ GraphicsContext(Object contextImpl) {
+ this.context = contextImpl;
+ }
+
+ @JavaScriptBody(args = {"centerx", "centery", "radius", "startangle", "endangle", "ccw"},
+ body = "this.fld_context.arc(centerx,centery, radius, startangle, endangle,ccw);")
+ public native void arc(double centerX,
+ double centerY,
+ double startAngle,
+ double radius,
+ double endAngle,
+ boolean ccw);
+
+ @JavaScriptBody(args = {"x1", "y1", "x2", "y2", "r"},
+ body = "this.fld_context.arcTo(x1,y1,x2,y2,r);")
+ public native void arcTo(double x1,
+ double y1,
+ double x2,
+ double y2,
+ double r);
+
+ @JavaScriptBody(args = {"x", "y"},
+ body = "return this.fld_context.isPointInPath(x,y);")
+ public native boolean isPointInPath(double x, double y);
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.fill();")
+ public native void fill();
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.stroke();")
+ public native void stroke();
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.beginPath();")
+ public native void beginPath();
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.closePath();")
+ public native void closePath();
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.clip();")
+ public native void clip();
+
+ @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.moveTo(x,y);")
+ public native void moveTo(double x, double y);
+
+ @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.lineTo(x,y);")
+ public native void lineTo(double x, double y);
+
+ @JavaScriptBody(args = {"cpx", "cpy", "x", "y"}, body = "this.fld_context.quadraticCurveTo(cpx,cpy,x,y);")
+ public native void quadraticCurveTo(double cpx, double cpy, double x, double y);
+
+ @JavaScriptBody(args = {"cp1x", "cp1y", "cp2x", "cp2y", "x", "y"},
+ body = "this.fld_context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);")
+ public native void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y);
+
+ @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.fillRect(x,y,width,height);")
+ public native void fillRect(double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.strokeRect(x,y,width,height);")
+ public native void strokeRect(double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.clearRect(x,y,width,height);")
+ public native void clearRect(double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.rectect(x,y,width,height);")
+ public native void rect(double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.save();")
+ public native void save();
+
+ @JavaScriptBody(args = {}, body = "this.fld_context.restore();")
+ public native void restore();
+
+ @JavaScriptBody(args = {"angle"}, body = "this.fld_context.rotate(angle);")
+ public native void rotate(double angle);
+
+ @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.transform(a,b,c,d,e,f);")
+ public native void transform(double a, double b, double c, double d, double e, double f);
+
+ @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.setTransform(a,b,c,d,e,f);")
+ public native void setTransform(double a, double b, double c, double d, double e, double f);
+
+ @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.translate(x,y);")
+ public native void translate(double x, double y);
+
+ @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.scale(x,y);")
+ public native void scale(double x, double y);
+
+ public void drawImage(Image image, double x, double y) {
+ drawImageImpl(context, Element.getElementById(image), x, y);
+ }
+
+ public void drawImage(Image image, double x, double y, double width, double height) {
+ drawImageImpl(context, Element.getElementById(image), x, y, width, height);
+ }
+
+ public void drawImage(Image image, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height) {
+ drawImageImpl(context, Element.getElementById(image), sx, sy, sWidth, sHeight, x, y, width, height);
+ }
+
+ @JavaScriptBody(args = {"ctx", "img", "x", "y", "width", "height"}, body = "ctx.drawImage(img,x,y,width,height);")
+ private native static void drawImageImpl(Object ctx, Object img, double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {"ctx", "img", "sx", "sy", "swidth", "sheight", "x", "y", "width", "height"}, body = "ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);")
+ private native static void drawImageImpl(Object ctx, Object img, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height);
+
+ @JavaScriptBody(args = {"ctx", "img", "x", "y"}, body = "ctx.drawImage(img,x,y);")
+ private native static void drawImageImpl(Object ctx, Object img, double x, double y);
+
+ @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;")
+ public native void setFillStyle(String style);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.fillStyle;")
+ public native String getFillStyle();
+
+ public void setFillStyle(LinearGradient style) {
+ setFillStyleImpl(context, style.object());
+ }
+
+ public void setFillStyle(RadialGradient style) {
+ setFillStyleImpl(context, style.object());
+ }
+
+ public void setFillStyle(Pattern style) {
+ setFillStyleImpl(context, style.object());
+ }
+
+ @JavaScriptBody(args = {"context","obj"}, body = "context.fillStyle=obj;")
+ private native void setFillStyleImpl(Object context, Object obj);
+
+ @JavaScriptBody(args = {"style"}, body = "this.fld_context.strokeStyle=style;")
+ public native void setStrokeStyle(String style);
+
+ public void setStrokeStyle(LinearGradient style) {
+ setStrokeStyleImpl(context, style.object());
+ }
+
+ public void setStrokeStyle(RadialGradient style) {
+ setStrokeStyleImpl(context, style.object());
+ }
+
+ @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;")
+ public void setStrokeStyle(Pattern style) {
+ setStrokeStyleImpl(context, style.object());
+ }
+
+ @JavaScriptBody(args = {"context","obj"}, body = "context.strokeStyle=obj;")
+ private native void setStrokeStyleImpl(Object context, Object obj);
+
+ @JavaScriptBody(args = {"color"}, body = "this.fld_context.shadowColor=color;")
+ public native void setShadowColor(String color);
+
+ @JavaScriptBody(args = {"blur"}, body = "this.fld_context.shadowBlur=blur;")
+ public native void setShadowBlur(double blur);
+
+ @JavaScriptBody(args = {"x"}, body = "this.fld_context.shadowOffsetX=x;")
+ public native void setShadowOffsetX(double x);
+
+ @JavaScriptBody(args = {"y"}, body = "this.fld_context.shadowOffsetY=y;")
+ public native void setShadowOffsetY(double y);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.strokeStyle;")
+ public native String getStrokeStyle();
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.shadowColor;")
+ public native String getShadowColor();
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.shadowBlur;")
+ public native double getShadowBlur();
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetX;")
+ public native double getShadowOffsetX();
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetY;")
+ public native double getShadowOffsetY();
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.lineCap;")
+ public native String getLineCap();
+
+ @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineCap=style;")
+ public native void setLineCap(String style);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.lineJoin;")
+ public native String getLineJoin();
+
+ @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineJoin=style;")
+ public native void setLineJoin(String style) ;
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.lineWidth;")
+ public native double getLineWidth();
+
+ @JavaScriptBody(args = {"width"}, body = "this.fld_context.lineJoin=width;")
+ public native void setLineWidth(double width);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.miterLimit;")
+ public native double getMiterLimit();
+
+ @JavaScriptBody(args = {"limit"}, body = "this.fld_context.miterLimit=limit;")
+ public native void setMiterLimit(double limit);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.font;")
+ public native String getFont();
+
+ @JavaScriptBody(args = {"font"}, body = "this.fld_context.font=font;")
+ public native void setFont(String font);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.textAlign;")
+ public native String getTextAlign();
+
+ @JavaScriptBody(args = {"textalign"}, body = "this.fld_context.textAlign=textalign;")
+ public native void setTextAlign(String textAlign);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.textBaseline;")
+ public native String getTextBaseline();
+
+ @JavaScriptBody(args = {"textbaseline"}, body = "this.fld_context.textBaseline=textbaseline;")
+ public native void setTextBaseline(String textbaseline);
+
+ @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.fillText(text,x,y);")
+ public native void fillText(String text, double x, double y);
+
+ @JavaScriptBody(args = {"text", "x", "y", "maxwidth"}, body = "this.fld_context.fillText(text,x,y,maxwidth);")
+ public void fillText(String text, double x, double y, double maxWidth) {
+ }
+
+ public TextMetrics measureText(String text) {
+ return new TextMetrics(measureTextImpl(text));
+ }
+
+ @JavaScriptBody(args = {"text"},
+ body = "return this.fld_context.measureText(text);")
+ private native Object measureTextImpl(String text);
+
+ @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.strokeText(text,x,y);")
+ public native void strokeText(String text, double x, double y);
+
+ @JavaScriptBody(args = {"text", "x", "y", "maxWidth"}, body = "this.fld_context.strokeText(text,x,y,maxWidth);")
+ public native void strokeText(String text, double x, double y, double maxWidth) ;
+
+ public ImageData createImageData(double x, double y) {
+ return new ImageData(createImageDataImpl(x, y));
+ }
+
+ @JavaScriptBody(args = {"x", "y"},
+ body = "return this.fld_context.createImageData(x,y);")
+ private native Object createImageDataImpl(double x, double y);
+
+ public ImageData createImageData(ImageData imageData) {
+ return new ImageData(createImageDataImpl(imageData.getWidth(), imageData.getHeight()));
+ }
+
+ public ImageData getImageData(double x, double y, double width, double height) {
+ return new ImageData(getImageDataImpl(x, y, width, height));
+ }
+
+ @JavaScriptBody(args = {"x", "y", "width", "height"},
+ body = "return this.fld_context.getImageData(x,y,width,height);")
+ private native Object getImageDataImpl(double x, double y, double width, double height);
+
+ public void putImageData(ImageData imageData, double x, double y) {
+ putImageDataImpl(imageData.object(), x, y);
+ }
+
+ @JavaScriptBody(args = {"imageData", "x", "y"},
+ body = "this.fld_context.putImageData(imageData,x,y);")
+ private native void putImageDataImpl(Object imageData, double x, double y);
+
+ public void putImageData(ImageData imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight) {
+ putImageDataImpl(imageData.object(), x, y, dirtyx, dirtyy, dirtywidth, dirtyheight);
+ }
+
+ @JavaScriptBody(args = {"imageData", "x", "y", "dirtyx", "dirtyy", "dirtywidth", "dirtyheight"},
+ body = "this.fld_context.putImageData(imageData,x,y, dirtyx, dirtyy, dirtywidth,dirtyheight);")
+ private native void putImageDataImpl(Object imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight);
+
+ @JavaScriptBody(args = {"alpha"}, body = "this.fld_context.globalAlpha=alpha;")
+ public native void setGlobalAlpha(double alpha) ;
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.globalAlpha;")
+ public native double getGlobalAlpha();
+
+ @JavaScriptBody(args = {"operation"}, body = "this.fld_context.globalCompositeOperation=operation;")
+ public native void setGlobalCompositeOperation(double alpha);
+
+ @JavaScriptBody(args = {}, body = "return this.fld_context.globalCompositeOperation;")
+ public native double getGlobalCompositeOperation();
+
+ public LinearGradient createLinearGradient(double x0, double y0, double x1, double y1) {
+ return new LinearGradient(createLinearGradientImpl(context, x0, y0, x1, y1));
+ }
+
+ @JavaScriptBody(args = {"context", "x0", "y0", "x1", "y1"}, body = "return context.createLinearGradient(x0,y0,x1,y1);")
+ private native Object createLinearGradientImpl(Object context, double x0, double y0, double x1, double y1);
+
+ public Pattern createPattern(Image image, String repeat) {
+ return new Pattern(createPatternImpl(context, image, repeat));
+ }
+
+ @JavaScriptBody(args = {"context", "image", "repeat"}, body = "return context.createPattern(image, repeat);")
+ private static native Object createPatternImpl(Object context, Image image, String repeat);
+
+ public RadialGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1) {
+ return new RadialGradient(createRadialGradientImpl(context, x0, y0, r0, x1, y1, r1));
+ }
+
+ @JavaScriptBody(args = {"context", "x0", "y0", "r0", "x1", "y1", "r1"}, body = "return context.createRadialGradient(x0,y0,r0,x1,y1,r1);")
+ private static native Object createRadialGradientImpl(Object context, double x0, double y0, double r0, double x1, double y1, double r1);
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Image.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Image.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,36 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class Image extends Element{
+
+ public Image(String id) {
+ super(id);
+ }
+
+
+
+ @Override
+ void dontSubclass() {
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ImageData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ImageData.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,89 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class ImageData {
+
+ private Object imageData;
+ private Data data;
+
+ public ImageData(Object imageData) {
+ this.imageData = imageData;
+ }
+
+ public Data getData(){
+ if (data == null){
+ data = new Data(getDataImpl(imageData));
+ }
+ return data;
+ }
+
+ @JavaScriptBody(args = {"imageData"}, body = "return imageData.data")
+ public native Object getDataImpl(Object imageData);
+
+ public double getWidth() {
+ return getWidthImpl(imageData);
+ }
+
+ @JavaScriptBody(args = {"imageData"}, body = "return imagedata.width;")
+ private static native double getWidthImpl(Object imageData);
+
+ public double getHeight() {
+ return getHeightImpl(imageData);
+ }
+
+ @JavaScriptBody(args = {"imageData"}, body = "return imagedata.height;")
+ private static native double getHeightImpl(Object imageData);
+
+ Object object() {
+ return imageData;
+ }
+
+ public static class Data {
+
+ Object data;
+
+ public Data(Object data) {
+ this.data = data;
+ }
+
+ public int get(int index) {
+ return getImpl(data, index);
+ }
+
+ public void set(int index, int value) {
+ setImpl(data, index, value);
+ }
+
+ @JavaScriptBody(args = {"data", "index", "value"}, body = "data[index]=value;")
+ private static native void setImpl(Object data, int index, int value);
+
+ @JavaScriptBody(args = {"imagedata", "index"}, body = "return data[index];")
+ private static native int getImpl(Object data, int index);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,44 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class Input extends Element {
+ public Input(String id) {
+ super(id);
+ }
+
+ @Override
+ void dontSubclass() {
+ }
+
+ public void setAutocomplete(boolean state) {
+ setAttribute(this, "autocomplete", state);
+ }
+
+ public final String getValue() {
+ return (String)getAttribute(this, "value");
+ }
+
+ public final void setValue(String txt) {
+ setAttribute(this, "value", txt);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/LinearGradient.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/LinearGradient.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,45 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class LinearGradient {
+
+ private final Object gradient;
+
+ LinearGradient(Object linearGradient) {
+ this.gradient = linearGradient;
+ }
+
+ Object object() {
+ return gradient;
+ }
+
+ public void addColorStop(double position, String color) {
+ addColorStopImpl(gradient, position, color);
+ }
+
+ @JavaScriptBody(args = {"gradient", "position", "color"}, body =
+ "gradient.addColorStop(position,color)")
+ private static native void addColorStopImpl(Object gradient, double position, String color);
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/On.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/On.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,35 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Adds an onClick handler to an element identified by given id.
+ * Apply on a public static void method with no arguments.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.METHOD)
+public @interface On {
+ OnEvent event();
+ String[] id();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,43 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/** Controller created via {@link OnEvent#of(org.apidesign.bck2brwsr.htmlpage.api.Element[])}.
+ *
+ * @author Jaroslav Tulach
+ */
+public final class OnController {
+ private final Element[] arr;
+ private final OnEvent event;
+
+ OnController(OnEvent event, Element[] arr) {
+ this.event = event;
+ this.arr = arr;
+ }
+
+ /** Registers a runnable to be performed on associated {@link OnEvent}
+ * and {@link Element}.
+ *
+ * @see OnEvent#of
+ */
+ public void perform(Runnable r) {
+ for (Element e : arr) {
+ e.on(event, r);
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,103 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/** Type of events to use in connection with {@link On} annotation.
+ *
+ * @author Jaroslav Tulach
+ */
+public enum OnEvent {
+ ABORT("onabort"),
+ BLUR("onblur"),
+ CAN_PLAY("oncanplay"),
+ CAN_PLAY_THROUGH("oncanplaythrough"),
+ CHANGE("onchange"),
+ CLICK("onclick"),
+ CONTEXT_MENU("oncontextmenu"),
+ DBL_CLICK("ondblclick"),
+ DRAG("ondrag"),
+ DRAG_END("ondragend"),
+ DRAG_ENTER("ondragenter"),
+ DRAG_LEAVE("ondragleave"),
+ DRAG_OVER("ondragover"),
+ DRAG_START("ondragstart"),
+ DROP("ondrop"),
+ DURATION_CHANGE("ondurationchange"),
+ EMPTIED("onemptied"),
+ ENDED("onended"),
+ ERROR("onerror"),
+ FOCUS("onfocus"),
+ FORM_CHANGE("onformchange"),
+ FORM_INPUT("onforminput"),
+ INPUT("oninput"),
+ INVALID("oninvalid"),
+ KEY_DOWN("onkeydown"),
+ KEY_PRESS("onkeypress"),
+ KEY_UP("onkeyup"),
+ LOAD("onload"),
+ LOADED_DATA("onloadeddata"),
+ LOADED_META_DATA("onloadedmetadata"),
+ LOAD_START("onloadstart"),
+ MOUSE_DOWN("onmousedown"),
+ MOUSE_MOVE("onmousemove"),
+ MOUSE_OUT("onmouseout"),
+ MOUSE_OVER("onmouseover"),
+ MOUSE_UP("onmouseup"),
+ MOUSE_WHEEL("onmousewheel"),
+ PAUSE("onpause"),
+ PLAY("onplay"),
+ PLAYING("onplaying"),
+ PROGRESS("onprogress"),
+ RATE_CHANGE("onratechange"),
+ READY_STATE_CHANGE("onreadystatechange"),
+ SCROLL("onscroll"),
+ SEEKED("onseeked"),
+ SEEKING("onseeking"),
+ SELECT("onselect"),
+ SHOW("onshow"),
+ STALLED("onstalled"),
+ SUBMIT("onsubmit"),
+ SUSPEND("onsuspend"),
+ TIME_UPDATE("ontimeupdate"),
+ VOLUME_CHANGE("onvolumechange"),
+ WAITING("onwaiting");
+
+ final String id;
+
+ private OnEvent(String id) {
+ this.id = id;
+ }
+
+ /** The name of property this event is referenced by from an {@link Element}.
+ * For {@link OnEvent#CHANGE}, it is onchange.
+ */
+ public String getElementPropertyName() {
+ return id;
+ }
+
+ /** What should happen when this even happen on one
+ * of associated elements. Continue by calling {@link OnController#perform(java.lang.Runnable)}
+ * method.
+ *
+ * @param elmnts one or more elements
+ * @return controller with perform method.
+ */
+ public OnController of(Element... elmnts) {
+ return new OnController(this, elmnts);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,42 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Converts an XHTML page into a Java class that contains
+ * references to all IDs.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Page {
+ /** Path to the XHTML page to read in */
+ String xhtml();
+ /** Name of a Java class to generate. It will contain constants for all
+ * found elements with IDs.
+ */
+ String className() default "";
+ /** List of properties generated into the page.
+ */
+ Property[] properties() default {};
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Paint.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Paint.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,30 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class Paint {
+
+
+ String asString(){
+ return "";
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Pattern.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Pattern.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,35 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class Pattern {
+
+ private Object pattern;
+
+ public Pattern(Object pattern) {
+ this.pattern = pattern;
+ }
+
+ Object object() {
+ return pattern;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,34 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Represents a property in a generated model of an HTML
+ * {@link Page}.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({})
+public @interface Property {
+ String name();
+ Class> type();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/RadialGradient.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/RadialGradient.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,45 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class RadialGradient {
+
+ private Object gradient;
+
+ public RadialGradient(Object radialGradient) {
+ this.gradient = radialGradient;
+ }
+
+ public void addColorStop(double position, String color) {
+ addColorStopImpl(gradient, position, color);
+ }
+
+ @JavaScriptBody(args = {"gradient", "position", "color"}, body =
+ "gradient.addColorStop(position,color)")
+ private static native void addColorStopImpl(Object gradient, double position, String color);
+
+ Object object() {
+ return gradient;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/TextMetrics.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/TextMetrics.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,48 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Anton Epple
+ */
+public class TextMetrics {
+
+ private Object textMetrics;
+
+ TextMetrics(Object measureTextImpl) {
+ this.textMetrics = measureTextImpl;
+ }
+
+ @JavaScriptBody(args = {"textMetrics"}, body = "return textMetrics.width;")
+ private native double getWidth(Object textMetrics);
+
+ @JavaScriptBody(args = {"textMetrics"}, body = "return textMetrics.height;")
+ private native double getHeight(Object textMetrics);
+
+ public double getWidth() {
+ return getWidth(textMetrics);
+ }
+
+ public double getHeight() {
+ return getHeight(textMetrics);
+
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Timer.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Timer.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,59 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+import java.io.Closeable;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class Timer implements Closeable {
+ private final Object t;
+
+ private Timer(Object t) {
+ this.t = t;
+ }
+
+ /** Creates a timer that invokes provided runnable on a fixed interval
+ *
+ * @param r the runnable to execute
+ * @param time milliseconds to invoke the timer periodically
+ */
+ public static Timer create(Runnable r, int time) {
+ return new Timer(interval(r, time));
+ }
+
+ @JavaScriptBody(args = { "r", "time" }, body =
+ "return window.setInterval(function() { r.run__V(); }, time);"
+ )
+ private static native Object interval(Runnable r, int time);
+
+ @JavaScriptBody(args = { "self" }, body =
+ "window.clearInterval(self);"
+ )
+ private static native void close(Object self);
+
+ /** Cancels this timer.
+ */
+ @Override
+ public void close() {
+ close(t);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,36 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage.api;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class Title extends Element {
+ public Title(String id) {
+ super(id);
+ }
+
+ @Override
+ void dontSubclass() {
+ }
+
+ public final void setText(String text) {
+ setAttribute(this, "innerHTML", text);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,3587 @@
+// Knockout JavaScript library v2.2.1
+// (c) Steven Sanderson - http://knockoutjs.com/
+// License: MIT (http://www.opensource.org/licenses/mit-license.php)
+
+(function(){
+var DEBUG=true;
+(function(window,document,navigator,jQuery,undefined){
+!function(factory) {
+ // Support three module loading scenarios
+ if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
+ // [1] CommonJS/Node.js
+ var target = module['exports'] || exports; // module.exports is for Node.js
+ factory(target);
+ } else if (typeof define === 'function' && define['amd']) {
+ // [2] AMD anonymous module
+ define(['exports'], factory);
+ } else {
+ // [3] No module loader (plain ");
+ };
+
+ if (jQueryTmplVersion > 0) {
+ jQuery['tmpl']['tag']['ko_code'] = {
+ open: "__.push($1 || '');"
+ };
+ jQuery['tmpl']['tag']['ko_with'] = {
+ open: "with($1) {",
+ close: "} "
+ };
+ }
+ };
+
+ ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
+
+ // Use this one by default *only if jquery.tmpl is referenced*
+ var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
+ if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
+ ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
+
+ ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
+})();
+});
+})(window,document,navigator,window["jQuery"]);
+})();
\ No newline at end of file
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,62 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
+import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+import org.apidesign.bck2brwsr.htmlpage.api.Property;
+import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
+import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
+import org.apidesign.bck2brwsr.vmtest.VMTest;
+import org.testng.annotations.Factory;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={
+ @Property(name="name", type=String.class)
+})
+public class KnockoutTest {
+
+ @HtmlFragment(
+ "
Loading Bck2Brwsr's Hello World...
\n" +
+ "Your name: \n" +
+ "\n"
+ )
+ @BrwsrTest public void modifyValueAssertChangeInModel() {
+ KnockoutModel m = new KnockoutModel();
+ m.setName("Kukuc");
+ m.applyBindings();
+ assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue();
+ m.INPUT.setValue("Jardo");
+ m.triggerEvent(m.INPUT, OnEvent.CHANGE);
+ assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
+ }
+
+ @ComputedProperty
+ static String helloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+
+ @Factory
+ public static Object[] create() {
+ return VMTest.create(KnockoutTest.class);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,119 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+import org.apidesign.bck2brwsr.htmlpage.api.Property;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Page(xhtml = "Empty.html", className = "Model", properties = {
+ @Property(name = "value", type = int.class),
+ @Property(name = "unrelated", type = long.class)
+})
+public class ModelTest {
+ private Model model;
+ private static Model leakedModel;
+
+ @BeforeMethod
+ public void createModel() {
+ model = new Model();
+ }
+
+ @Test public void classGeneratedWithSetterGetter() {
+ model.setValue(10);
+ assertEquals(10, model.getValue(), "Value changed");
+ }
+
+ @Test public void computedMethod() {
+ model.setValue(4);
+ assertEquals(16, model.getPowerValue());
+ }
+
+ @Test public void derivedPropertiesAreNotified() {
+ MockKnockout my = new MockKnockout();
+ MockKnockout.next = my;
+
+ model.applyBindings();
+
+ model.setValue(33);
+
+ assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
+ assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
+ assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
+
+ my.mutated.clear();
+
+ model.setUnrelated(44);
+ assertEquals(my.mutated.size(), 1, "One property changed");
+ assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
+ }
+
+ @Test public void computedPropertyCannotWriteToModel() {
+ leakedModel = model;
+ try {
+ String res = model.getNotAllowedWrite();
+ fail("We should not be allowed to write to the model: " + res);
+ } catch (IllegalStateException ex) {
+ // OK, we can't read
+ }
+ }
+
+ @Test public void computedPropertyCannotReadToModel() {
+ leakedModel = model;
+ try {
+ String res = model.getNotAllowedRead();
+ fail("We should not be allowed to read from the model: " + res);
+ } catch (IllegalStateException ex) {
+ // OK, we can't read
+ }
+ }
+
+ @ComputedProperty
+ static int powerValue(int value) {
+ return value * value;
+ }
+
+ @ComputedProperty
+ static String notAllowedRead() {
+ return "Not allowed callback: " + leakedModel.getUnrelated();
+ }
+
+ @ComputedProperty
+ static String notAllowedWrite() {
+ leakedModel.setUnrelated(11);
+ return "Not allowed callback!";
+ }
+
+ static class MockKnockout extends Knockout {
+ List mutated = new ArrayList();
+
+ @Override
+ public void valueHasMutated(String prop) {
+ mutated.add(prop);
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,63 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
+import org.apidesign.bck2brwsr.htmlpage.api.On;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+
+/** Trivial demo for the bck2brwsr project. First of all start
+ * with your XHTML page. Include there
+ * a script that will boot Java in your browser.
+ *
+ * Then use @Page annotation to
+ * generate a Java representation of elements with IDs in that page.
+ * Depending on the type of the elements, they will have different
+ * methods (e.g. PG_TITLE has setText, etc.).
+ * Use @OnClick annotation to associate behavior
+ * with existing elements. Use the generated elements
+ * (PG_TITLE, PG_TEXT) to modify the page.
+ *
+ * Everything is type-safe. As soon as somebody modifies the page and
+ * removes the IDs or re-assigns them to wrong elements. Java compiler
+ * will emit an error.
+ *
+ * Welcome to the type-safe HTML5 world!
+ *
+ * @author Jaroslav Tulach
+ */
+@Page(xhtml="TestPage.html")
+public class PageController {
+ private static final TestPage PAGE = new TestPage();
+
+ @On(event = CLICK, id="pg.button")
+ static void updateTitle(TestPage ref) {
+ if (PAGE != ref) {
+ throw new IllegalStateException("Both references should be the same. " + ref + " != " + PAGE);
+ }
+ ref.PG_TITLE.setText("You want this window to be named " + ref.PG_TEXT.getValue());
+ }
+
+ @On(event = CLICK, id={ "pg.title", "pg.text" })
+ static void click(String id) {
+ if (!id.equals("pg.title")) {
+ throw new IllegalStateException();
+ }
+ PAGE.PG_TITLE.setText(id);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,142 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.htmlpage;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.apidesign.vm4brwsr.Bck2Brwsr;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class ProcessPageTest {
+
+
+ @Test public void findsThreeIds() throws IOException {
+ InputStream is = ProcessPageTest.class.getResourceAsStream("TestPage.html");
+ assertNotNull(is, "Sample HTML page found");
+ ProcessPage res = ProcessPage.readPage(is);
+ final Set ids = res.ids();
+ assertEquals(ids.size(), 3, "Three ids found: " + ids);
+
+ assertEquals(res.tagNameForId("pg.title"), "title");
+ assertEquals(res.tagNameForId("pg.button"), "button");
+ assertEquals(res.tagNameForId("pg.text"), "input");
+ }
+
+ @Test public void testCompileAndRunPageController() throws Exception {
+ StringBuilder sb = new StringBuilder();
+ sb.append(
+ "var window = new Object();\n"
+ + "var doc = new Object();\n"
+ + "doc.button = new Object();\n"
+ + "doc.title = new Object();\n"
+ + "doc.title.innerHTML = 'nothing';\n"
+ + "doc.text = new Object();\n"
+ + "doc.text.value = 'something';\n"
+ + "doc.getElementById = function(id) {\n"
+ + " switch(id) {\n"
+ + " case 'pg.button': return doc.button;\n"
+ + " case 'pg.title': return doc.title;\n"
+ + " case 'pg.text': return doc.text;\n"
+ + " }\n"
+ + " throw id;\n"
+ + " }\n"
+ + "\n"
+ + "function clickAndCheck() {\n"
+ + " doc.button.onclick();\n"
+ + " return doc.title.innerHTML.toString();\n"
+ + "};\n"
+ + "\n"
+ + "window.document = doc;\n"
+ );
+ Invocable i = compileClass(sb, "org/apidesign/bck2brwsr/htmlpage/PageController");
+
+ Object ret = null;
+ try {
+ ret = i.invokeFunction("clickAndCheck");
+ } catch (ScriptException ex) {
+ fail("Execution failed in " + sb, ex);
+ } catch (NoSuchMethodException ex) {
+ fail("Cannot find method in " + sb, ex);
+ }
+ assertEquals(ret, "You want this window to be named something", "We expect that the JavaCode performs all the wiring");
+ }
+
+ @Test public void clickWithArgumentCalled() throws Exception {
+ StringBuilder sb = new StringBuilder();
+ sb.append(
+ "var window = new Object();\n"
+ + "var doc = new Object();\n"
+ + "doc.button = new Object();\n"
+ + "doc.title = new Object();\n"
+ + "doc.title.innerHTML = 'nothing';\n"
+ + "doc.text = new Object();\n"
+ + "doc.text.value = 'something';\n"
+ + "doc.getElementById = function(id) {\n"
+ + " switch(id) {\n"
+ + " case 'pg.button': return doc.button;\n"
+ + " case 'pg.title': return doc.title;\n"
+ + " case 'pg.text': return doc.text;\n"
+ + " }\n"
+ + " throw id;\n"
+ + " }\n"
+ + "\n"
+ + "function clickAndCheck() {\n"
+ + " doc.title.onclick();\n"
+ + " return doc.title.innerHTML.toString();\n"
+ + "};\n"
+ + "\n"
+ + "window.document = doc;\n"
+ );
+ Invocable i = compileClass(sb,
+ "org/apidesign/bck2brwsr/htmlpage/PageController"
+ );
+
+ Object ret = null;
+ try {
+ ret = i.invokeFunction("clickAndCheck");
+ } catch (ScriptException ex) {
+ fail("Execution failed in " + sb, ex);
+ } catch (NoSuchMethodException ex) {
+ fail("Cannot find method in " + sb, ex);
+ }
+ assertEquals(ret, "pg.title", "Title has been passed to the method argument");
+ }
+
+ static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
+ if (sb == null) {
+ sb = new StringBuilder();
+ }
+ Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
+ ScriptEngineManager sem = new ScriptEngineManager();
+ ScriptEngine js = sem.getEngineByExtension("js");
+ try {
+ Object res = js.eval(sb.toString());
+ assertTrue(js instanceof Invocable, "It is invocable object: " + res);
+ return (Invocable) js;
+ } catch (ScriptException ex) {
+ fail("Could not compile:\n" + sb, ex);
+ return null;
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Empty.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Empty.html Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Empty
+
+
+ Empty page
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,25 @@
+
+
+
+
Loading Bck2Brwsr's Hello World...
+ Your name:
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,30 @@
+
+
+
+
+
+ Default Title
+
+
+ New title:
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/nbactions.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/demo-calculator-dynamic/nbactions.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,29 @@
+
+
+
+
+ run
+
+ process-classes
+ org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/demo-calculator-dynamic/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ org.apidesign.bck2brwsr
+ demo.calculator
+ 0.3-SNAPSHOT
+ jar
+
+ JavaQuery Demo - Calculator
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+ org.apidesign.bck2brwsr
+ mojo
+ 0.3-SNAPSHOT
+
+
+
+ brwsr
+
+
+
+
+ org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.7
+
+
+
+
+
+
+
+ org.apidesign.bck2brwsr
+ emul
+ 0.3-SNAPSHOT
+
+
+ org.apidesign.bck2brwsr
+ javaquery.api
+ 0.3-SNAPSHOT
+
+
+ org.testng
+ testng
+ 6.5.2
+ test
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,112 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.demo.calc;
+
+import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
+import org.apidesign.bck2brwsr.htmlpage.api.On;
+import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+import org.apidesign.bck2brwsr.htmlpage.api.Property;
+
+/** HTML5 & Java demo showing the power of
+ * annotation processors
+ * as well as other goodies.
+ *
+ * @author Jaroslav Tulach
+ */
+@Page(xhtml="Calculator.xhtml", properties = {
+ @Property(name = "memory", type = double.class),
+ @Property(name = "display", type = double.class),
+ @Property(name = "operation", type = String.class),
+ @Property(name = "hover", type = boolean.class)
+})
+public class Calc {
+ static {
+ new Calculator().applyBindings();
+ }
+
+ @On(event = CLICK, id="clear")
+ static void clear(Calculator c) {
+ c.setMemory(0);
+ c.setOperation(null);
+ c.setDisplay(0);
+ }
+
+ @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
+ static void applyOp(Calculator c, String op) {
+ c.setMemory(c.getDisplay());
+ c.setOperation(op);
+ c.setDisplay(0);
+ }
+
+ @On(event = MOUSE_OVER, id= { "result" })
+ static void attemptingIn(Calculator c, String op) {
+ c.setHover(true);
+ }
+ @On(event = MOUSE_OUT, id= { "result" })
+ static void attemptingOut(Calculator c, String op) {
+ c.setHover(false);
+ }
+
+ @On(event = CLICK, id="result")
+ static void computeTheValue(Calculator c) {
+ c.setDisplay(compute(
+ c.getOperation(),
+ c.getMemory(),
+ c.getDisplay()
+ ));
+ c.setMemory(0);
+ }
+
+ private static double compute(String op, double memory, double display) {
+ switch (op) {
+ case "plus": return memory + display;
+ case "minus": return memory - display;
+ case "mul": return memory * display;
+ case "div": return memory / display;
+ default: throw new IllegalStateException(op);
+ }
+ }
+
+ @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"})
+ static void addDigit(String digit, Calculator c) {
+ digit = digit.substring(1);
+
+ double v = c.getDisplay();
+ if (v == 0.0) {
+ c.setDisplay(Integer.parseInt(digit));
+ } else {
+ String txt = Double.toString(v);
+ if (txt.endsWith(".0")) {
+ txt = txt.substring(0, txt.length() - 2);
+ }
+ txt = txt + digit;
+ c.setDisplay(Double.parseDouble(txt));
+ }
+ }
+
+ @ComputedProperty
+ public static String displayPreview(
+ double display, boolean hover, double memory, String operation
+ ) {
+ if (!hover) {
+ return "Type numbers and perform simple operations! Press '=' to get result.";
+ }
+ return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,159 @@
+
+
+
+
+
+ Simple Calculator in HTML5 and Java
+
+
+
+
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaquery/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+ bck2brwsr
+ org.apidesign
+ 0.3-SNAPSHOT
+
+ org.apidesign.bck2brwsr
+ javaquery
+ 0.3-SNAPSHOT
+ pom
+ JavaQuery API and Demo
+
+ api
+ demo-calculator
+ demo-calculator-dynamic
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ org.apidesign
+ bck2brwsr
+ 0.3-SNAPSHOT
+
+ org.apidesign.bck2brwsr
+ launcher
+ 0.3-SNAPSHOT
+ Bck2Brwsr Launcher
+ http://maven.apache.org
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.7
+
+
+
+
+
+ UTF-8
+
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+ org.glassfish.grizzly
+ grizzly-http-server
+ 2.2.19
+
+
+ ${project.groupId}
+ vm4brwsr
+ ${project.version}
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,486 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.launcher;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apidesign.vm4brwsr.Bck2Brwsr;
+import org.glassfish.grizzly.PortRange;
+import org.glassfish.grizzly.http.server.HttpHandler;
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.http.server.NetworkListener;
+import org.glassfish.grizzly.http.server.Request;
+import org.glassfish.grizzly.http.server.Response;
+import org.glassfish.grizzly.http.server.ServerConfiguration;
+
+/**
+ * Lightweight server to launch Bck2Brwsr applications and tests.
+ * Supports execution in native browser as well as Java's internal
+ * execution engine.
+ */
+final class Bck2BrwsrLauncher extends Launcher implements Closeable {
+ private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
+ private static final MethodInvocation END = new MethodInvocation(null, null, null);
+ private Set loaders = new LinkedHashSet<>();
+ private BlockingQueue methods = new LinkedBlockingQueue<>();
+ private long timeOut;
+ private final Res resources = new Res();
+ private final String cmd;
+ private Object[] brwsr;
+ private HttpServer server;
+ private CountDownLatch wait;
+
+ public Bck2BrwsrLauncher(String cmd) {
+ this.cmd = cmd;
+ }
+
+ @Override
+ MethodInvocation addMethod(Class> clazz, String method, String html) throws IOException {
+ loaders.add(clazz.getClassLoader());
+ MethodInvocation c = new MethodInvocation(clazz.getName(), method, html);
+ methods.add(c);
+ try {
+ c.await(timeOut);
+ } catch (InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ return c;
+ }
+
+ public void setTimeout(long ms) {
+ timeOut = ms;
+ }
+
+ public void addClassLoader(ClassLoader url) {
+ this.loaders.add(url);
+ }
+
+ public void showURL(String startpage) throws IOException {
+ if (!startpage.startsWith("/")) {
+ startpage = "/" + startpage;
+ }
+ HttpServer s = initServer();
+ s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
+ try {
+ launchServerAndBrwsr(s, startpage);
+ } catch (URISyntaxException | InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ @Override
+ public void initialize() throws IOException {
+ try {
+ executeInBrowser();
+ } catch (InterruptedException ex) {
+ final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
+ iio.initCause(ex);
+ throw iio;
+ } catch (Exception ex) {
+ if (ex instanceof IOException) {
+ throw (IOException)ex;
+ }
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException)ex;
+ }
+ throw new IOException(ex);
+ }
+ }
+
+ private HttpServer initServer() {
+ HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
+
+ final ServerConfiguration conf = s.getServerConfiguration();
+ conf.addHttpHandler(new Page(resources,
+ "org/apidesign/bck2brwsr/launcher/console.xhtml",
+ "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
+ ), "/console");
+ conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
+ conf.addHttpHandler(new VMInit(), "/vm.js");
+ conf.addHttpHandler(new Classes(resources), "/classes/");
+ return s;
+ }
+
+ private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
+ wait = new CountDownLatch(1);
+ server = initServer();
+ ServerConfiguration conf = server.getServerConfiguration();
+ conf.addHttpHandler(new Page(resources,
+ "org/apidesign/bck2brwsr/launcher/harness.xhtml"
+ ), "/execute");
+ conf.addHttpHandler(new HttpHandler() {
+ int cnt;
+ List cases = new ArrayList<>();
+ @Override
+ public void service(Request request, Response response) throws Exception {
+ String id = request.getParameter("request");
+ String value = request.getParameter("result");
+
+ if (id != null && value != null) {
+ LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
+ value = decodeURL(value);
+ cases.get(Integer.parseInt(id)).result(value, null);
+ }
+
+ MethodInvocation mi = methods.take();
+ if (mi == END) {
+ response.getWriter().write("");
+ wait.countDown();
+ cnt = 0;
+ LOG.log(Level.INFO, "End of data reached. Exiting.");
+ return;
+ }
+
+ cases.add(mi);
+ final String cn = mi.className;
+ final String mn = mi.methodName;
+ LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
+ response.getWriter().write("{"
+ + "className: '" + cn + "', "
+ + "methodName: '" + mn + "', "
+ + "request: " + cnt
+ );
+ if (mi.html != null) {
+ response.getWriter().write(", html: '");
+ response.getWriter().write(encodeJSON(mi.html));
+ response.getWriter().write("'");
+ }
+ response.getWriter().write("}");
+ cnt++;
+ }
+ }, "/data");
+
+ this.brwsr = launchServerAndBrwsr(server, "/execute");
+ }
+
+ private static String encodeJSON(String in) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < in.length(); i++) {
+ char ch = in.charAt(i);
+ if (ch < 32 || ch == '\'' || ch == '"') {
+ sb.append("\\u");
+ String hs = "0000" + Integer.toHexString(ch);
+ hs = hs.substring(hs.length() - 4);
+ sb.append(hs);
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ methods.offer(END);
+ for (;;) {
+ int prev = methods.size();
+ try {
+ if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
+ break;
+ }
+ } catch (InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ if (prev == methods.size()) {
+ LOG.log(
+ Level.WARNING,
+ "Timeout and no test has been executed meanwhile (at {0}). Giving up.",
+ methods.size()
+ );
+ break;
+ }
+ LOG.log(Level.INFO,
+ "Timeout, but tests got from {0} to {1}. Trying again.",
+ new Object[]{prev, methods.size()}
+ );
+ }
+ stopServerAndBrwsr(server, brwsr);
+ }
+
+ static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
+ for (;;) {
+ int ch = is.read();
+ if (ch == -1) {
+ break;
+ }
+ if (ch == '$' && params.length > 0) {
+ int cnt = is.read() - '0';
+ if (cnt == 'U' - '0') {
+ os.write(baseURL.getBytes());
+ }
+ if (cnt >= 0 && cnt < params.length) {
+ os.write(params[cnt].getBytes());
+ }
+ } else {
+ os.write(ch);
+ }
+ }
+ }
+
+ private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
+ server.start();
+ NetworkListener listener = server.getListeners().iterator().next();
+ int port = listener.getPort();
+
+ URI uri = new URI("http://localhost:" + port + page);
+ LOG.log(Level.INFO, "Showing {0}", uri);
+ if (cmd == null) {
+ try {
+ LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
+ System.getProperty("java.vm.name"),
+ System.getProperty("java.vm.vendor"),
+ System.getProperty("java.vm.version"),
+ });
+ java.awt.Desktop.getDesktop().browse(uri);
+ LOG.log(Level.INFO, "Desktop.browse successfully finished");
+ return null;
+ } catch (UnsupportedOperationException ex) {
+ LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
+ LOG.log(Level.FINE, null, ex);
+ }
+ }
+ {
+ String cmdName = cmd == null ? "xdg-open" : cmd;
+ String[] cmdArr = {
+ cmdName, uri.toString()
+ };
+ LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
+ final Process process = Runtime.getRuntime().exec(cmdArr);
+ return new Object[] { process, null };
+ }
+ }
+
+ private static String decodeURL(String s) {
+ for (;;) {
+ int pos = s.indexOf('%');
+ if (pos == -1) {
+ return s;
+ }
+ int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
+ s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
+ }
+ }
+
+ private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
+ if (brwsr == null) {
+ return;
+ }
+ Process process = (Process)brwsr[0];
+
+ server.stop();
+ InputStream stdout = process.getInputStream();
+ InputStream stderr = process.getErrorStream();
+ drain("StdOut", stdout);
+ drain("StdErr", stderr);
+ process.destroy();
+ int res;
+ try {
+ res = process.waitFor();
+ } catch (InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ LOG.log(Level.INFO, "Exit code: {0}", res);
+
+ deleteTree((File)brwsr[1]);
+ }
+
+ private static void drain(String name, InputStream is) throws IOException {
+ int av = is.available();
+ if (av > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("v== ").append(name).append(" ==v\n");
+ while (av-- > 0) {
+ sb.append((char)is.read());
+ }
+ sb.append("\n^== ").append(name).append(" ==^");
+ LOG.log(Level.INFO, sb.toString());
+ }
+ }
+
+ private void deleteTree(File file) {
+ if (file == null) {
+ return;
+ }
+ File[] arr = file.listFiles();
+ if (arr != null) {
+ for (File s : arr) {
+ deleteTree(s);
+ }
+ }
+ file.delete();
+ }
+
+ @Override
+ public void close() throws IOException {
+ shutdown();
+ }
+
+ private class Res implements Bck2Brwsr.Resources {
+ @Override
+ public InputStream get(String resource) throws IOException {
+ for (ClassLoader l : loaders) {
+ URL u = null;
+ Enumeration en = l.getResources(resource);
+ while (en.hasMoreElements()) {
+ u = en.nextElement();
+ }
+ if (u != null) {
+ return u.openStream();
+ }
+ }
+ throw new IOException("Can't find " + resource);
+ }
+ }
+
+ private static class Page extends HttpHandler {
+ private final String resource;
+ private final String[] args;
+ private final Res res;
+
+ public Page(Res res, String resource, String... args) {
+ this.res = res;
+ this.resource = resource;
+ this.args = args.length == 0 ? new String[] { "$0" } : args;
+ }
+
+ @Override
+ public void service(Request request, Response response) throws Exception {
+ String r = resource;
+ if (r == null) {
+ r = request.getHttpHandlerPath();
+ if (r.startsWith("/")) {
+ r = r.substring(1);
+ }
+ }
+ String[] replace = {};
+ if (r.endsWith(".html")) {
+ response.setContentType("text/html");
+ LOG.info("Content type text/html");
+ replace = args;
+ }
+ if (r.endsWith(".xhtml")) {
+ response.setContentType("application/xhtml+xml");
+ LOG.info("Content type application/xhtml+xml");
+ replace = args;
+ }
+ OutputStream os = response.getOutputStream();
+ try (InputStream is = res.get(r)) {
+ copyStream(is, os, request.getRequestURL().toString(), replace);
+ } catch (IOException ex) {
+ response.setDetailMessage(ex.getLocalizedMessage());
+ response.setError();
+ response.setStatus(404);
+ }
+ }
+ }
+
+ private static class VM extends HttpHandler {
+ private final Res loader;
+
+ public VM(Res loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public void service(Request request, Response response) throws Exception {
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/javascript");
+ Bck2Brwsr.generate(response.getWriter(), loader);
+ }
+ }
+ private static class VMInit extends HttpHandler {
+ public VMInit() {
+ }
+
+ @Override
+ public void service(Request request, Response response) throws Exception {
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("text/javascript");
+ response.getWriter().append(
+ "function ldCls(res) {\n"
+ + " var request = new XMLHttpRequest();\n"
+ + " request.open('GET', '/classes/' + res, false);\n"
+ + " request.send();\n"
+ + " var arr = eval('(' + request.responseText + ')');\n"
+ + " return arr;\n"
+ + "}\n"
+ + "var vm = new bck2brwsr(ldCls);\n");
+ }
+ }
+
+ private static class Classes extends HttpHandler {
+ private final Res loader;
+
+ public Classes(Res loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public void service(Request request, Response response) throws Exception {
+ String res = request.getHttpHandlerPath();
+ if (res.startsWith("/")) {
+ res = res.substring(1);
+ }
+ try (InputStream is = loader.get(res)) {
+ response.setContentType("text/javascript");
+ Writer w = response.getWriter();
+ w.append("[");
+ for (int i = 0;; i++) {
+ int b = is.read();
+ if (b == -1) {
+ break;
+ }
+ if (i > 0) {
+ w.append(", ");
+ }
+ if (i % 20 == 0) {
+ w.write("\n");
+ }
+ if (b > 127) {
+ b = b - 256;
+ }
+ w.append(Integer.toString(b));
+ }
+ w.append("\n]");
+ } catch (IOException ex) {
+ response.setError();
+ response.setDetailMessage(ex.getMessage());
+ }
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,253 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.Enumeration;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class Console {
+ static {
+ turnAssetionStatusOn();
+ }
+
+ @JavaScriptBody(args = {"id", "attr"}, body =
+ "return window.document.getElementById(id)[attr].toString();")
+ private static native Object getAttr(String id, String attr);
+
+ @JavaScriptBody(args = {"id", "attr", "value"}, body =
+ "window.document.getElementById(id)[attr] = value;")
+ private static native void setAttr(String id, String attr, Object value);
+
+ @JavaScriptBody(args = {}, body = "return; window.close();")
+ private static native void closeWindow();
+
+ private static void log(String newText) {
+ String id = "bck2brwsr.result";
+ String attr = "value";
+ setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
+ setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
+ }
+
+ public static void execute() throws Exception {
+ String clazz = (String) getAttr("clazz", "value");
+ String method = (String) getAttr("method", "value");
+ Object res = invokeMethod(clazz, method);
+ setAttr("bck2brwsr.result", "value", res);
+ }
+
+ @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
+ + "var request = new XMLHttpRequest();\n"
+ + "request.open('GET', url, true);\n"
+ + "request.onreadystatechange = function() {\n"
+ + " if (this.readyState!==4) return;\n"
+ + " arr[0] = this.responseText;\n"
+ + " callback.run__V();\n"
+ + "};"
+ + "request.send();"
+ )
+ private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
+
+ public static void harness(String url) throws IOException {
+ log("Connecting to " + url);
+ Request r = new Request(url);
+ }
+
+ private static class Request implements Runnable {
+ private final String[] arr = { null };
+ private final String url;
+
+ private Request(String url) throws IOException {
+ this.url = url;
+ loadText(url, this, arr);
+ }
+
+ @Override
+ public void run() {
+ try {
+ String data = arr[0];
+ log("\nGot \"" + data + "\"");
+
+ if (data == null) {
+ log("Some error exiting");
+ closeWindow();
+ return;
+ }
+
+ if (data.isEmpty()) {
+ log("No data, exiting");
+ closeWindow();
+ return;
+ }
+
+ Case c = Case.parseData(data);
+ if (c.getHtmlFragment() != null) {
+ setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
+ }
+ log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
+
+ Object result = invokeMethod(c.getClassName(), c.getMethodName());
+
+ setAttr("bck2brwsr.fragment", "innerHTML", "");
+ log("Result: " + result);
+
+ result = encodeURL("" + result);
+
+ log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
+ String u = url + "?request=" + c.getRequestId() + "&result=" + result;
+
+ loadText(u, this, arr);
+
+ } catch (Exception ex) {
+ log(ex.getMessage());
+ }
+ }
+ }
+
+ private static String encodeURL(String r) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < r.length(); i++) {
+ int ch = r.charAt(i);
+ if (ch < 32 || ch == '%' || ch == '+') {
+ sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
+ } else {
+ if (ch == 32) {
+ sb.append("+");
+ } else {
+ sb.append((char)ch);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
+ final Object r = invokeMethod(clazz, method);
+ return r == null ? "null" : r.toString().toString();
+ }
+
+ /** Helper method that inspects the classpath and loads given resource
+ * (usually a class file). Used while running tests in Rhino.
+ *
+ * @param name resource name to find
+ * @return the array of bytes in the given resource
+ * @throws IOException I/O in case something goes wrong
+ */
+ public static byte[] read(String name) throws IOException {
+ URL u = null;
+ Enumeration en = Console.class.getClassLoader().getResources(name);
+ while (en.hasMoreElements()) {
+ u = en.nextElement();
+ }
+ if (u == null) {
+ throw new IOException("Can't find " + name);
+ }
+ try (InputStream is = u.openStream()) {
+ byte[] arr;
+ arr = new byte[is.available()];
+ int offset = 0;
+ while (offset < arr.length) {
+ int len = is.read(arr, offset, arr.length - offset);
+ if (len == -1) {
+ throw new IOException("Can't read " + name);
+ }
+ offset += len;
+ }
+ return arr;
+ }
+ }
+
+ private static Object invokeMethod(String clazz, String method)
+ throws ClassNotFoundException, InvocationTargetException,
+ SecurityException, IllegalAccessException, IllegalArgumentException,
+ InstantiationException {
+ Method found = null;
+ Class> c = Class.forName(clazz);
+ for (Method m : c.getMethods()) {
+ if (m.getName().equals(method)) {
+ found = m;
+ }
+ }
+ Object res;
+ if (found != null) {
+ try {
+ if ((found.getModifiers() & Modifier.STATIC) != 0) {
+ res = found.invoke(null);
+ } else {
+ res = found.invoke(c.newInstance());
+ }
+ } catch (Throwable ex) {
+ res = ex.getClass().getName() + ":" + ex.getMessage();
+ }
+ } else {
+ res = "Can't find method " + method + " in " + clazz;
+ }
+ return res;
+ }
+
+ @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
+ private static void turnAssetionStatusOn() {
+ }
+
+ private static final class Case {
+ private final Object data;
+
+ private Case(Object data) {
+ this.data = data;
+ }
+
+ public static Case parseData(String s) {
+ return new Case(toJSON(s));
+ }
+
+ public String getMethodName() {
+ return value("methodName", data);
+ }
+
+ public String getClassName() {
+ return value("className", data);
+ }
+
+ public String getRequestId() {
+ return value("request", data);
+ }
+
+ public String getHtmlFragment() {
+ return value("html", data);
+ }
+
+ @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
+ private static native Object toJSON(String s);
+
+ @JavaScriptBody(args = {"p", "d"}, body =
+ "var v = d[p];\n"
+ + "if (typeof v === 'undefined') return null;\n"
+ + "return v.toString();"
+ )
+ private static native String value(String p, Object d);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,126 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.apidesign.vm4brwsr.Bck2Brwsr;
+
+/**
+ * Tests execution in Java's internal scripting engine.
+ */
+final class JSLauncher extends Launcher {
+ private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
+ private Set loaders = new LinkedHashSet<>();
+ private final Res resources = new Res();
+ private Invocable code;
+ private StringBuilder codeSeq;
+ private Object console;
+
+
+ @Override MethodInvocation addMethod(Class> clazz, String method, String html) {
+ loaders.add(clazz.getClassLoader());
+ MethodInvocation mi = new MethodInvocation(clazz.getName(), method, html);
+ try {
+ mi.result(code.invokeMethod(
+ console,
+ "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
+ mi.className, mi.methodName).toString(), null);
+ } catch (ScriptException | NoSuchMethodException ex) {
+ mi.result(null, ex);
+ }
+ return mi;
+ }
+
+ public void addClassLoader(ClassLoader url) {
+ this.loaders.add(url);
+ }
+
+ @Override
+ public void initialize() throws IOException {
+ try {
+ initRhino();
+ } catch (Exception ex) {
+ if (ex instanceof IOException) {
+ throw (IOException)ex;
+ }
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException)ex;
+ }
+ throw new IOException(ex);
+ }
+ }
+
+ private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
+ StringBuilder sb = new StringBuilder();
+ Bck2Brwsr.generate(sb, new Res());
+
+ ScriptEngineManager sem = new ScriptEngineManager();
+ ScriptEngine mach = sem.getEngineByExtension("js");
+
+ sb.append(
+ "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
+ + "\nfunction initVM() { return vm; };"
+ + "\n");
+
+ Object res = mach.eval(sb.toString());
+ if (!(mach instanceof Invocable)) {
+ throw new IOException("It is invocable object: " + res);
+ }
+ code = (Invocable) mach;
+ codeSeq = sb;
+
+ Object vm = code.invokeFunction("initVM");
+ console = code.invokeMethod(vm, "loadClass", Console.class.getName());
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ }
+
+ @Override
+ public String toString() {
+ return codeSeq.toString();
+ }
+
+ private class Res implements Bck2Brwsr.Resources {
+ @Override
+ public InputStream get(String resource) throws IOException {
+ for (ClassLoader l : loaders) {
+ URL u = null;
+ Enumeration en = l.getResources(resource);
+ while (en.hasMoreElements()) {
+ u = en.nextElement();
+ }
+ if (u != null) {
+ return u.openStream();
+ }
+ }
+ throw new IOException("Can't find " + resource);
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,63 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.launcher;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.URLClassLoader;
+import org.apidesign.vm4brwsr.Bck2Brwsr;
+
+/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
+ * Either in JavaScript engine, or in external browser.
+ *
+ * @author Jaroslav Tulach
+ */
+public abstract class Launcher {
+
+ Launcher() {
+ }
+
+ abstract MethodInvocation addMethod(Class> clazz, String method, String html) throws IOException;
+
+ public abstract void initialize() throws IOException;
+ public abstract void shutdown() throws IOException;
+ public MethodInvocation invokeMethod(Class> clazz, String method, String html) throws IOException {
+ return addMethod(clazz, method, html);
+ }
+
+
+
+ public static Launcher createJavaScript() {
+ final JSLauncher l = new JSLauncher();
+ l.addClassLoader(Bck2Brwsr.class.getClassLoader());
+ return l;
+ }
+
+ public static Launcher createBrowser(String cmd) {
+ final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
+ l.addClassLoader(Bck2Brwsr.class.getClassLoader());
+ l.setTimeout(180000);
+ return l;
+ }
+ public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
+ Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
+ l.addClassLoader(classes);
+ l.showURL(startpage);
+ return l;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,59 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.launcher;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class MethodInvocation {
+ final CountDownLatch wait = new CountDownLatch(1);
+ final String className;
+ final String methodName;
+ final String html;
+ private String result;
+ private Throwable exception;
+
+ MethodInvocation(String className, String methodName, String html) {
+ this.className = className;
+ this.methodName = methodName;
+ this.html = html;
+ }
+
+ void await(long timeOut) throws InterruptedException {
+ wait.await(timeOut, TimeUnit.MILLISECONDS);
+ }
+
+ void result(String r, Throwable e) {
+ this.result = r;
+ this.exception = e;
+ wait.countDown();
+ }
+
+ @Override
+ public String toString() {
+ if (exception != null) {
+ return exception.toString();
+ }
+ return result;
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,41 @@
+
+
+
+
+
+ Bck2Brwsr Harness
+
+
+
+
+
+
Bck2Brwsr Execution Harness
+
+
+
+
+
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,86 @@
+
+
+ 4.0.0
+
+ org.apidesign
+ bck2brwsr
+ 0.3-SNAPSHOT
+
+ org.apidesign.bck2brwsr
+ mojo
+ 0.3-SNAPSHOT
+ maven-plugin
+ Bck2Brwsr Maven Project
+ http://maven.apache.org
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ 3.1
+
+
+ java-annotations
+
+ true
+
+
+
+ mojo-descriptor
+ process-classes
+
+ descriptor
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.6
+
+
+
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 3.0.4
+ jar
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ 3.0
+ jar
+
+
+ ${project.groupId}
+ vm4brwsr
+ 0.3-SNAPSHOT
+
+
+ emul
+ org.apidesign.bck2brwsr
+
+
+
+
+ org.apache.maven
+ maven-core
+ 3.0.2
+ jar
+
+
+ ${project.groupId}
+ launcher
+ ${project.version}
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,122 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.mojo;
+
+import org.apache.maven.plugin.AbstractMojo;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apidesign.vm4brwsr.Bck2Brwsr;
+
+/** Compiles classes into JavaScript. */
+@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
+public class Bck2BrswrMojo extends AbstractMojo {
+ public Bck2BrswrMojo() {
+ }
+ /** Root of the class files */
+ @Parameter(defaultValue="${project.build.directory}/classes")
+ private File classes;
+ /** File to generate. Defaults bootjava.js in the first non-empty
+ package under the classes directory */
+ @Parameter
+ private File javascript;
+
+ @Parameter(defaultValue="${project}")
+ private MavenProject prj;
+
+
+
+ @Override
+ public void execute() throws MojoExecutionException {
+ if (!classes.isDirectory()) {
+ throw new MojoExecutionException("Can't find " + classes);
+ }
+
+ if (javascript == null) {
+ javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
+ }
+
+ List arr = new ArrayList();
+ long newest = collectAllClasses("", classes, arr);
+
+ if (javascript.lastModified() > newest) {
+ return;
+ }
+
+ try {
+ URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
+ FileWriter w = new FileWriter(javascript);
+ Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
+ w.close();
+ } catch (IOException ex) {
+ throw new MojoExecutionException("Can't compile", ex);
+ }
+ }
+
+ private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
+ if (!dir.isDirectory()) {
+ throw new MojoExecutionException("Not a directory " + dir);
+ }
+ File[] arr = dir.listFiles();
+ if (arr.length == 1 && arr[0].isDirectory()) {
+ return findNonEmptyFolder(arr[0]);
+ }
+ return dir;
+ }
+
+ private static long collectAllClasses(String prefix, File toCheck, List arr) {
+ File[] files = toCheck.listFiles();
+ if (files != null) {
+ long newest = 0L;
+ for (File f : files) {
+ long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
+ if (newest < lastModified) {
+ newest = lastModified;
+ }
+ }
+ return newest;
+ } else if (toCheck.getName().endsWith(".class")) {
+ arr.add(prefix.substring(0, prefix.length() - 7));
+ return toCheck.lastModified();
+ } else {
+ return 0L;
+ }
+ }
+
+ private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException {
+ List arr = new ArrayList();
+ arr.add(root.toURI().toURL());
+ for (Artifact a : deps) {
+ arr.add(a.getFile().toURI().toURL());
+ }
+ return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader());
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,92 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.bck2brwsr.mojo;
+
+import java.io.Closeable;
+import org.apache.maven.plugin.AbstractMojo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apidesign.bck2brwsr.launcher.Launcher;
+
+/** Executes given HTML page in a browser. */
+@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
+public class BrswrMojo extends AbstractMojo {
+ public BrswrMojo() {
+ }
+ /** Resource to show as initial page */
+ @Parameter
+ private String startpage;
+
+ @Parameter(defaultValue="${project}")
+ private MavenProject prj;
+
+ /** Root of the class files */
+ @Parameter(defaultValue="${project.build.directory}/classes")
+ private File classes;
+
+ @Override
+ public void execute() throws MojoExecutionException {
+ if (startpage == null) {
+ throw new MojoExecutionException("You have to provide a start page");
+ }
+
+ try {
+ URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
+
+ Closeable httpServer;
+ try {
+ httpServer = Launcher.showURL(url, startpage());
+ } catch (Exception ex) {
+ throw new MojoExecutionException("Can't open " + startpage(), ex);
+ }
+ System.in.read();
+ httpServer.close();
+ } catch (IOException ex) {
+ throw new MojoExecutionException("Can't show the browser", ex);
+ }
+ }
+
+ private String startpage() {
+ return startpage;
+ }
+
+ private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException {
+ List arr = new ArrayList();
+ arr.add(root.toURI().toURL());
+ for (Artifact a : deps) {
+ final File f = a.getFile();
+ if (f != null) {
+ arr.add(f.toURI().toURL());
+ }
+ }
+ return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/META-INF/maven/archetype-metadata.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,48 @@
+
+
+
+
+
+ src/main/java
+
+ **/App.java
+
+
+
+ src/main/resources
+
+ **/*.xhtml
+
+
+
+ src/test/java
+
+ **/*Test.java
+
+
+
+
+
+ nbactions.xml
+
+
+
+
\ No newline at end of file
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/nbactions.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/nbactions.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,10 @@
+
+
+
+ run
+
+ process-classes
+ org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,69 @@
+
+
+ 4.0.0
+
+ ${groupId}
+ ${artifactId}
+ ${version}
+ jar
+
+ ${artifactId}
+
+
+ UTF-8
+
+
+
+
+ org.apidesign.bck2brwsr
+ mojo
+ 0.3-SNAPSHOT
+
+
+
+ brwsr
+
+
+
+
+ ${package.replace('.','/')}/index.xhtml
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.7
+
+
+
+
+
+
+
+ org.apidesign.bck2brwsr
+ emul
+ 0.3-SNAPSHOT
+
+
+ org.apidesign.bck2brwsr
+ javaquery.api
+ 0.3-SNAPSHOT
+
+
+ org.testng
+ testng
+ 6.5.2
+ test
+
+
+ ${project.groupId}
+ vmtest
+ 0.3-SNAPSHOT
+ test
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/main/java/App.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,34 @@
+package ${package};
+
+import org.apidesign.bck2brwsr.htmlpage.api.*;
+import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
+import org.apidesign.bck2brwsr.htmlpage.api.Page;
+import org.apidesign.bck2brwsr.htmlpage.api.Property;
+import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
+
+/** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
+ * Use this class to define behavior of the elements.
+ */
+@Page(xhtml="index.xhtml", className="Index", properties={
+ @Property(name="name", type=String.class)
+})
+public class App {
+ static {
+ Index model = new Index();
+ model.setName("World");
+ model.applyBindings();
+ }
+
+ @On(event = CLICK, id="hello")
+ static void hello(Index m) {
+ GraphicsContext g = m.CANVAS.getContext();
+ g.clearRect(0, 0, 1000, 1000);
+ g.setFont("italic 40px Calibri");
+ g.fillText(m.getHelloMessage(), 10, 40);
+ }
+
+ @ComputedProperty
+ static String helloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,22 @@
+
+
+
+
+ Bck2Brwsr's Hello World
+
+
+
Loading Bck2Brwsr's Hello World...
+ Your name:
+
+
+
+
+
+
+
+
+
+
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,26 @@
+package ${package};
+
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
+ * as it does not reference any HTML elements or browser functionality. Just
+ * operates on the page model.
+ *
+ * @author Jaroslav Tulach
+ */
+public class AppTest {
+ private Index model;
+
+
+ @BeforeMethod
+ public void initModel() {
+ model = new Index().applyBindings();
+ }
+
+ @Test public void testHelloMessage() {
+ model.setName("Joe");
+ assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,40 @@
+package ${package};
+
+import org.apidesign.bck2brwsr.vmtest.Compare;
+import org.apidesign.bck2brwsr.vmtest.VMTest;
+import org.testng.annotations.Factory;
+
+/** Bck2brwsr cares about compatibility with real Java. Whatever API is
+ * supported by bck2brwsr, it needs to behave the same way as when running
+ * in HotSpot VM.
+ *
+ * There can be bugs, however. To help us fix them, we kindly ask you to
+ * write an "inconsistency" test. A test that compares behavior of the API
+ * between real VM and bck2brwsr VM. This class is skeleton of such test.
+ *
+ * @author Jaroslav Tulach
+ */
+public class InconsistencyTest {
+ /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
+ * Make calls to an API that behaves strangely, return some result at
+ * the end. No need to use any assert.
+ *
+ * @return value to compare between HotSpot and bck2brwsr
+ */
+ @Compare
+ public int checkStringHashCode() throws Exception {
+ return "Is string hashCode the same?".hashCode();
+ }
+
+ /** Factory method that creates a three tests for each method annotated with
+ * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
+ * HotSpot, one in Rhino and the last one compares the results.
+ *
+ * @see org.apidesign.bck2brwsr.vmtest.VMTest
+ */
+ @Factory
+ public static Object[] create() {
+ return VMTest.create(InconsistencyTest.class);
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,46 @@
+package ${package};
+
+import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
+import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
+import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
+import org.apidesign.bck2brwsr.vmtest.VMTest;
+import org.testng.annotations.Factory;
+
+/** Sometimes it is useful to run tests inside of the real browser.
+ * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
+ * and that is it. If your code references elements on the HTML page,
+ * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
+ * will be made available on the page before your test starts.
+ *
+ * @author Jaroslav Tulach
+ */
+public class IntegrationTest {
+
+ /** Write to testing code here. Use assert (but not TestNG's
+ * Assert, as TestNG is not compiled with target 1.6 yet).
+ */
+ @HtmlFragment(
+ "
Loading Bck2Brwsr's Hello World...
\n" +
+ "Your name: \n" +
+ "\n" +
+ "
\n" +
+ " \n" +
+ "
\n"
+ )
+ @BrwsrTest
+ public void modifyValueAssertChangeInModel() {
+ Index m = new Index();
+ m.setName("Joe Hacker");
+ m.applyBindings();
+ assert "Joe Hacker".equals(m.INPUT.getValue()) : "Value is really Joe Hacker: " + m.INPUT.getValue();
+ m.INPUT.setValue("Happy Joe");
+ m.triggerEvent(m.INPUT, OnEvent.CHANGE);
+ assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
+ }
+
+ @Factory
+ public static Object[] create() {
+ return VMTest.create(IntegrationTest.class);
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a pom.xml
--- a/pom.xml Thu Oct 11 06:15:22 2012 -0700
+++ b/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -3,14 +3,20 @@
4.0.0org.apidesignbck2brwsr
- 1.0-SNAPSHOT
+ 0.3-SNAPSHOTpomBack 2 Browser
- vm
- htmlpage
+ vmemulcore
+ dew
+ mojo
+ javaquery
+ javap
+ benchmarks
+ launcher
+ vmtest
@@ -43,6 +49,40 @@
+
+
+
+ false
+ com.mycila.maven-license-plugin
+ maven-license-plugin
+ 1.9.0
+
+
+ blah
+
+ check
+
+
+
+
+ true
+ ${basedir}
+ COPYING
+ true
+
+ emul/**
+ javap/**
+ *
+ .*/**
+ mojo/src/main/resources/archetype-resources/**
+ dew/src/main/resources/org/apidesign/bck2brwsr/dew/**
+ vmtest/src/test/resources/**
+ javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js
+
+
+
+
+
@@ -75,4 +115,4 @@
COPYING
-
\ No newline at end of file
+
diff -r 029e6eed60e9 -r 388e48c0a37a vm/nb-configuration.xml
--- a/vm/nb-configuration.xml Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-
-
-
-
-
-
- all
-
-
diff -r 029e6eed60e9 -r 388e48c0a37a vm/pom.xml
--- a/vm/pom.xml Thu Oct 11 06:15:22 2012 -0700
+++ b/vm/pom.xml Wed Jan 23 20:16:48 2013 +0100
@@ -4,12 +4,12 @@
org.apidesignbck2brwsr
- 1.0-SNAPSHOT
+ 0.3-SNAPSHOTorg.apidesign.bck2brwsrvm4brwsr
- 0.1-SNAPSHOT
+ 0.3-SNAPSHOTjarJava VM for Browser
@@ -54,19 +54,20 @@
- org.apidesign.vm4brwsr.GenJS
+ org.apidesign.vm4brwsr.Main
-
- com.mycila.maven-license-plugin
- maven-license-plugin
- 1.9.0
-
- src/header.txt
-
-
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.7
+
+
@@ -82,21 +83,21 @@
- org.netbeans.api
- org-netbeans-modules-classfile
+ ${project.groupId}
+ core
+ 0.3-SNAPSHOTjar
- org.apidesign.bck2brwsr
- core
- 1.0-SNAPSHOT
- jar
+ ${project.groupId}
+ emul
+ 0.3-SNAPSHOT
+ test
- org.apidesign.bck2brwsr
- emul
- 1.0-SNAPSHOT
- test
+ ${project.groupId}
+ javap
+ 0.3-SNAPSHOT
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/header.txt
--- a/vm/src/header.txt Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-Java 4 Browser Bytecode Translator
-Copyright (C) 2012-${year} Jaroslav Tulach
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 2 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. Look for COPYING file in the top folder.
-If not, see http://opensource.org/licenses/GPL-2.0.
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,106 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+/** Build your own virtual machine! Use methods in this class to generate
+ * a skeleton JVM in JavaScript that contains pre-compiled classes of your
+ * choice. The generated script defines one JavaScript method that can
+ * be used to bootstrap and load the virtual machine:
+ * var vm = bck2brwsr();
+ * var main = vm.loadClass('org.your.pkg.Main');
+ * main.main__V_3Ljava_lang_String_2(null);
+ *
+ * In case one wants to initialize the virtual machine with ability to
+ * load classes lazily when needed, one can provide a loader function to
+ * when creating the virtual machine:
+ * var vm = bck2brwsr(function(resource) {
+ * return null; // byte[] for the resource
+ * });
+ *
+ * In this scenario, when a request for an unknown class is made, the loader
+ * function is asked for its byte code and the system dynamically transforms
+ * it to JavaScript.
+ *
+ * @author Jaroslav Tulach
+ */
+public final class Bck2Brwsr {
+ private Bck2Brwsr() {
+ }
+
+ /** Generates virtual machine from bytes served by a resources
+ * provider.
+ *
+ * @param out the output to write the generated JavaScript to
+ * @param resources provider of class files to use
+ * @param classes additional classes to include in the generated script
+ * @throws IOException I/O exception can be thrown when something goes wrong
+ */
+ public static void generate(Appendable out, Resources resources, String... classes) throws IOException {
+ StringArray arr = StringArray.asList(classes);
+ arr.add(VM.class.getName().replace('.', '/'));
+ VM.compile(resources, out, arr);
+ }
+
+ /** Generates virtual machine from bytes served by a class loader.
+ *
+ * @param out the output to write the generated JavaScript to
+ * @param loader class loader to load needed classes from
+ * @param classes additional classes to include in the generated script
+ * @throws IOException I/O exception can be thrown when something goes wrong
+ */
+ public static void generate(Appendable out, final ClassLoader loader, String... classes) throws IOException {
+ class R implements Resources {
+ @Override
+ public InputStream get(String name) throws IOException {
+ Enumeration en = loader.getResources(name);
+ URL u = null;
+ while (en.hasMoreElements()) {
+ u = en.nextElement();
+ }
+ if (u == null) {
+ throw new IOException("Can't find " + name);
+ }
+ return u.openStream();
+ }
+ }
+ generate(out, new R(), classes);
+ }
+
+ /** Provider of resources (classes and other files). The
+ * {@link #generate(java.lang.Appendable, org.apidesign.vm4brwsr.Bck2Brwsr.Resources, java.lang.String[])
+ * generator method} will call back here for all classes needed during
+ * translation to JavaScript.
+ */
+ public interface Resources {
+ /** Loads given resource (class or other file like image). The
+ * resource name to load bytes for the {@link String} class
+ * would be "java/lang/String.class".
+ *
+ * @param resource path to resource to load
+ * @return the input stream for the resource
+ * @throws IOException can be thrown if the loading fails on some error
+ * or the file cannot be found
+ */
+ public InputStream get(String resource) throws IOException;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
--- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Oct 11 06:15:22 2012 -0700
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 23 20:16:48 2013 +0100
@@ -1,698 +1,1179 @@
-/*
-Java 4 Browser Bytecode Translator
-Copyright (C) 2012-2012 Jaroslav Tulach
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 2 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. Look for COPYING file in the top folder.
-If not, see http://opensource.org/licenses/GPL-2.0.
-*/
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
package org.apidesign.vm4brwsr;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.apidesign.bck2brwsr.core.ExtraJavaScript;
import org.apidesign.bck2brwsr.core.JavaScriptBody;
-import org.netbeans.modules.classfile.Annotation;
-import org.netbeans.modules.classfile.AnnotationComponent;
-import org.netbeans.modules.classfile.ArrayElementValue;
-import static org.netbeans.modules.classfile.ByteCodes.*;
-import org.netbeans.modules.classfile.CPClassInfo;
-import org.netbeans.modules.classfile.CPEntry;
-import org.netbeans.modules.classfile.CPFieldInfo;
-import org.netbeans.modules.classfile.CPMethodInfo;
-import org.netbeans.modules.classfile.CPStringInfo;
-import org.netbeans.modules.classfile.ClassFile;
-import org.netbeans.modules.classfile.ClassName;
-import org.netbeans.modules.classfile.Code;
-import org.netbeans.modules.classfile.ElementValue;
-import org.netbeans.modules.classfile.Method;
-import org.netbeans.modules.classfile.Parameter;
-import org.netbeans.modules.classfile.PrimitiveElementValue;
-import org.netbeans.modules.classfile.Variable;
+import org.apidesign.javap.AnnotationParser;
+import org.apidesign.javap.ClassData;
+import org.apidesign.javap.FieldData;
+import org.apidesign.javap.MethodData;
+import org.apidesign.javap.StackMapIterator;
+import static org.apidesign.javap.RuntimeConstants.*;
+import org.apidesign.javap.TrapData;
+import org.apidesign.javap.TrapDataIterator;
/** Translator of the code inside class files to JavaScript.
*
* @author Jaroslav Tulach
*/
-public final class ByteCodeToJavaScript {
- private final ClassFile jc;
- private final Appendable out;
- private final Collection super String> references;
+abstract class ByteCodeToJavaScript {
+ private ClassData jc;
+ final Appendable out;
- private ByteCodeToJavaScript(
- ClassFile jc, Appendable out, Collection super String> references
- ) {
- this.jc = jc;
+ protected ByteCodeToJavaScript(Appendable out) {
this.out = out;
- this.references = references;
+ }
+
+ /* Collects additional required resources.
+ *
+ * @param internalClassName classes that were referenced and should be loaded in order the
+ * generated JavaScript code works properly. The names are in internal
+ * JVM form so String is java/lang/String.
+ */
+ protected abstract boolean requireReference(String internalClassName);
+
+ /*
+ * @param resourcePath name of resources to read
+ */
+ protected abstract void requireScript(String resourcePath) throws IOException;
+
+ /** Allows subclasses to redefine what field a function representing a
+ * class gets assigned. By default it returns the suggested name followed
+ * by " = ";
+ *
+ * @param className suggested name of the class
+ */
+ /* protected */ String assignClass(String className) {
+ return className + " = ";
+ }
+ /* protected */ String accessClass(String classOperation) {
+ return classOperation;
+ }
+
+ /** Prints out a debug message.
+ *
+ * @param msg the message
+ * @return true if the message has been printed
+ * @throws IOException
+ */
+ boolean debug(String msg) throws IOException {
+ out.append(msg);
+ return true;
}
/**
* Converts a given class file to a JavaScript version.
*
* @param classFile input stream with code of the .class file
- * @param out a {@link StringBuilder} or similar to generate the output to
- * @param references a write only collection where the system adds list of
- * other classes that were referenced and should be loaded in order the
- * generated JavaScript code works properly. The names are in internal
- * JVM form so String is java/lang/String. Can be null
- * if one is not interested in knowing references
- * @param scripts write only collection with names of resources to read
* @return the initialization code for this class, if any. Otherwise null
*
* @throws IOException if something goes wrong during read or write or translating
*/
- public static String compile(
- InputStream classFile, Appendable out,
- Collection super String> references,
- Collection super String> scripts
- ) throws IOException {
- ClassFile jc = new ClassFile(classFile, true);
- final ClassName extraAnn = ClassName.getClassName(ExtraJavaScript.class.getName().replace('.', '/'));
- Annotation a = jc.getAnnotation(extraAnn);
- if (a != null) {
- final ElementValue annVal = a.getComponent("resource").getValue();
- String res = ((PrimitiveElementValue)annVal).getValue().getValue().toString();
- scripts.add(res);
- final AnnotationComponent process = a.getComponent("processByteCode");
- if (process != null && "const=0".equals(process.getValue().toString())) {
+ public String compile(InputStream classFile) throws IOException {
+ this.jc = new ClassData(classFile);
+ if (jc.getMajor_version() < 50) {
+ throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "."
+ + jc.getMinor_version() + " - recompile with -target 1.6 (at least)."
+ );
+ }
+ byte[] arrData = jc.findAnnotationData(true);
+ String[] arr = findAnnotation(arrData, jc,
+ "org.apidesign.bck2brwsr.core.ExtraJavaScript",
+ "resource", "processByteCode"
+ );
+ if (arr != null) {
+ requireScript(arr[0]);
+ if ("0".equals(arr[1])) {
return null;
}
}
-
- ByteCodeToJavaScript compiler = new ByteCodeToJavaScript(
- jc, out, references
+ String[] proto = findAnnotation(arrData, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptPrototype",
+ "container", "prototype"
);
- List toInitilize = new ArrayList();
- for (Method m : jc.getMethods()) {
- if (m.isStatic()) {
- compiler.generateStaticMethod(m, toInitilize);
- } else {
- compiler.generateInstanceMethod(m);
+ StringArray toInitilize = new StringArray();
+ final String className = className(jc);
+ out.append("\n\n").append(assignClass(className));
+ out.append("function CLS() {");
+ out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
+ for (FieldData v : jc.getFields()) {
+ if (v.isStatic()) {
+ out.append("\n CLS.").append(v.getName()).append(initField(v));
}
}
- for (Variable v : jc.getVariables()) {
- if (v.isStatic()) {
- compiler.generateStaticField(v);
+ if (proto == null) {
+ String sc = jc.getSuperClassName(); // with _
+ out.append("\n var pp = ").
+ append(accessClass(sc.replace('/', '_'))).append("(true);");
+ out.append("\n var p = CLS.prototype = pp;");
+ out.append("\n var c = p;");
+ out.append("\n var sprcls = pp.constructor.$class;");
+ } else {
+ out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
+ if (proto[0] == null) {
+ proto[0] = "p";
+ }
+ out.append("\n var c = ").append(proto[0]).append(";");
+ out.append("\n var sprcls = null;");
+ }
+ for (MethodData m : jc.getMethods()) {
+ byte[] onlyArr = m.findAnnotationData(true);
+ String[] only = findAnnotation(onlyArr, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptOnly",
+ "name", "value"
+ );
+ if (only != null) {
+ if (only[0] != null && only[1] != null) {
+ out.append("\n p.").append(only[0]).append(" = ")
+ .append(only[1]).append(";");
+ }
+ continue;
+ }
+ String prefix;
+ String mn;
+ if (m.isStatic()) {
+ prefix = "\n c.";
+ mn = generateStaticMethod(prefix, m, toInitilize);
+ } else {
+ if (m.isConstructor()) {
+ prefix = "\n CLS.";
+ mn = generateInstanceMethod(prefix, m);
+ } else {
+ prefix = "\n c.";
+ mn = generateInstanceMethod(prefix, m);
+ }
+ }
+ byte[] runAnno = m.findAnnotationData(false);
+ if (runAnno != null) {
+ out.append(prefix).append(mn).append(".anno = {");
+ generateAnno(jc, out, runAnno);
+ out.append("\n };");
+ }
+ out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
+ }
+ out.append("\n c.constructor = CLS;");
+ out.append("\n c.$instOf_").append(className).append(" = true;");
+ for (String superInterface : jc.getSuperInterfaces()) {
+ out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
+ }
+ out.append("\n CLS.$class = ");
+ out.append(accessClass("java_lang_Class(true);"));
+ out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
+ out.append("\n CLS.$class.superclass = sprcls;");
+ out.append("\n CLS.$class.access = ").append(jc.getAccessFlags()+";");
+ out.append("\n CLS.$class.cnstr = CLS;");
+ byte[] classAnno = jc.findAnnotationData(false);
+ if (classAnno != null) {
+ out.append("\n CLS.$class.anno = {");
+ generateAnno(jc, out, classAnno);
+ out.append("\n };");
+ }
+ out.append("\n }");
+ out.append("\n if (arguments.length === 0) {");
+ out.append("\n if (!(this instanceof CLS)) {");
+ out.append("\n return new CLS();");
+ out.append("\n }");
+ for (FieldData v : jc.getFields()) {
+ byte[] onlyArr = v.findAnnotationData(true);
+ String[] only = findAnnotation(onlyArr, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptOnly",
+ "name", "value"
+ );
+ if (only != null) {
+ if (only[0] != null && only[1] != null) {
+ out.append("\n p.").append(only[0]).append(" = ")
+ .append(only[1]).append(";");
+ }
+ continue;
+ }
+ if (!v.isStatic()) {
+ out.append("\n this.fld_").
+ append(v.getName()).append(initField(v));
}
}
-
- final String className = jc.getName().getInternalName().replace('/', '_');
- out.append("\nfunction ").append(className);
- out.append("() {");
- for (Variable v : jc.getVariables()) {
- if (!v.isStatic()) {
- out.append("\n this." + v.getName() + " = 0;");
- }
- }
- out.append("\n}\n\nfunction ").append(className).append("_proto() {");
- out.append("\n if (").append(className).
- append(".prototype.$instOf_").append(className).append(") {");
- out.append("\n return ").append(className).append(".prototype;");
+ out.append("\n return this;");
out.append("\n }");
- ClassName sc = jc.getSuperClass();
- if (sc != null) {
- out.append("\n ").append(sc.getInternalName().replace('/', '_')).append("_proto();");
- out.append("\n ").append(className)
- .append(".prototype = new ").append(sc.getInternalName().replace('/', '_')).append(';');
- }
- for (Method m : jc.getMethods()) {
- if (!m.isStatic() && !m.isPrivate() && !m.getName().contains("")) {
- compiler.generateMethodReference("\n " + className + ".prototype.", m);
- }
- }
- out.append("\n " + className + ".prototype.$instOf_").append(className).append(" = true;");
- for (ClassName superInterface : jc.getInterfaces()) {
- out.append("\n " + className + ".prototype.$instOf_").append(superInterface.getInternalName().replace('/', '_')).append(" = true;");
- }
- out.append("\n return ").append(className).append(".prototype;");
- out.append("\n}");
- out.append("\n").append(className).append("_proto();");
+ out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
+ out.append("\n};");
StringBuilder sb = new StringBuilder();
- for (String init : toInitilize) {
+ for (String init : toInitilize.toArray()) {
sb.append("\n").append(init).append("();");
}
return sb.toString();
}
- private void generateStaticMethod(Method m, List toInitilize) throws IOException {
- if (javaScriptBody(m, true)) {
+ private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
+ String jsb = javaScriptBody(prefix, m, true);
+ if (jsb != null) {
+ return jsb;
+ }
+ final String mn = findMethodName(m, new StringBuilder());
+ if (mn.equals("class__V")) {
+ toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
+ }
+ generateMethod(prefix, mn, m);
+ return mn;
+ }
+
+ private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
+ String jsb = javaScriptBody(prefix, m, false);
+ if (jsb != null) {
+ return jsb;
+ }
+ final String mn = findMethodName(m, new StringBuilder());
+ generateMethod(prefix, mn, m);
+ return mn;
+ }
+
+ private void generateMethod(String prefix, String name, MethodData m)
+ throws IOException {
+ final StackMapIterator stackMapIterator = m.createStackMapIterator();
+ TrapDataIterator trap = m.getTrapDataIterator();
+ final LocalsMapper lmapper =
+ new LocalsMapper(stackMapIterator.getArguments());
+
+ out.append(prefix).append(name).append(" = function(");
+ lmapper.outputArguments(out, m.isStatic());
+ out.append(") {").append("\n");
+
+ final byte[] byteCodes = m.getCode();
+ if (byteCodes == null) {
+ out.append(" throw 'no code found for ")
+ .append(jc.getClassName()).append('.')
+ .append(m.getName()).append("';\n");
+ out.append("};");
return;
}
- final String mn = findMethodName(m);
- out.append("\nfunction ").append(
- jc.getName().getInternalName().replace('/', '_')
- ).append('_').append(mn);
- if (mn.equals("classV")) {
- toInitilize.add(jc.getName().getInternalName().replace('/', '_') + '_' + mn);
+
+ final StackMapper smapper = new StackMapper();
+
+ if (!m.isStatic()) {
+ out.append(" var ").append(" lcA0 = this;\n");
}
- out.append('(');
- String space = "";
- List args = m.getParameters();
- for (int index = 0, i = 0; i < args.size(); i++) {
- out.append(space);
- out.append("arg").append(String.valueOf(index));
- space = ",";
- final String desc = findDescriptor(args.get(i).getDescriptor());
- if ("D".equals(desc) || "J".equals(desc)) {
- index += 2;
- } else {
- index++;
- }
- }
- out.append(") {").append("\n");
- final Code code = m.getCode();
- if (code != null) {
- int len = code.getMaxLocals();
- for (int index = args.size(), i = args.size(); i < len; i++) {
- out.append(" var ");
- out.append("arg").append(String.valueOf(i)).append(";\n");
- }
- out.append(" var stack = new Array();\n");
- produceCode(code.getByteCodes());
- } else {
- out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n");
- }
- out.append("}");
- }
-
- private void generateMethodReference(String prefix, Method m) throws IOException {
- final String name = findMethodName(m);
- out.append(prefix).append(name).append(" = ")
- .append(jc.getName().getInternalName().replace('/', '_'))
- .append('_').append(name).append(";");
- }
-
- private void generateInstanceMethod(Method m) throws IOException {
- if (javaScriptBody(m, false)) {
- return;
- }
- out.append("\nfunction ").append(
- jc.getName().getInternalName().replace('/', '_')
- ).append('_').append(findMethodName(m));
- out.append("(arg0");
- String space = ",";
- List args = m.getParameters();
- for (int index = 1, i = 0; i < args.size(); i++) {
- out.append(space);
- out.append("arg").append(String.valueOf(index));
- final String desc = findDescriptor(args.get(i).getDescriptor());
- if ("D".equals(desc) || "J".equals(desc)) {
- index += 2;
- } else {
- index++;
- }
- }
- out.append(") {").append("\n");
- final Code code = m.getCode();
- if (code != null) {
- int len = code.getMaxLocals();
- for (int index = args.size(), i = args.size(); i < len; i++) {
- out.append(" var ");
- out.append("arg").append(String.valueOf(i + 1)).append(";\n");
- }
- out.append(";\n var stack = new Array();\n");
- produceCode(code.getByteCodes());
- } else {
- out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n");
- }
- out.append("}");
- }
- private void produceCode(byte[] byteCodes) throws IOException {
+ int lastStackFrame = -1;
+ TrapData[] previousTrap = null;
+
out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
for (int i = 0; i < byteCodes.length; i++) {
int prev = i;
- out.append(" case " + i).append(": ");
- final int c = (byteCodes[i] + 256) % 256;
+ stackMapIterator.advanceTo(i);
+ boolean changeInCatch = trap.advanceTo(i);
+ if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
+ if (previousTrap != null) {
+ generateCatch(previousTrap);
+ previousTrap = null;
+ }
+ }
+ if (lastStackFrame != stackMapIterator.getFrameIndex()) {
+ lastStackFrame = stackMapIterator.getFrameIndex();
+ lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
+ smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
+ out.append(" case " + i).append(": ");
+ changeInCatch = true;
+ } else {
+ debug(" /* " + i + " */ ");
+ }
+ if (changeInCatch && trap.useTry()) {
+ out.append("try {");
+ previousTrap = trap.current();
+ }
+ final int c = readByte(byteCodes, i);
switch (c) {
- case bc_aload_0:
- case bc_iload_0:
- case bc_lload_0:
- case bc_fload_0:
- case bc_dload_0:
- out.append("stack.push(arg0);");
+ case opc_aload_0:
+ emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
break;
- case bc_aload_1:
- case bc_iload_1:
- case bc_lload_1:
- case bc_fload_1:
- case bc_dload_1:
- out.append("stack.push(arg1);");
+ case opc_iload_0:
+ emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0));
break;
- case bc_aload_2:
- case bc_iload_2:
- case bc_lload_2:
- case bc_fload_2:
- case bc_dload_2:
- out.append("stack.push(arg2);");
+ case opc_lload_0:
+ emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0));
break;
- case bc_aload_3:
- case bc_iload_3:
- case bc_lload_3:
- case bc_fload_3:
- case bc_dload_3:
- out.append("stack.push(arg3);");
+ case opc_fload_0:
+ emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0));
break;
- case bc_iload:
- case bc_lload:
- case bc_fload:
- case bc_dload:
- case bc_aload: {
- final int indx = (byteCodes[++i] + 256) % 256;
- out.append("stack.push(arg").append(indx + ");");
+ case opc_dload_0:
+ emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0));
+ break;
+ case opc_aload_1:
+ emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1));
+ break;
+ case opc_iload_1:
+ emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1));
+ break;
+ case opc_lload_1:
+ emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1));
+ break;
+ case opc_fload_1:
+ emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1));
+ break;
+ case opc_dload_1:
+ emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1));
+ break;
+ case opc_aload_2:
+ emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2));
+ break;
+ case opc_iload_2:
+ emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2));
+ break;
+ case opc_lload_2:
+ emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2));
+ break;
+ case opc_fload_2:
+ emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2));
+ break;
+ case opc_dload_2:
+ emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2));
+ break;
+ case opc_aload_3:
+ emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3));
+ break;
+ case opc_iload_3:
+ emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3));
+ break;
+ case opc_lload_3:
+ emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3));
+ break;
+ case opc_fload_3:
+ emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3));
+ break;
+ case opc_dload_3:
+ emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
+ break;
+ case opc_iload: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ smapper.pushI(), lmapper.getI(indx));
break;
}
- case bc_istore:
- case bc_lstore:
- case bc_fstore:
- case bc_dstore:
- case bc_astore: {
- final int indx = (byteCodes[++i] + 256) % 256;
- out.append("arg" + indx).append(" = stack.pop()");
+ case opc_lload: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ smapper.pushL(), lmapper.getL(indx));
break;
}
- case bc_astore_0:
- case bc_istore_0:
- case bc_lstore_0:
- case bc_fstore_0:
- case bc_dstore_0:
- out.append("arg0 = stack.pop();");
+ case opc_fload: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ smapper.pushF(), lmapper.getF(indx));
break;
- case bc_astore_1:
- case bc_istore_1:
- case bc_lstore_1:
- case bc_fstore_1:
- case bc_dstore_1:
- out.append("arg1 = stack.pop();");
+ }
+ case opc_dload: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ smapper.pushD(), lmapper.getD(indx));
break;
- case bc_astore_2:
- case bc_istore_2:
- case bc_lstore_2:
- case bc_fstore_2:
- case bc_dstore_2:
- out.append("arg2 = stack.pop();");
+ }
+ case opc_aload: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ smapper.pushA(), lmapper.getA(indx));
break;
- case bc_astore_3:
- case bc_istore_3:
- case bc_lstore_3:
- case bc_fstore_3:
- case bc_dstore_3:
- out.append("arg3 = stack.pop();");
+ }
+ case opc_istore: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ lmapper.setI(indx), smapper.popI());
break;
- case bc_iadd:
- case bc_ladd:
- case bc_fadd:
- case bc_dadd:
- out.append("stack.push(stack.pop() + stack.pop());");
+ }
+ case opc_lstore: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ lmapper.setL(indx), smapper.popL());
break;
- case bc_isub:
- case bc_lsub:
- case bc_fsub:
- case bc_dsub:
- out.append("{ var tmp = stack.pop(); stack.push(stack.pop() - tmp); }");
+ }
+ case opc_fstore: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ lmapper.setF(indx), smapper.popF());
break;
- case bc_imul:
- case bc_lmul:
- case bc_fmul:
- case bc_dmul:
- out.append("stack.push(stack.pop() * stack.pop());");
+ }
+ case opc_dstore: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ lmapper.setD(indx), smapper.popD());
break;
- case bc_idiv:
- case bc_ldiv:
- out.append("{ var tmp = stack.pop(); stack.push(Math.floor(stack.pop() / tmp)); }");
+ }
+ case opc_astore: {
+ final int indx = readByte(byteCodes, ++i);
+ emit(out, "var @1 = @2;",
+ lmapper.setA(indx), smapper.popA());
break;
- case bc_fdiv:
- case bc_ddiv:
- out.append("{ var tmp = stack.pop(); stack.push(stack.pop() / tmp); }");
+ }
+ case opc_astore_0:
+ emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA());
break;
- case bc_iand:
- case bc_land:
- out.append("stack.push(stack.pop() & stack.pop());");
+ case opc_istore_0:
+ emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI());
break;
- case bc_ior:
- case bc_lor:
- out.append("stack.push(stack.pop() | stack.pop());");
+ case opc_lstore_0:
+ emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL());
break;
- case bc_ixor:
- case bc_lxor:
- out.append("stack.push(stack.pop() ^ stack.pop());");
+ case opc_fstore_0:
+ emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF());
break;
- case bc_ineg:
- case bc_lneg:
- case bc_fneg:
- case bc_dneg:
- out.append("stack.push(- stack.pop());");
+ case opc_dstore_0:
+ emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD());
break;
- case bc_ishl:
- case bc_lshl:
- out.append("{ var v = stack.pop(); stack.push(stack.pop() << v); }");
+ case opc_astore_1:
+ emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA());
break;
- case bc_ishr:
- case bc_lshr:
- out.append("{ var v = stack.pop(); stack.push(stack.pop() >> v); }");
+ case opc_istore_1:
+ emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI());
break;
- case bc_iushr:
- case bc_lushr:
- out.append("{ var v = stack.pop(); stack.push(stack.pop() >>> v); }");
+ case opc_lstore_1:
+ emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL());
break;
- case bc_iinc: {
- final int varIndx = (byteCodes[++i] + 256) % 256;
- final int incrBy = (byteCodes[++i] + 256) % 256;
+ case opc_fstore_1:
+ emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF());
+ break;
+ case opc_dstore_1:
+ emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD());
+ break;
+ case opc_astore_2:
+ emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA());
+ break;
+ case opc_istore_2:
+ emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI());
+ break;
+ case opc_lstore_2:
+ emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL());
+ break;
+ case opc_fstore_2:
+ emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF());
+ break;
+ case opc_dstore_2:
+ emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD());
+ break;
+ case opc_astore_3:
+ emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA());
+ break;
+ case opc_istore_3:
+ emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI());
+ break;
+ case opc_lstore_3:
+ emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL());
+ break;
+ case opc_fstore_3:
+ emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF());
+ break;
+ case opc_dstore_3:
+ emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
+ break;
+ case opc_iadd:
+ emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
+ break;
+ case opc_ladd:
+ emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_fadd:
+ emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
+ break;
+ case opc_dadd:
+ emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
+ break;
+ case opc_isub:
+ emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lsub:
+ emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_fsub:
+ emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
+ break;
+ case opc_dsub:
+ emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
+ break;
+ case opc_imul:
+ emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lmul:
+ emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_fmul:
+ emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
+ break;
+ case opc_dmul:
+ emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
+ break;
+ case opc_idiv:
+ emit(out, "@1 = Math.floor(@1 / @2);",
+ smapper.getI(1), smapper.popI());
+ break;
+ case opc_ldiv:
+ emit(out, "@1 = Math.floor(@1 / @2);",
+ smapper.getL(1), smapper.popL());
+ break;
+ case opc_fdiv:
+ emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
+ break;
+ case opc_ddiv:
+ emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
+ break;
+ case opc_irem:
+ emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lrem:
+ emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_frem:
+ emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
+ break;
+ case opc_drem:
+ emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
+ break;
+ case opc_iand:
+ emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_land:
+ emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_ior:
+ emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lor:
+ emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_ixor:
+ emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lxor:
+ emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL());
+ break;
+ case opc_ineg:
+ emit(out, "@1 = -@1;", smapper.getI(0));
+ break;
+ case opc_lneg:
+ emit(out, "@1 = -@1;", smapper.getL(0));
+ break;
+ case opc_fneg:
+ emit(out, "@1 = -@1;", smapper.getF(0));
+ break;
+ case opc_dneg:
+ emit(out, "@1 = -@1;", smapper.getD(0));
+ break;
+ case opc_ishl:
+ emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lshl:
+ emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI());
+ break;
+ case opc_ishr:
+ emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lshr:
+ emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
+ break;
+ case opc_iushr:
+ emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
+ break;
+ case opc_lushr:
+ emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
+ break;
+ case opc_iinc: {
+ final int varIndx = readByte(byteCodes, ++i);
+ final int incrBy = byteCodes[++i];
if (incrBy == 1) {
- out.append("arg" + varIndx).append("++;");
+ emit(out, "@1++;", lmapper.getI(varIndx));
} else {
- out.append("arg" + varIndx).append(" += " + incrBy).append(";");
+ emit(out, "@1 += @2;",
+ lmapper.getI(varIndx),
+ Integer.toString(incrBy));
}
break;
}
- case bc_return:
- out.append("return;");
+ case opc_return:
+ emit(out, "return;");
break;
- case bc_ireturn:
- case bc_lreturn:
- case bc_freturn:
- case bc_dreturn:
- case bc_areturn:
- out.append("return stack.pop();");
+ case opc_ireturn:
+ emit(out, "return @1;", smapper.popI());
break;
- case bc_i2l:
- case bc_i2f:
- case bc_i2d:
- case bc_l2i:
+ case opc_lreturn:
+ emit(out, "return @1;", smapper.popL());
+ break;
+ case opc_freturn:
+ emit(out, "return @1;", smapper.popF());
+ break;
+ case opc_dreturn:
+ emit(out, "return @1;", smapper.popD());
+ break;
+ case opc_areturn:
+ emit(out, "return @1;", smapper.popA());
+ break;
+ case opc_i2l:
+ emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL());
+ break;
+ case opc_i2f:
+ emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF());
+ break;
+ case opc_i2d:
+ emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
+ break;
+ case opc_l2i:
+ emit(out, "var @2 = @1;", smapper.popL(), smapper.pushI());
+ break;
// max int check?
- case bc_l2f:
- case bc_l2d:
- case bc_f2d:
- case bc_d2f:
- out.append("/* number conversion */");
+ case opc_l2f:
+ emit(out, "var @2 = @1;", smapper.popL(), smapper.pushF());
break;
- case bc_f2i:
- case bc_f2l:
- case bc_d2i:
- case bc_d2l:
- out.append("stack.push(Math.floor(stack.pop()));");
+ case opc_l2d:
+ emit(out, "var @2 = @1;", smapper.popL(), smapper.pushD());
break;
- case bc_i2b:
- case bc_i2c:
- case bc_i2s:
- out.append("/* number conversion */");
+ case opc_f2d:
+ emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
break;
- case bc_aconst_null:
- out.append("stack.push(null);");
+ case opc_d2f:
+ emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
break;
- case bc_iconst_m1:
- out.append("stack.push(-1);");
+ case opc_f2i:
+ emit(out, "var @2 = Math.floor(@1);",
+ smapper.popF(), smapper.pushI());
break;
- case bc_iconst_0:
- case bc_dconst_0:
- case bc_lconst_0:
- case bc_fconst_0:
- out.append("stack.push(0);");
+ case opc_f2l:
+ emit(out, "var @2 = Math.floor(@1);",
+ smapper.popF(), smapper.pushL());
break;
- case bc_iconst_1:
- case bc_lconst_1:
- case bc_fconst_1:
- case bc_dconst_1:
- out.append("stack.push(1);");
+ case opc_d2i:
+ emit(out, "var @2 = Math.floor(@1);",
+ smapper.popD(), smapper.pushI());
break;
- case bc_iconst_2:
- case bc_fconst_2:
- out.append("stack.push(2);");
+ case opc_d2l:
+ emit(out, "var @2 = Math.floor(@1);",
+ smapper.popD(), smapper.pushL());
break;
- case bc_iconst_3:
- out.append("stack.push(3);");
+ case opc_i2b:
+ emit(out, "var @1 = @1.toInt8();", smapper.getI(0));
break;
- case bc_iconst_4:
- out.append("stack.push(4);");
+ case opc_i2c:
+ out.append("{ /* number conversion */ }");
break;
- case bc_iconst_5:
- out.append("stack.push(5);");
+ case opc_i2s:
+ emit(out, "var @1 = @1.toInt16();", smapper.getI(0));
break;
- case bc_ldc: {
- int indx = byteCodes[++i];
- CPEntry entry = jc.getConstantPool().get(indx);
- String v = encodeConstant(entry);
- out.append("stack.push(").append(v).append(");");
+ case opc_aconst_null:
+ emit(out, "var @1 = null;", smapper.pushA());
+ break;
+ case opc_iconst_m1:
+ emit(out, "var @1 = -1;", smapper.pushI());
+ break;
+ case opc_iconst_0:
+ emit(out, "var @1 = 0;", smapper.pushI());
+ break;
+ case opc_dconst_0:
+ emit(out, "var @1 = 0;", smapper.pushD());
+ break;
+ case opc_lconst_0:
+ emit(out, "var @1 = 0;", smapper.pushL());
+ break;
+ case opc_fconst_0:
+ emit(out, "var @1 = 0;", smapper.pushF());
+ break;
+ case opc_iconst_1:
+ emit(out, "var @1 = 1;", smapper.pushI());
+ break;
+ case opc_lconst_1:
+ emit(out, "var @1 = 1;", smapper.pushL());
+ break;
+ case opc_fconst_1:
+ emit(out, "var @1 = 1;", smapper.pushF());
+ break;
+ case opc_dconst_1:
+ emit(out, "var @1 = 1;", smapper.pushD());
+ break;
+ case opc_iconst_2:
+ emit(out, "var @1 = 2;", smapper.pushI());
+ break;
+ case opc_fconst_2:
+ emit(out, "var @1 = 2;", smapper.pushF());
+ break;
+ case opc_iconst_3:
+ emit(out, "var @1 = 3;", smapper.pushI());
+ break;
+ case opc_iconst_4:
+ emit(out, "var @1 = 4;", smapper.pushI());
+ break;
+ case opc_iconst_5:
+ emit(out, "var @1 = 5;", smapper.pushI());
+ break;
+ case opc_ldc: {
+ int indx = readByte(byteCodes, ++i);
+ String v = encodeConstant(indx);
+ int type = VarType.fromConstantType(jc.getTag(indx));
+ emit(out, "var @1 = @2;", smapper.pushT(type), v);
break;
}
- case bc_ldc_w:
- case bc_ldc2_w: {
+ case opc_ldc_w:
+ case opc_ldc2_w: {
int indx = readIntArg(byteCodes, i);
- CPEntry entry = jc.getConstantPool().get(indx);
i += 2;
- String v = encodeConstant(entry);
- out.append("stack.push(").append(v).append(");");
+ String v = encodeConstant(indx);
+ int type = VarType.fromConstantType(jc.getTag(indx));
+ emit(out, "var @1 = @2;", smapper.pushT(type), v);
break;
}
- case bc_lcmp:
- case bc_fcmpl:
- case bc_fcmpg:
- case bc_dcmpl:
- case bc_dcmpg: {
- out.append("{ var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); }");
+ case opc_lcmp:
+ emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
+ smapper.popL(), smapper.popL(), smapper.pushI());
break;
- }
- case bc_if_icmpeq: {
- i = generateIf(byteCodes, i, "==");
+ case opc_fcmpl:
+ case opc_fcmpg:
+ emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
+ smapper.popF(), smapper.popF(), smapper.pushI());
break;
- }
- case bc_ifeq: {
+ case opc_dcmpl:
+ case opc_dcmpg:
+ emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
+ smapper.popD(), smapper.popD(), smapper.pushI());
+ break;
+ case opc_if_acmpeq:
+ i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
+ "===");
+ break;
+ case opc_if_acmpne:
+ i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
+ "!=");
+ break;
+ case opc_if_icmpeq:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ "==");
+ break;
+ case opc_ifeq: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() == 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 == 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifne: {
+ case opc_ifne: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() != 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 != 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_iflt: {
+ case opc_iflt: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() < 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 < 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifle: {
+ case opc_ifle: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() <= 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 <= 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifgt: {
+ case opc_ifgt: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() > 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 > 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifge: {
+ case opc_ifge: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() >= 0) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 >= 0) { gt = @2; continue; }",
+ smapper.popI(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifnonnull: {
+ case opc_ifnonnull: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop()) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 !== null) { gt = @2; continue; }",
+ smapper.popA(), Integer.toString(indx));
i += 2;
break;
}
- case bc_ifnull: {
+ case opc_ifnull: {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (!stack.pop()) { gt = " + indx);
- out.append("; continue; }");
+ emit(out, "if (@1 === null) { gt = @2; continue; }",
+ smapper.popA(), Integer.toString(indx));
i += 2;
break;
}
- case bc_if_icmpne:
- i = generateIf(byteCodes, i, "!=");
+ case opc_if_icmpne:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ "!=");
break;
- case bc_if_icmplt:
- i = generateIf(byteCodes, i, ">");
+ case opc_if_icmplt:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ "<");
break;
- case bc_if_icmple:
- i = generateIf(byteCodes, i, ">=");
+ case opc_if_icmple:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ "<=");
break;
- case bc_if_icmpgt:
- i = generateIf(byteCodes, i, "<");
+ case opc_if_icmpgt:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ ">");
break;
- case bc_if_icmpge:
- i = generateIf(byteCodes, i, "<=");
+ case opc_if_icmpge:
+ i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
+ ">=");
break;
- case bc_goto: {
+ case opc_goto: {
int indx = i + readIntArg(byteCodes, i);
- out.append("gt = " + indx).append("; continue;");
+ emit(out, "gt = @1; continue;", Integer.toString(indx));
i += 2;
break;
}
- case bc_invokeinterface: {
- i = invokeVirtualMethod(byteCodes, i) + 2;
+ case opc_lookupswitch: {
+ int table = i / 4 * 4 + 4;
+ int dflt = i + readInt4(byteCodes, table);
+ table += 4;
+ int n = readInt4(byteCodes, table);
+ table += 4;
+ out.append("switch (").append(smapper.popI()).append(") {\n");
+ while (n-- > 0) {
+ int cnstnt = readInt4(byteCodes, table);
+ table += 4;
+ int offset = i + readInt4(byteCodes, table);
+ table += 4;
+ out.append(" case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
+ }
+ out.append(" default: gt = " + dflt).append("; continue;\n}");
+ i = table - 1;
break;
}
- case bc_invokevirtual:
- i = invokeVirtualMethod(byteCodes, i);
+ case opc_tableswitch: {
+ int table = i / 4 * 4 + 4;
+ int dflt = i + readInt4(byteCodes, table);
+ table += 4;
+ int low = readInt4(byteCodes, table);
+ table += 4;
+ int high = readInt4(byteCodes, table);
+ table += 4;
+ out.append("switch (").append(smapper.popI()).append(") {\n");
+ while (low <= high) {
+ int offset = i + readInt4(byteCodes, table);
+ table += 4;
+ out.append(" case " + low).append(": gt = " + offset).append("; continue;\n");
+ low++;
+ }
+ out.append(" default: gt = " + dflt).append("; continue;\n}");
+ i = table - 1;
break;
- case bc_invokespecial:
- i = invokeStaticMethod(byteCodes, i, false);
+ }
+ case opc_invokeinterface: {
+ i = invokeVirtualMethod(byteCodes, i, smapper) + 2;
break;
- case bc_invokestatic:
- i = invokeStaticMethod(byteCodes, i, true);
+ }
+ case opc_invokevirtual:
+ i = invokeVirtualMethod(byteCodes, i, smapper);
break;
- case bc_new: {
+ case opc_invokespecial:
+ i = invokeStaticMethod(byteCodes, i, smapper, false);
+ break;
+ case opc_invokestatic:
+ i = invokeStaticMethod(byteCodes, i, smapper, true);
+ break;
+ case opc_new: {
int indx = readIntArg(byteCodes, i);
- CPClassInfo ci = jc.getConstantPool().getClass(indx);
- out.append("stack.push(");
- out.append("new ").append(ci.getClassName().getInternalName().replace('/','_'));
- out.append(");");
- addReference(ci.getClassName().getInternalName());
+ String ci = jc.getClassName(indx);
+ emit(out, "var @1 = new @2;",
+ smapper.pushA(), accessClass(ci.replace('/', '_')));
+ addReference(ci);
i += 2;
break;
}
- case bc_newarray: {
- int type = byteCodes[i++];
- out.append("stack.push(new Array(stack.pop()));");
+ case opc_newarray:
+ int atype = readByte(byteCodes, ++i);
+ String jvmType;
+ switch (atype) {
+ case 4: jvmType = "[Z"; break;
+ case 5: jvmType = "[C"; break;
+ case 6: jvmType = "[F"; break;
+ case 7: jvmType = "[D"; break;
+ case 8: jvmType = "[B"; break;
+ case 9: jvmType = "[S"; break;
+ case 10: jvmType = "[I"; break;
+ case 11: jvmType = "[J"; break;
+ default: throw new IllegalStateException("Array type: " + atype);
+ }
+ emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
+ smapper.popI(), smapper.pushA(), jvmType);
+ break;
+ case opc_anewarray: {
+ int type = readIntArg(byteCodes, i);
+ i += 2;
+ String typeName = jc.getClassName(type);
+ if (typeName.startsWith("[")) {
+ typeName = "[" + typeName;
+ } else {
+ typeName = "[L" + typeName + ";";
+ }
+ emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
+ smapper.popI(), smapper.pushA(), typeName);
break;
}
- case bc_anewarray: {
- i += 2; // skip type of array
- out.append("stack.push(new Array(stack.pop()));");
+ case opc_multianewarray: {
+ int type = readIntArg(byteCodes, i);
+ i += 2;
+ String typeName = jc.getClassName(type);
+ int dim = readByte(byteCodes, ++i);
+ StringBuilder dims = new StringBuilder();
+ dims.append('[');
+ for (int d = 0; d < dim; d++) {
+ if (d != 0) {
+ dims.append(",");
+ }
+ dims.append(smapper.popI());
+ }
+ dims.append(']');
+ emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
+ dims.toString(), smapper.pushA(), typeName);
break;
}
- case bc_arraylength:
- out.append("stack.push(stack.pop().length);");
+ case opc_arraylength:
+ emit(out, "var @2 = @1.length;",
+ smapper.popA(), smapper.pushI());
break;
- case bc_iastore:
- case bc_lastore:
- case bc_fastore:
- case bc_dastore:
- case bc_aastore:
- case bc_bastore:
- case bc_castore:
- case bc_sastore: {
- out.append("{ var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; }");
+ case opc_lastore:
+ emit(out, "@3.at(@2, @1);",
+ smapper.popL(), smapper.popI(), smapper.popA());
+ break;
+ case opc_fastore:
+ emit(out, "@3.at(@2, @1);",
+ smapper.popF(), smapper.popI(), smapper.popA());
+ break;
+ case opc_dastore:
+ emit(out, "@3.at(@2, @1);",
+ smapper.popD(), smapper.popI(), smapper.popA());
+ break;
+ case opc_aastore:
+ emit(out, "@3.at(@2, @1);",
+ smapper.popA(), smapper.popI(), smapper.popA());
+ break;
+ case opc_iastore:
+ case opc_bastore:
+ case opc_castore:
+ case opc_sastore:
+ emit(out, "@3.at(@2, @1);",
+ smapper.popI(), smapper.popI(), smapper.popA());
+ break;
+ case opc_laload:
+ emit(out, "var @3 = @2.at(@1);",
+ smapper.popI(), smapper.popA(), smapper.pushL());
+ break;
+ case opc_faload:
+ emit(out, "var @3 = @2.at(@1);",
+ smapper.popI(), smapper.popA(), smapper.pushF());
+ break;
+ case opc_daload:
+ emit(out, "var @3 = @2.at(@1);",
+ smapper.popI(), smapper.popA(), smapper.pushD());
+ break;
+ case opc_aaload:
+ emit(out, "var @3 = @2.at(@1);",
+ smapper.popI(), smapper.popA(), smapper.pushA());
+ break;
+ case opc_iaload:
+ case opc_baload:
+ case opc_caload:
+ case opc_saload:
+ emit(out, "var @3 = @2.at(@1);",
+ smapper.popI(), smapper.popA(), smapper.pushI());
+ break;
+ case opc_pop:
+ case opc_pop2:
+ smapper.pop(1);
+ debug("/* pop */");
+ break;
+ case opc_dup: {
+ final Variable v = smapper.get(0);
+ emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v);
break;
}
- case bc_iaload:
- case bc_laload:
- case bc_faload:
- case bc_daload:
- case bc_aaload:
- case bc_baload:
- case bc_caload:
- case bc_saload: {
- out.append("{ var indx = stack.pop(); stack.push(stack.pop()[indx]); }");
+ case opc_dup2: {
+ if (smapper.get(0).isCategory2()) {
+ final Variable v = smapper.get(0);
+ emit(out, "var @1 = @2;",
+ smapper.pushT(v.getType()), v);
+ } else {
+ final Variable v1 = smapper.get(0);
+ final Variable v2 = smapper.get(1);
+ emit(out, "var @1 = @2, @3 = @4;",
+ smapper.pushT(v2.getType()), v2,
+ smapper.pushT(v1.getType()), v1);
+ }
break;
}
- case bc_pop2:
- out.append("stack.pop();");
- case bc_pop:
- out.append("stack.pop();");
+ case opc_dup_x1: {
+ final Variable vi1 = smapper.pop();
+ final Variable vi2 = smapper.pop();
+ final Variable vo3 = smapper.pushT(vi1.getType());
+ final Variable vo2 = smapper.pushT(vi2.getType());
+ final Variable vo1 = smapper.pushT(vi1.getType());
+
+ emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
+ vo1, vi1, vo2, vi2, vo3, vo1);
break;
- case bc_dup:
- out.append("stack.push(stack[stack.length - 1]);");
+ }
+ case opc_dup_x2: {
+ if (smapper.get(1).isCategory2()) {
+ final Variable vi1 = smapper.pop();
+ final Variable vi2 = smapper.pop();
+ final Variable vo3 = smapper.pushT(vi1.getType());
+ final Variable vo2 = smapper.pushT(vi2.getType());
+ final Variable vo1 = smapper.pushT(vi1.getType());
+
+ emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
+ vo1, vi1, vo2, vi2, vo3, vo1);
+ } else {
+ final Variable vi1 = smapper.pop();
+ final Variable vi2 = smapper.pop();
+ final Variable vi3 = smapper.pop();
+ final Variable vo4 = smapper.pushT(vi1.getType());
+ final Variable vo3 = smapper.pushT(vi3.getType());
+ final Variable vo2 = smapper.pushT(vi2.getType());
+ final Variable vo1 = smapper.pushT(vi1.getType());
+
+ emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
+ vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
+ }
break;
- case bc_bipush:
- out.append("stack.push(" + byteCodes[++i] + ");");
+ }
+ case opc_bipush:
+ emit(out, "var @1 = @2;",
+ smapper.pushI(), Integer.toString(byteCodes[++i]));
break;
- case bc_sipush:
- out.append("stack.push(" + readIntArg(byteCodes, i) + ");");
+ case opc_sipush:
+ emit(out, "var @1 = @2;",
+ smapper.pushI(),
+ Integer.toString(readIntArg(byteCodes, i)));
i += 2;
break;
- case bc_getfield: {
+ case opc_getfield: {
int indx = readIntArg(byteCodes, i);
- CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
- out.append("stack.push(stack.pop().").append(fi.getFieldName()).append(");");
+ String[] fi = jc.getFieldInfoName(indx);
+ final int type = VarType.fromFieldType(fi[2].charAt(0));
+ emit(out, "var @2 = @1.fld_@3;",
+ smapper.popA(), smapper.pushT(type), fi[1]);
i += 2;
break;
}
- case bc_getstatic: {
+ case opc_getstatic: {
int indx = readIntArg(byteCodes, i);
- CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
- final String in = fi.getClassName().getInternalName();
- out.append("stack.push(").append(in.replace('/', '_'));
- out.append('_').append(fi.getFieldName()).append(");");
+ String[] fi = jc.getFieldInfoName(indx);
+ final int type = VarType.fromFieldType(fi[2].charAt(0));
+ emit(out, "var @1 = @2(false).constructor.@3;",
+ smapper.pushT(type),
+ accessClass(fi[0].replace('/', '_')), fi[1]);
i += 2;
- addReference(in);
+ addReference(fi[0]);
break;
}
- case bc_putstatic: {
+ case opc_putfield: {
int indx = readIntArg(byteCodes, i);
- CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
- final String in = fi.getClassName().getInternalName();
- out.append(in.replace('/', '_'));
- out.append('_').append(fi.getFieldName()).append(" = stack.pop();");
- i += 2;
- addReference(in);
- break;
- }
- case bc_putfield: {
- int indx = readIntArg(byteCodes, i);
- CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
- out.append("{ var v = stack.pop(); stack.pop().")
- .append(fi.getFieldName()).append(" = v; }");
+ String[] fi = jc.getFieldInfoName(indx);
+ final int type = VarType.fromFieldType(fi[2].charAt(0));
+ emit(out, "@2.fld_@3 = @1;",
+ smapper.popT(type), smapper.popA(), fi[1]);
i += 2;
break;
}
- case bc_checkcast: {
+ case opc_putstatic: {
int indx = readIntArg(byteCodes, i);
- CPClassInfo ci = jc.getConstantPool().getClass(indx);
- final String type = ci.getClassName().getType();
+ String[] fi = jc.getFieldInfoName(indx);
+ final int type = VarType.fromFieldType(fi[2].charAt(0));
+ emit(out, "@1(false).constructor.@2 = @3;",
+ accessClass(fi[0].replace('/', '_')), fi[1],
+ smapper.popT(type));
+ i += 2;
+ addReference(fi[0]);
+ break;
+ }
+ case opc_checkcast: {
+ int indx = readIntArg(byteCodes, i);
+ final String type = jc.getClassName(indx);
if (!type.startsWith("[")) {
// no way to check arrays right now
- out.append("if(stack[stack.length - 1].$instOf_")
- .append(type.replace('/', '_'))
- .append(" != 1) throw {};"); // XXX proper exception
+ // XXX proper exception
+ emit(out,
+ "if (@1 !== null && !@1.$instOf_@2) throw {};",
+ smapper.getA(0), type.replace('/', '_'));
}
i += 2;
break;
}
- case bc_instanceof: {
+ case opc_instanceof: {
int indx = readIntArg(byteCodes, i);
- CPClassInfo ci = jc.getConstantPool().getClass(indx);
- out.append("stack.push(stack.pop().$instOf_")
- .append(ci.getClassName().getInternalName().replace('/', '_'))
- .append(" ? 1 : 0);");
+ final String type = jc.getClassName(indx);
+ emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
+ smapper.popA(), smapper.pushI(),
+ type.replace('/', '_'));
i += 2;
break;
}
-
+ case opc_athrow: {
+ final Variable v = smapper.popA();
+ smapper.clear();
+
+ emit(out, "{ var @1 = @2; throw @2; }",
+ smapper.pushA(), v);
+ break;
+ }
+
+ case opc_monitorenter: {
+ out.append("/* monitor enter */");
+ smapper.popA();
+ break;
+ }
+
+ case opc_monitorexit: {
+ out.append("/* monitor exit */");
+ smapper.popA();
+ break;
+ }
+
+ default: {
+ emit(out, "throw 'unknown bytecode @1';",
+ Integer.toString(c));
+ }
}
- out.append(" //");
- for (int j = prev; j <= i; j++) {
- out.append(" ");
- final int cc = (byteCodes[j] + 256) % 256;
- out.append(Integer.toString(cc));
+ if (debug(" //")) {
+ for (int j = prev; j <= i; j++) {
+ out.append(" ");
+ final int cc = readByte(byteCodes, j);
+ out.append(Integer.toString(cc));
+ }
}
- out.append("\n");
+ out.append("\n");
+ }
+ if (previousTrap != null) {
+ generateCatch(previousTrap);
}
out.append(" }\n");
+ out.append("};");
}
- private int generateIf(byte[] byteCodes, int i, final String test) throws IOException {
+ private int generateIf(byte[] byteCodes, int i,
+ final Variable v2, final Variable v1,
+ final String test) throws IOException {
int indx = i + readIntArg(byteCodes, i);
- out.append("if (stack.pop() ").append(test).append(" stack.pop()) { gt = " + indx);
- out.append("; continue; }");
+ out.append("if (").append(v1)
+ .append(' ').append(test).append(' ')
+ .append(v2).append(") { gt = " + indx)
+ .append("; continue; }");
return i + 2;
}
@@ -701,12 +1182,22 @@
final int indxLo = byteCodes[offsetInstruction + 2];
return (indxHi & 0xffffff00) | (indxLo & 0xff);
}
+ private int readInt4(byte[] byteCodes, int offsetInstruction) {
+ final int d = byteCodes[offsetInstruction + 0] << 24;
+ final int c = byteCodes[offsetInstruction + 1] << 16;
+ final int b = byteCodes[offsetInstruction + 2] << 8;
+ final int a = byteCodes[offsetInstruction + 3];
+ return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
+ }
+ private int readByte(byte[] byteCodes, int offsetInstruction) {
+ return byteCodes[offsetInstruction] & 0xff;
+ }
- private static int countArgs(String descriptor, boolean[] hasReturnType, StringBuilder sig) {
- int cnt = 0;
+ private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
int i = 0;
Boolean count = null;
boolean array = false;
+ sig.append("__");
int firstPos = sig.length();
while (i < descriptor.length()) {
char ch = descriptor.charAt(i++);
@@ -717,9 +1208,6 @@
case ')':
count = false;
continue;
- case 'A':
- array = true;
- break;
case 'B':
case 'C':
case 'D':
@@ -729,63 +1217,76 @@
case 'S':
case 'Z':
if (count) {
- cnt++;
if (array) {
- sig.append('A');
+ sig.append("_3");
}
sig.append(ch);
+ if (ch == 'J' || ch == 'D') {
+ cnt.append('1');
+ } else {
+ cnt.append('0');
+ }
} else {
- hasReturnType[0] = true;
sig.insert(firstPos, ch);
if (array) {
- sig.insert(firstPos, 'A');
+ returnType[0] = '[';
+ sig.insert(firstPos, "_3");
+ } else {
+ returnType[0] = ch;
}
}
array = false;
continue;
case 'V':
assert !count;
- hasReturnType[0] = false;
+ returnType[0] = 'V';
sig.insert(firstPos, 'V');
continue;
case 'L':
int next = descriptor.indexOf(';', i);
+ String realSig = mangleSig(descriptor, i - 1, next + 1);
if (count) {
- cnt++;
if (array) {
- sig.append('A');
+ sig.append("_3");
}
- sig.append(ch);
- sig.append(descriptor.substring(i, next).replace('/', '_'));
+ sig.append(realSig);
+ cnt.append('0');
} else {
- sig.insert(firstPos, descriptor.substring(i, next).replace('/', '_'));
- sig.insert(firstPos, ch);
+ sig.insert(firstPos, realSig);
if (array) {
- sig.insert(firstPos, 'A');
+ sig.insert(firstPos, "_3");
}
- hasReturnType[0] = true;
+ returnType[0] = 'L';
}
i = next + 1;
+ array = false;
continue;
case '[':
- //arrays++;
+ array = true;
continue;
default:
- break; // invalid character
+ throw new IllegalStateException("Invalid char: " + ch);
}
}
- return cnt;
+ }
+
+ private static String mangleSig(String txt, int first, int last) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = first; i < last; i++) {
+ final char ch = txt.charAt(i);
+ switch (ch) {
+ case '/': sb.append('_'); break;
+ case '_': sb.append("_1"); break;
+ case ';': sb.append("_2"); break;
+ case '[': sb.append("_3"); break;
+ default: sb.append(ch); break;
+ }
+ }
+ return sb.toString();
}
- private void generateStaticField(Variable v) throws IOException {
- out.append("\nvar ")
- .append(jc.getName().getInternalName().replace('/', '_'))
- .append('_').append(v.getName()).append(" = 0;");
- }
-
- private String findMethodName(Method m) {
+ private static String findMethodName(MethodData m, StringBuilder cnt) {
StringBuilder name = new StringBuilder();
- String descr = m.getDescriptor();
if ("".equals(m.getName())) { // NOI18N
name.append("cons"); // NOI18N
} else if ("".equals(m.getName())) { // NOI18N
@@ -794,97 +1295,106 @@
name.append(m.getName());
}
- boolean hasReturn[] = { false };
- countArgs(findDescriptor(m.getDescriptor()), hasReturn, name);
+ countArgs(m.getInternalSig(), new char[1], name, cnt);
return name.toString();
}
- private String findMethodName(CPMethodInfo mi, int[] cnt, boolean[] hasReturn) {
+ static String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) {
StringBuilder name = new StringBuilder();
- String descr = mi.getDescriptor();
- if ("".equals(mi.getName())) { // NOI18N
+ String descr = mi[2];//mi.getDescriptor();
+ String nm= mi[1];
+ if ("".equals(nm)) { // NOI18N
name.append("cons"); // NOI18N
} else {
- name.append(mi.getName());
+ name.append(nm);
}
- cnt[0] = countArgs(findDescriptor(mi.getDescriptor()), hasReturn, name);
+ countArgs(descr, returnType, name, cnt);
return name.toString();
}
- private int invokeStaticMethod(byte[] byteCodes, int i, boolean isStatic)
+ private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
throws IOException {
int methodIndex = readIntArg(byteCodes, i);
- CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex);
- boolean[] hasReturn = { false };
- int[] cnt = { 0 };
- String mn = findMethodName(mi, cnt, hasReturn);
- out.append("{ ");
- for (int j = cnt[0] - 1; j >= 0; j--) {
- out.append("var v" + j).append(" = stack.pop(); ");
+ String[] mi = jc.getFieldInfoName(methodIndex);
+ char[] returnType = { 'V' };
+ StringBuilder cnt = new StringBuilder();
+ String mn = findMethodName(mi, cnt, returnType);
+
+ final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
+ final Variable[] vars = new Variable[numArguments];
+
+ for (int j = numArguments - 1; j >= 0; --j) {
+ vars[j] = mapper.pop();
}
-
- if (hasReturn[0]) {
- out.append("stack.push(");
+
+ if (returnType[0] != 'V') {
+ out.append("var ")
+ .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
+ .append(" = ");
}
- final String in = mi.getClassName().getInternalName();
- out.append(in.replace('/', '_'));
- out.append('_');
+
+ final String in = mi[0];
+ out.append(accessClass(in.replace('/', '_')));
+ out.append("(false).");
+ if (mn.startsWith("cons_")) {
+ out.append("constructor.");
+ }
out.append(mn);
- out.append('(');
- String sep = "";
- if (!isStatic) {
- out.append("stack.pop()");
- sep = ", ";
+ if (isStatic) {
+ out.append('(');
+ } else {
+ out.append(".call(");
}
- for (int j = 0; j < cnt[0]; j++) {
- out.append(sep);
- out.append("v" + j);
- sep = ", ";
+ if (numArguments > 0) {
+ out.append(vars[0]);
+ for (int j = 1; j < numArguments; ++j) {
+ out.append(", ");
+ out.append(vars[j]);
+ }
}
- out.append(")");
- if (hasReturn[0]) {
- out.append(")");
- }
- out.append("; }");
+ out.append(");");
i += 2;
addReference(in);
return i;
}
- private int invokeVirtualMethod(byte[] byteCodes, int i)
+ private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
throws IOException {
int methodIndex = readIntArg(byteCodes, i);
- CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex);
- boolean[] hasReturn = { false };
- int[] cnt = { 0 };
- String mn = findMethodName(mi, cnt, hasReturn);
- out.append("{ ");
- for (int j = cnt[0] - 1; j >= 0; j--) {
- out.append("var v" + j).append(" = stack.pop(); ");
+ String[] mi = jc.getFieldInfoName(methodIndex);
+ char[] returnType = { 'V' };
+ StringBuilder cnt = new StringBuilder();
+ String mn = findMethodName(mi, cnt, returnType);
+
+ final int numArguments = cnt.length() + 1;
+ final Variable[] vars = new Variable[numArguments];
+
+ for (int j = numArguments - 1; j >= 0; --j) {
+ vars[j] = mapper.pop();
}
- out.append("var self = stack.pop(); ");
- if (hasReturn[0]) {
- out.append("stack.push(");
+
+ if (returnType[0] != 'V') {
+ out.append("var ")
+ .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
+ .append(" = ");
}
- out.append("self.");
+
+ out.append(vars[0]).append('.');
out.append(mn);
out.append('(');
- out.append("self");
- for (int j = 0; j < cnt[0]; j++) {
- out.append(", ");
- out.append("v" + j);
+ String sep = "";
+ for (int j = 1; j < numArguments; ++j) {
+ out.append(sep);
+ out.append(vars[j]);
+ sep = ", ";
}
- out.append(")");
- if (hasReturn[0]) {
- out.append(")");
- }
- out.append("; }");
+ out.append(");");
i += 2;
return i;
}
-
- private void addReference(String cn) {
- if (references != null) {
- references.add(cn);
+
+ private void addReference(String cn) throws IOException {
+ if (requireReference(cn)) {
+ debug(" /* needs " + cn + " */");
}
}
@@ -902,61 +1412,220 @@
}
}
- private String encodeConstant(CPEntry entry) {
- final String v;
- if (entry instanceof CPClassInfo) {
- v = "new java_lang_Class";
- } else if (entry instanceof CPStringInfo) {
- v = "\"" + entry.getValue().toString().replace("\"", "\\\"") + "\"";
- } else {
- v = entry.getValue().toString();
+ private String encodeConstant(int entryIndex) throws IOException {
+ String[] classRef = { null };
+ String s = jc.stringValue(entryIndex, classRef);
+ if (classRef[0] != null) {
+ addReference(classRef[0]);
+ s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
}
- return v;
+ return s;
}
- private String findDescriptor(String d) {
- return d.replace('[', 'A');
+ private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
+ byte[] arr = m.findAnnotationData(true);
+ if (arr == null) {
+ return null;
+ }
+ final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
+ class P extends AnnotationParser {
+ public P() {
+ super(false);
+ }
+
+ int cnt;
+ String[] args = new String[30];
+ String body;
+
+ @Override
+ protected void visitAttr(String type, String attr, String at, String value) {
+ if (type.equals(jvmType)) {
+ if ("body".equals(attr)) {
+ body = value;
+ } else if ("args".equals(attr)) {
+ args[cnt++] = value;
+ } else {
+ throw new IllegalArgumentException(attr);
+ }
+ }
+ }
+ }
+ P p = new P();
+ p.parse(arr, jc);
+ if (p.body == null) {
+ return null;
+ }
+ StringBuilder cnt = new StringBuilder();
+ final String mn = findMethodName(m, cnt);
+ out.append(prefix).append(mn);
+ out.append(" = function(");
+ String space = "";
+ int index = 0;
+ for (int i = 0; i < cnt.length(); i++) {
+ out.append(space);
+ space = outputArg(out, p.args, index);
+ index++;
+ }
+ out.append(") {").append("\n");
+ out.append(p.body);
+ out.append("\n}\n");
+ return mn;
+ }
+ private static String className(ClassData jc) {
+ //return jc.getName().getInternalName().replace('/', '_');
+ return jc.getClassName().replace('/', '_');
+ }
+
+ private static String[] findAnnotation(
+ byte[] arr, ClassData cd, final String className,
+ final String... attrNames
+ ) throws IOException {
+ if (arr == null) {
+ return null;
+ }
+ final String[] values = new String[attrNames.length];
+ final boolean[] found = { false };
+ final String jvmType = "L" + className.replace('.', '/') + ";";
+ AnnotationParser ap = new AnnotationParser(false) {
+ @Override
+ protected void visitAttr(String type, String attr, String at, String value) {
+ if (type.equals(jvmType)) {
+ found[0] = true;
+ for (int i = 0; i < attrNames.length; i++) {
+ if (attrNames[i].equals(attr)) {
+ values[i] = value;
+ }
+ }
+ }
+ }
+
+ };
+ ap.parse(arr, cd);
+ return found[0] ? values : null;
}
- private boolean javaScriptBody(Method m, boolean isStatic) throws IOException {
- final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/'));
- Annotation a = m.getAnnotation(extraAnn);
- if (a != null) {
- final ElementValue annVal = a.getComponent("body").getValue();
- String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString();
+ private CharSequence initField(FieldData v) {
+ final String is = v.getInternalSig();
+ if (is.length() == 1) {
+ switch (is.charAt(0)) {
+ case 'S':
+ case 'J':
+ case 'B':
+ case 'Z':
+ case 'C':
+ case 'I': return " = 0;";
+ case 'F':
+ case 'D': return " = 0.0;";
+ default:
+ throw new IllegalStateException(is);
+ }
+ }
+ return " = null;";
+ }
+
+ private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
+ AnnotationParser ap = new AnnotationParser(true) {
+ int anno;
+ int cnt;
- final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue();
- final int len = arrVal.getValues().length;
- String[] names = new String[len];
- for (int i = 0; i < len; i++) {
- names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString();
+ @Override
+ protected void visitAnnotationStart(String type) throws IOException {
+ if (anno++ > 0) {
+ out.append(",");
+ }
+ out.append('"').append(type).append("\" : {\n");
+ cnt = 0;
}
- out.append("\nfunction ").append(
- jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m));
- out.append("(");
- String space;
- int index;
- if (!isStatic) {
- out.append(names[0]);
- space = ",";
- index = 1;
+
+ @Override
+ protected void visitAnnotationEnd(String type) throws IOException {
+ out.append("\n}\n");
+ }
+
+ @Override
+ protected void visitAttr(String type, String attr, String attrType, String value)
+ throws IOException {
+ if (attr == null) {
+ return;
+ }
+ if (cnt++ > 0) {
+ out.append(",\n");
+ }
+ out.append(attr).append("__").append(attrType).append(" : ").append(value);
+ }
+ };
+ ap.parse(data, cd);
+ }
+
+ private static String outputArg(Appendable out, String[] args, int indx) throws IOException {
+ final String name = args[indx];
+ if (name == null) {
+ return "";
+ }
+ if (name.contains(",")) {
+ throw new IOException("Wrong parameter with ',': " + name);
+ }
+ out.append(name);
+ return ",";
+ }
+
+ private static void emit(final Appendable out,
+ final String format,
+ final CharSequence... params) throws IOException {
+ final int length = format.length();
+
+ int processed = 0;
+ int paramOffset = format.indexOf('@');
+ while ((paramOffset != -1) && (paramOffset < (length - 1))) {
+ final char paramChar = format.charAt(paramOffset + 1);
+ if ((paramChar >= '1') && (paramChar <= '9')) {
+ final int paramIndex = paramChar - '0' - 1;
+
+ out.append(format, processed, paramOffset);
+ out.append(params[paramIndex]);
+
+ ++paramOffset;
+ processed = paramOffset + 1;
+ }
+
+ paramOffset = format.indexOf('@', paramOffset + 1);
+ }
+
+ out.append(format, processed, length);
+ }
+
+ private void generateCatch(TrapData[] traps) throws IOException {
+ out.append("} catch (e) {\n");
+ int finallyPC = -1;
+ for (TrapData e : traps) {
+ if (e == null) {
+ break;
+ }
+ if (e.catch_cpx != 0) { //not finally
+ final String classInternalName = jc.getClassName(e.catch_cpx);
+ addReference(classInternalName);
+ if ("java/lang/Throwable".equals(classInternalName)) {
+ out.append("if (e.$instOf_java_lang_Throwable) {");
+ out.append(" var stA0 = e;");
+ out.append("} else {");
+ out.append(" var stA0 = vm.java_lang_Throwable(true);");
+ out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
+ out.append("}");
+ out.append("gt=" + e.handler_pc + "; continue;");
+ } else {
+ out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
+ out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
+ out.append("}\n");
+ }
} else {
- space = "";
- index = 0;
+ finallyPC = e.handler_pc;
}
- List args = m.getParameters();
- for (int i = 0; i < args.size(); i++) {
- out.append(space);
- out.append(names[index]);
- final String desc = findDescriptor(args.get(i).getDescriptor());
- index++;
- space = ",";
- }
- out.append(") {").append("\n");
- out.append(body);
- out.append("\n}\n");
- return true;
}
- return false;
+ if (finallyPC == -1) {
+ out.append("throw e;");
+ } else {
+ out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
+ }
+ out.append("\n}");
}
}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java
--- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-package org.apidesign.vm4brwsr;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/** Generator of JavaScript from bytecode of classes on classpath of the VM.
- *
- * @author Jaroslav Tulach
- */
-final class GenJS {
- private GenJS() {}
-
- public static void main(String... args) throws IOException {
- if (args.length < 2) {
- System.err.println("Usage: java -cp ... -jar ... java/lang/Class org/your/App ...");
- return;
- }
-
- Writer w = new BufferedWriter(new FileWriter(args[0]));
- List classes = Arrays.asList(args).subList(1, args.length);
- compile(w, classes);
- w.close();
- }
-
- static void compile(Appendable out, String... names) throws IOException {
- compile(out, Arrays.asList(names));
- }
- static void compile(Appendable out, List names) throws IOException {
- for (String baseClass : names) {
- Map processed = new HashMap();
- LinkedList toProcess = new LinkedList();
- toProcess.add(baseClass);
- for (;;) {
- String name = null;
- Iterator it = toProcess.iterator();
- while (it.hasNext() && name == null) {
- String n = it.next();
- if (processed.get(n) != null) {
- continue;
- }
- name = n;
- }
- if (name == null) {
- break;
- }
- if (name.startsWith("java/")
- && !name.equals("java/lang/Object")
- && !name.equals("java/lang/Class")
- && !name.equals("java/lang/Number")
- && !name.equals("java/lang/Integer")
- && !name.equals("java/lang/Throwable")
- && !name.equals("java/lang/Exception")
- && !name.equals("java/lang/RuntimeException")
- && !name.equals("java/lang/UnsupportedOperationException")
- && !name.equals("java/lang/String")
- && !name.equals("java/lang/String$CaseInsensitiveComparator")
- && !name.equals("java/lang/StringBuilder")
- && !name.equals("java/lang/AbstractStringBuilder")
- ) {
- processed.put(name, "");
- continue;
- }
- InputStream is = loadClass(name);
- if (is == null) {
- throw new IOException("Can't find class " + name);
- }
- LinkedList scripts = new LinkedList();
- try {
- String initCode = ByteCodeToJavaScript.compile(is, out, toProcess, scripts);
- processed.put(name, initCode == null ? "" : initCode);
- } catch (RuntimeException ex) {
- if (out instanceof CharSequence) {
- CharSequence seq = (CharSequence)out;
- int lastBlock = seq.length();
- while (lastBlock-- >= 0) {
- if (seq.charAt(lastBlock) == '{') {
- break;
- }
- }
- throw new IOException("Error while compiling " + name + "\n"
- + seq.subSequence(lastBlock + 1, seq.length()), ex
- );
- } else {
- throw new IOException("Error while compiling " + name + "\n"
- + out, ex
- );
- }
- }
- for (String resource : scripts) {
- InputStream emul = GenJS.class.getResourceAsStream(resource);
- if (emul == null) {
- throw new IOException("Can't find " + resource);
- }
- readResource(emul, out);
- }
- }
-
- Collections.reverse(toProcess);
-
- for (String clazz : toProcess) {
- String initCode = processed.remove(clazz);
- if (initCode != null) {
- out.append(initCode).append("\n");
- }
- }
- }
-
- }
- private static void readResource(InputStream emul, Appendable out) throws IOException {
- try {
- int state = 0;
- for (;;) {
- int ch = emul.read();
- if (ch == -1) {
- break;
- }
- if (ch < 0 || ch > 255) {
- throw new IOException("Invalid char in emulation " + ch);
- }
- switch (state) {
- case 0:
- if (ch == '/') {
- state = 1;
- } else {
- out.append((char)ch);
- }
- break;
- case 1:
- if (ch == '*') {
- state = 2;
- } else {
- out.append('/').append((char)ch);
- state = 0;
- }
- break;
- case 2:
- if (ch == '*') {
- state = 3;
- }
- break;
- case 3:
- if (ch == '/') {
- state = 0;
- } else {
- state = 2;
- }
- break;
- }
- }
- } finally {
- emul.close();
- }
- }
-
- private static InputStream loadClass(String name) throws IOException {
- Enumeration en = ClassLoader.getSystemClassLoader().getResources(name + ".class");
- URL u = null;
- while (en.hasMoreElements()) {
- u = en.nextElement();
- }
- if (u == null) {
- throw new IOException("Can't find " + name);
- }
- return u.openStream();
- }
-
-}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,142 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.IOException;
+import org.apidesign.javap.RuntimeConstants;
+import org.apidesign.javap.TypeArray;
+
+final class LocalsMapper {
+ private final TypeArray argTypeRecords;
+ private final TypeArray localTypeRecords;
+
+ public LocalsMapper(final TypeArray stackMapArgs) {
+ final TypeArray initTypeRecords = new TypeArray();
+ updateRecords(initTypeRecords, stackMapArgs);
+
+ argTypeRecords = initTypeRecords;
+ localTypeRecords = new TypeArray(initTypeRecords);
+ }
+
+ public void outputArguments(final Appendable out, boolean isStatic) throws IOException {
+ final int argRecordCount = argTypeRecords.getSize();
+ int first = isStatic ? 0 : 1;
+ if (argRecordCount > first) {
+ Variable variable = getVariable(argTypeRecords, first);
+ out.append(variable);
+
+ int i = first + (variable.isCategory2() ? 2 : 1);
+ while (i < argRecordCount) {
+ variable = getVariable(argTypeRecords, i);
+ out.append(", ");
+ out.append(variable);
+ i += variable.isCategory2() ? 2 : 1;
+ }
+ }
+ }
+
+ public void syncWithFrameLocals(final TypeArray frameLocals) {
+ updateRecords(localTypeRecords, frameLocals);
+ }
+
+ public Variable setI(final int index) {
+ return setT(index, VarType.INTEGER);
+ }
+
+ public Variable setL(final int index) {
+ return setT(index, VarType.LONG);
+ }
+
+ public Variable setF(final int index) {
+ return setT(index, VarType.FLOAT);
+ }
+
+ public Variable setD(final int index) {
+ return setT(index, VarType.DOUBLE);
+ }
+
+ public Variable setA(final int index) {
+ return setT(index, VarType.REFERENCE);
+ }
+
+ public Variable setT(final int index, final int type) {
+ updateRecord(localTypeRecords, index, type);
+ return Variable.getLocalVariable(type, index);
+ }
+
+ public Variable getI(final int index) {
+ return getT(index, VarType.INTEGER);
+ }
+
+ public Variable getL(final int index) {
+ return getT(index, VarType.LONG);
+ }
+
+ public Variable getF(final int index) {
+ return getT(index, VarType.FLOAT);
+ }
+
+ public Variable getD(final int index) {
+ return getT(index, VarType.DOUBLE);
+ }
+
+ public Variable getA(final int index) {
+ return getT(index, VarType.REFERENCE);
+ }
+
+ public Variable getT(final int index, final int type) {
+ final int oldRecordValue = localTypeRecords.get(index);
+ if ((oldRecordValue & 0xff) != type) {
+ throw new IllegalStateException("Type mismatch");
+ }
+
+ return Variable.getLocalVariable(type, index);
+ }
+
+ private static void updateRecords(final TypeArray typeRecords,
+ final TypeArray stackMapTypes) {
+ final int srcSize = stackMapTypes.getSize();
+ for (int i = 0, dstIndex = 0; i < srcSize; ++i) {
+ final int smType = stackMapTypes.get(i);
+ if (smType == RuntimeConstants.ITEM_Bogus) {
+ ++dstIndex;
+ continue;
+ }
+ final int varType = VarType.fromStackMapType(smType);
+ updateRecord(typeRecords, dstIndex, varType);
+ dstIndex += VarType.isCategory2(varType) ? 2 : 1;
+ }
+ }
+
+ private static void updateRecord(final TypeArray typeRecords,
+ final int index, final int type) {
+ if (typeRecords.getSize() < (index + 1)) {
+ typeRecords.setSize(index + 1);
+ }
+
+ final int oldRecordValue = typeRecords.get(index);
+ final int usedTypesMask =
+ (oldRecordValue >> 8) | (1 << type);
+ typeRecords.set(index, (usedTypesMask << 8) | type);
+ }
+
+ private static Variable getVariable(final TypeArray typeRecords,
+ final int index) {
+ return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Main.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,50 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/** Generator of JavaScript from bytecode of classes on classpath of the VM
+ * with a Main method.
+ *
+ * @author Jaroslav Tulach
+ */
+final class Main {
+ private Main() {}
+
+ public static void main(String... args) throws IOException {
+ if (args.length < 2) {
+ System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012");
+ System.err.println("Usage: java -cp ... -jar ... java/lang/Class org/your/App ...");
+ return;
+ }
+
+ Writer w = new BufferedWriter(new FileWriter(args[0]));
+ StringArray classes = StringArray.asList(args);
+ classes.delete(0);
+ try {
+ Bck2Brwsr.generate(w, Main.class.getClassLoader(),
+ classes.toArray());
+ } finally {
+ w.close();
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,194 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import org.apidesign.javap.TypeArray;
+
+final class StackMapper {
+ private final TypeArray stackTypeIndexPairs;
+ private int[] typeCounters;
+ private int[] typeMaxCounters;
+
+ public StackMapper() {
+ stackTypeIndexPairs = new TypeArray();
+ typeCounters = new int[VarType.LAST + 1];
+ typeMaxCounters = new int[VarType.LAST + 1];
+ }
+
+ public void clear() {
+ for (int type = 0; type <= VarType.LAST; ++type) {
+ typeCounters[type] = 0;
+ }
+ stackTypeIndexPairs.clear();
+ }
+
+ public void syncWithFrameStack(final TypeArray frameStack) {
+ clear();
+
+ final int size = frameStack.getSize();
+ for (int i = 0; i < size; ++i) {
+ pushTypeImpl(VarType.fromStackMapType(frameStack.get(i)));
+ }
+ }
+
+ public Variable pushI() {
+ return pushT(VarType.INTEGER);
+ }
+
+ public Variable pushL() {
+ return pushT(VarType.LONG);
+ }
+
+ public Variable pushF() {
+ return pushT(VarType.FLOAT);
+ }
+
+ public Variable pushD() {
+ return pushT(VarType.DOUBLE);
+ }
+
+ public Variable pushA() {
+ return pushT(VarType.REFERENCE);
+ }
+
+ public Variable pushT(final int type) {
+ return getVariable(pushTypeImpl(type));
+ }
+
+ public Variable popI() {
+ return popT(VarType.INTEGER);
+ }
+
+ public Variable popL() {
+ return popT(VarType.LONG);
+ }
+
+ public Variable popF() {
+ return popT(VarType.FLOAT);
+ }
+
+ public Variable popD() {
+ return popT(VarType.DOUBLE);
+ }
+
+ public Variable popA() {
+ return popT(VarType.REFERENCE);
+ }
+
+ public Variable popT(final int type) {
+ final Variable variable = getT(0, type);
+ popImpl(1);
+ return variable;
+ }
+
+ public Variable pop() {
+ final Variable variable = get(0);
+ popImpl(1);
+ return variable;
+ }
+
+ public void pop(final int count) {
+ final int stackSize = stackTypeIndexPairs.getSize();
+ if (count > stackSize) {
+ throw new IllegalStateException("Stack underflow");
+ }
+ popImpl(count);
+ }
+
+ public Variable getI(final int indexFromTop) {
+ return getT(indexFromTop, VarType.INTEGER);
+ }
+
+ public Variable getL(final int indexFromTop) {
+ return getT(indexFromTop, VarType.LONG);
+ }
+
+ public Variable getF(final int indexFromTop) {
+ return getT(indexFromTop, VarType.FLOAT);
+ }
+
+ public Variable getD(final int indexFromTop) {
+ return getT(indexFromTop, VarType.DOUBLE);
+ }
+
+ public Variable getA(final int indexFromTop) {
+ return getT(indexFromTop, VarType.REFERENCE);
+ }
+
+ public Variable getT(final int indexFromTop, final int type) {
+ final int stackSize = stackTypeIndexPairs.getSize();
+ if (indexFromTop >= stackSize) {
+ throw new IllegalStateException("Stack underflow");
+ }
+ final int stackValue =
+ stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
+ if ((stackValue & 0xff) != type) {
+ throw new IllegalStateException("Type mismatch");
+ }
+
+ return getVariable(stackValue);
+ }
+
+ public Variable get(final int indexFromTop) {
+ final int stackSize = stackTypeIndexPairs.getSize();
+ if (indexFromTop >= stackSize) {
+ throw new IllegalStateException("Stack underflow");
+ }
+ final int stackValue =
+ stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
+
+ return getVariable(stackValue);
+ }
+
+ private int pushTypeImpl(final int type) {
+ final int count = typeCounters[type];
+ final int value = (count << 8) | (type & 0xff);
+ incCounter(type);
+ stackTypeIndexPairs.add(value);
+
+ return value;
+ }
+
+ private void popImpl(final int count) {
+ final int stackSize = stackTypeIndexPairs.getSize();
+ for (int i = stackSize - count; i < stackSize; ++i) {
+ final int value = stackTypeIndexPairs.get(i);
+ decCounter(value & 0xff);
+ }
+
+ stackTypeIndexPairs.setSize(stackSize - count);
+ }
+
+ private void incCounter(final int type) {
+ final int newValue = ++typeCounters[type];
+ if (typeMaxCounters[type] < newValue) {
+ typeMaxCounters[type] = newValue;
+ }
+ }
+
+ private void decCounter(final int type) {
+ --typeCounters[type];
+ }
+
+ public Variable getVariable(final int typeAndIndex) {
+ final int type = typeAndIndex & 0xff;
+ final int index = typeAndIndex >> 8;
+
+ return Variable.getStackVariable(type, index);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,97 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+class StringArray {
+ private String[] arr;
+
+ public StringArray() {
+ }
+
+ private StringArray(String[] arr) {
+ this.arr = arr;
+ }
+
+ public void add(String s) {
+ if (arr == null) {
+ arr = new String[1];
+ } else {
+ String[] tmp = new String[arr.length + 1];
+ for (int i = 0; i < arr.length; i++) {
+ tmp[i] = arr[i];
+ }
+ arr = tmp;
+ }
+ arr[arr.length - 1] = s;
+ }
+
+ public String[] toArray() {
+ return arr == null ? new String[0] : arr;
+ }
+
+ static StringArray asList(String... names) {
+ return new StringArray(names);
+ }
+
+ void reverse() {
+ for (int i = 0, j = arr.length; i < j; i++) {
+ String s = arr[i];
+ arr[i] = arr[--j];
+ arr[j] = s;
+ }
+ }
+
+ boolean contains(String n) {
+ if (arr == null) {
+ return false;
+ }
+ for (int i = 0; i < arr.length; i++) {
+ if (n.equals(arr[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void delete(int indx) {
+ if (arr == null || indx < 0 || indx >= arr.length) {
+ return;
+ }
+ String[] tmp = new String[arr.length - 1];
+ for (int i = 0, j = 0; i < arr.length; i++) {
+ if (i != indx) {
+ tmp[j++] = arr[i];
+ }
+ }
+ arr = tmp;
+ }
+
+ int indexOf(String ic) {
+ for (int i = 0; i < arr.length; i++) {
+ if (ic.equals(arr[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VM.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,220 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/** Generator of JavaScript from bytecode of classes on classpath of the VM.
+ *
+ * @author Jaroslav Tulach
+ */
+class VM extends ByteCodeToJavaScript {
+ public VM(Appendable out) {
+ super(out);
+ }
+
+ static {
+ // uses VMLazy to load dynamic classes
+ VMLazy.init();
+ }
+
+ @Override
+ boolean debug(String msg) throws IOException {
+ return false;
+ }
+
+ static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
+ new VM(out).doCompile(l, names);
+ }
+ protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
+ out.append("(function VM(global) {");
+ out.append("\n var vm = {};");
+ StringArray processed = new StringArray();
+ StringArray initCode = new StringArray();
+ for (String baseClass : names.toArray()) {
+ references.add(baseClass);
+ for (;;) {
+ String name = null;
+ for (String n : references.toArray()) {
+ if (processed.contains(n)) {
+ continue;
+ }
+ name = n;
+ }
+ if (name == null) {
+ break;
+ }
+ InputStream is = loadClass(l, name);
+ if (is == null) {
+ throw new IOException("Can't find class " + name);
+ }
+ try {
+ String ic = compile(is);
+ processed.add(name);
+ initCode.add(ic == null ? "" : ic);
+ } catch (RuntimeException ex) {
+ if (out instanceof CharSequence) {
+ CharSequence seq = (CharSequence)out;
+ int lastBlock = seq.length();
+ while (lastBlock-- > 0) {
+ if (seq.charAt(lastBlock) == '{') {
+ break;
+ }
+ }
+ throw new IOException("Error while compiling " + name + "\n"
+ + seq.subSequence(lastBlock + 1, seq.length()), ex
+ );
+ } else {
+ throw new IOException("Error while compiling " + name + "\n"
+ + out, ex
+ );
+ }
+ }
+ }
+
+ for (String resource : scripts.toArray()) {
+ while (resource.startsWith("/")) {
+ resource = resource.substring(1);
+ }
+ InputStream emul = l.get(resource);
+ if (emul == null) {
+ throw new IOException("Can't find " + resource);
+ }
+ readResource(emul, out);
+ }
+ scripts = new StringArray();
+
+ StringArray toInit = StringArray.asList(references.toArray());
+ toInit.reverse();
+
+ for (String ic : toInit.toArray()) {
+ int indx = processed.indexOf(ic);
+ if (indx >= 0) {
+ out.append(initCode.toArray()[indx]).append("\n");
+ initCode.toArray()[indx] = "";
+ }
+ }
+ }
+ out.append(
+ " global.bck2brwsr = function() {\n"
+ + " var args = arguments;\n"
+ + " var loader = {};\n"
+ + " loader.vm = vm;\n"
+ + " loader.loadClass = function(name) {\n"
+ + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
+ + " var fn = vm[attr];\n"
+ + " if (fn) return fn(false);\n"
+ + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
+ + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
+ + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
+ + " }\n"
+ + " if (args[0]) {\n"
+ + " vm.loadClass = loader.loadClass;\n"
+ + " vm.loadBytes = function(name) {\n"
+ + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
+ + " return args[0](name);\n"
+ + " }\n"
+ + " }\n"
+ + " return loader;\n"
+ + " };\n");
+ out.append("}(this));");
+ }
+ private static void readResource(InputStream emul, Appendable out) throws IOException {
+ try {
+ int state = 0;
+ for (;;) {
+ int ch = emul.read();
+ if (ch == -1) {
+ break;
+ }
+ if (ch < 0 || ch > 255) {
+ throw new IOException("Invalid char in emulation " + ch);
+ }
+ switch (state) {
+ case 0:
+ if (ch == '/') {
+ state = 1;
+ } else {
+ out.append((char)ch);
+ }
+ break;
+ case 1:
+ if (ch == '*') {
+ state = 2;
+ } else {
+ out.append('/').append((char)ch);
+ state = 0;
+ }
+ break;
+ case 2:
+ if (ch == '*') {
+ state = 3;
+ }
+ break;
+ case 3:
+ if (ch == '/') {
+ state = 0;
+ } else {
+ state = 2;
+ }
+ break;
+ }
+ }
+ } finally {
+ emul.close();
+ }
+ }
+
+ private static InputStream loadClass(Bck2Brwsr.Resources l, String name) throws IOException {
+ return l.get(name + ".class"); // NOI18N
+ }
+
+ static String toString(String name) throws IOException {
+ StringBuilder sb = new StringBuilder();
+// compile(sb, name);
+ return sb.toString().toString();
+ }
+
+ private StringArray scripts = new StringArray();
+ private StringArray references = new StringArray();
+
+ @Override
+ protected boolean requireReference(String cn) {
+ if (references.contains(cn)) {
+ return false;
+ }
+ references.add(cn);
+ return true;
+ }
+
+ @Override
+ protected void requireScript(String resourcePath) {
+ scripts.add(resourcePath);
+ }
+
+ @Override
+ String assignClass(String className) {
+ return "vm." + className + " = ";
+ }
+
+ @Override
+ String accessClass(String className) {
+ return "vm." + className;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,158 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+final class VMLazy {
+ private final Object loader;
+ private final Object[] args;
+
+ private VMLazy(Object loader, Object[] args) {
+ this.loader = loader;
+ this.args = args;
+ }
+
+ static void init() {
+ }
+
+ @JavaScriptBody(args={"l", "res", "args" }, body = ""
+ + "\ntry {"
+ + "\n return args[0](res.toString());"
+ + "\n} catch (x) {"
+ + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
+ + "\n}")
+ private static native byte[] read(Object l, String res, Object[] args);
+
+ static Object load(Object loader, String name, Object[] arguments)
+ throws IOException, ClassNotFoundException {
+ return new VMLazy(loader, arguments).load(name, false);
+ }
+
+ private Object load(String name, boolean instance)
+ throws IOException, ClassNotFoundException {
+ String res = name.replace('.', '/') + ".class";
+ byte[] arr = read(loader, res, args);
+ if (arr == null) {
+ throw new ClassNotFoundException(name);
+ }
+// beingDefined(loader, name);
+ StringBuilder out = new StringBuilder();
+ out.append("var loader = arguments[0];\n");
+ out.append("var vm = loader.vm;\n");
+ int prelude = out.length();
+ String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr));
+ String code = out.toString().toString();
+// dump("Loading " + name);
+ dump(code);
+ String under = name.replace('.', '_');
+ Object fn = applyCode(loader, under, code, instance);
+
+ if (!initCode.isEmpty()) {
+ out.setLength(prelude);
+ out.append(initCode);
+ code = out.toString().toString();
+ dump(code);
+ applyCode(loader, null, code, false);
+ }
+
+ return fn;
+ }
+
+// @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());")
+ static void dump(String s) {
+ }
+
+/* possibly not needed:
+ @JavaScriptBody(args = {"loader", "n" }, body =
+ "var cls = n.replace__Ljava_lang_String_2CC(n, '.','_').toString();" +
+ "loader.vm[cls] = true;\n"
+ )
+ private static native void beingDefined(Object loader, String name);
+*/
+
+
+ @JavaScriptBody(args = {"loader", "name", "script", "instance" }, body =
+ "try {\n" +
+ " new Function(script)(loader, name);\n" +
+ "} catch (ex) {\n" +
+ " throw 'Cannot compile ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" +
+ "}\n" +
+ "return name != null ? vm[name](instance) : null;\n"
+ )
+ private static native Object applyCode(Object loader, String name, String script, boolean instance);
+
+
+ private static final class Gen extends ByteCodeToJavaScript {
+ private final VMLazy lazy;
+
+ public Gen(VMLazy vm, Appendable out) {
+ super(out);
+ this.lazy = vm;
+ }
+
+ @JavaScriptBody(args = {"n"},
+ body =
+ "var cls = n.replace__Ljava_lang_String_2CC('/','_').toString();"
+ + "\nvar dot = n.replace__Ljava_lang_String_2CC('/','.').toString();"
+ + "\nvar lazy = this.fld_lazy;"
+ + "\nvar loader = lazy.fld_loader;"
+ + "\nvar vm = loader.vm;"
+ + "\nif (vm[cls]) return false;"
+ + "\nvm[cls] = function() {"
+ + "\n var instance = arguments.length == 0 || arguments[0] === true;"
+ + "\n return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2Z(dot, instance);"
+ + "\n};"
+ + "\nreturn true;")
+ @Override
+ protected boolean requireReference(String internalClassName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void requireScript(String resourcePath) throws IOException {
+ InputStream is = getClass().getResourceAsStream(resourcePath);
+ StringBuilder sb = new StringBuilder();
+ for (;;) {
+ int ch = is.read();
+ if (ch == -1) {
+ break;
+ }
+ sb.append((char)ch);
+ }
+ applyCode(lazy.loader, null, sb.toString(), false);
+ }
+
+ @Override
+ String assignClass(String className) {
+ return "vm[arguments[1]]=";
+ }
+
+ @Override
+ String accessClass(String classOperation) {
+ return "vm." + classOperation;
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VarType.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,110 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import org.apidesign.javap.RuntimeConstants;
+
+final class VarType {
+ public static final int INTEGER = 0;
+ public static final int LONG = 1;
+ public static final int FLOAT = 2;
+ public static final int DOUBLE = 3;
+ public static final int REFERENCE = 4;
+
+ public static final int LAST = REFERENCE;
+
+ private VarType() {
+ }
+
+ public static boolean isCategory2(final int varType) {
+ return (varType == LONG) || (varType == DOUBLE);
+ }
+
+ public static int fromStackMapType(final int smType) {
+ switch (smType & 0xff) {
+ case RuntimeConstants.ITEM_Integer:
+ return VarType.INTEGER;
+ case RuntimeConstants.ITEM_Float:
+ return VarType.FLOAT;
+ case RuntimeConstants.ITEM_Double:
+ return VarType.DOUBLE;
+ case RuntimeConstants.ITEM_Long:
+ return VarType.LONG;
+ case RuntimeConstants.ITEM_Object:
+ return VarType.REFERENCE;
+
+ case RuntimeConstants.ITEM_Bogus:
+ case RuntimeConstants.ITEM_Null:
+ case RuntimeConstants.ITEM_InitObject:
+ case RuntimeConstants.ITEM_NewObject:
+ /* unclear how to handle for now */
+ default:
+ throw new IllegalStateException("Unhandled stack map type");
+ }
+ }
+
+ public static int fromConstantType(final byte constantTag) {
+ switch (constantTag) {
+ case RuntimeConstants.CONSTANT_INTEGER:
+ return VarType.INTEGER;
+ case RuntimeConstants.CONSTANT_FLOAT:
+ return VarType.FLOAT;
+ case RuntimeConstants.CONSTANT_LONG:
+ return VarType.LONG;
+ case RuntimeConstants.CONSTANT_DOUBLE:
+ return VarType.DOUBLE;
+
+ case RuntimeConstants.CONSTANT_CLASS:
+ case RuntimeConstants.CONSTANT_UTF8:
+ case RuntimeConstants.CONSTANT_UNICODE:
+ case RuntimeConstants.CONSTANT_STRING:
+ return VarType.REFERENCE;
+
+ case RuntimeConstants.CONSTANT_FIELD:
+ case RuntimeConstants.CONSTANT_METHOD:
+ case RuntimeConstants.CONSTANT_INTERFACEMETHOD:
+ case RuntimeConstants.CONSTANT_NAMEANDTYPE:
+ /* unclear how to handle for now */
+ default:
+ throw new IllegalStateException("Unhandled constant tag");
+ }
+ }
+
+ public static int fromFieldType(final char fieldType) {
+ switch (fieldType) {
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ case 'I':
+ return VarType.INTEGER;
+ case 'J':
+ return VarType.LONG;
+ case 'F':
+ return VarType.FLOAT;
+ case 'D':
+ return VarType.DOUBLE;
+ case 'L':
+ case '[':
+ return VarType.REFERENCE;
+
+ default:
+ throw new IllegalStateException("Unhandled field type");
+ }
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Variable.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/Variable.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,100 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+final class Variable implements CharSequence {
+ private static final String STACK_VAR_PREFIX = "st";
+ private static final String LOCAL_VAR_PREFIX = "lc";
+
+ private final String name;
+ private final int type;
+ private final int index;
+
+ private static final char[] TYPE_IDS = { 'I', 'L', 'F', 'D', 'A' };
+
+ private Variable(final String prefix, final int type, final int index) {
+ this.name = prefix + TYPE_IDS[type] + index;
+ this.type = type;
+ this.index = index;
+ }
+
+ public static Variable getStackVariable(
+ final int type, final int index) {
+ // TODO: precreate frequently used variables
+ return new Variable(STACK_VAR_PREFIX, type, index);
+ }
+
+ public static Variable getLocalVariable(
+ final int type, final int index) {
+ // TODO: precreate frequently used variables
+ return new Variable(LOCAL_VAR_PREFIX, type, index);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public boolean isCategory2() {
+ return VarType.isCategory2(type);
+ }
+
+ @Override
+ public int length() {
+ return name.length();
+ }
+
+ @Override
+ public char charAt(final int index) {
+ return name.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(final int start, final int end) {
+ return name.subSequence(start, end);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Variable)) {
+ return false;
+ }
+
+ return name.equals(((Variable) other).name);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/resources/org/apidesign/vm4brwsr/emulation/java_lang_String.js
--- a/vm/src/main/resources/org/apidesign/vm4brwsr/emulation/java_lang_String.js Thu Oct 11 06:15:22 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3296 +0,0 @@
-/* */
-
-
-/*
-function java_lang_String_consV(arg0) {
- var arg1;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg0); // 42
- case 5: stack.push(0); // 3
- case 6: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 9: stack.push(arg0); // 42
- case 10: stack.push(0); // 3
- case 11: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 14: stack.push(arg0); // 42
- case 15: stack.push(0); // 3
- case 16: stack.push(new Array(stack.pop())); // 188 5
- case 18: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 21: return; // 177
- }
-}
-function java_lang_String_consVLjava_lang_String(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg1); // 43
- case 5: stack.push(stack.pop().count); // 180 1 97
- case 8: arg2 = stack.pop(); // 61
- case 9: stack.push(arg1); // 43
- case 10: stack.push(stack.pop().value); // 180 1 100
- case 13: arg3 = stack.pop(); // 78
- case 14: stack.push(arg3); // 45
- case 15: stack.push(stack.pop().length); // 190
- case 16: stack.push(arg2); // 28
- case 17: if (stack.pop() >= stack.pop()) { gt = 41; continue; } // 164 0 24
- case 20: stack.push(arg1); // 43
- case 21: stack.push(stack.pop().offset); // 180 1 99
- case 24: arg5 = stack.pop() // 54 5
- case 26: stack.push(arg3); // 45
- case 27: stack.push(arg5); // 21 5
- case 29: stack.push(arg5); // 21 5
- case 31: stack.push(arg2); // 28
- case 32: stack.push(stack.pop() + stack.pop()); // 96
- case 33: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfRangeACACAIAI(v0, v1, v2)); } // 184 1 173
- case 36: arg4 = stack.pop() // 58 4
- case 38: gt = 44; continue; // 167 0 6
- case 41: stack.push(arg3); // 45
- case 42: arg4 = stack.pop() // 58 4
- case 44: stack.push(arg0); // 42
- case 45: stack.push(0); // 3
- case 46: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 49: stack.push(arg0); // 42
- case 50: stack.push(arg2); // 28
- case 51: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 54: stack.push(arg0); // 42
- case 55: stack.push(arg4); // 25 4
- case 57: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 60: return; // 177
- }
-}
-*/
-function java_lang_String_consVAC(arg0,arg1) {
- arg0.r = arg1.join("");
-}
-/*
-function java_lang_String_consVACII(arg0,arg1,arg2,arg3) {
- var arg4;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg2); // 28
- case 5: if (stack.pop() >= 0) { gt = 17; continue; } // 156 0 12
- case 8: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 11: stack.push(stack[stack.length - 1]); // 89
- case 12: stack.push(arg2); // 28
- case 13: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 16: // 191
- case 17: stack.push(arg3); // 29
- case 18: if (stack.pop() >= 0) { gt = 30; continue; } // 156 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg3); // 29
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg2); // 28
- case 31: stack.push(arg1); // 43
- case 32: stack.push(stack.pop().length); // 190
- case 33: stack.push(arg3); // 29
- case 34: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 35: if (stack.pop() >= stack.pop()) { gt = 49; continue; } // 164 0 14
- case 38: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 41: stack.push(stack[stack.length - 1]); // 89
- case 42: stack.push(arg2); // 28
- case 43: stack.push(arg3); // 29
- case 44: stack.push(stack.pop() + stack.pop()); // 96
- case 45: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 48: // 191
- case 49: stack.push(arg0); // 42
- case 50: stack.push(0); // 3
- case 51: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 54: stack.push(arg0); // 42
- case 55: stack.push(arg3); // 29
- case 56: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 59: stack.push(arg0); // 42
- case 60: stack.push(arg1); // 43
- case 61: stack.push(arg2); // 28
- case 62: stack.push(arg2); // 28
- case 63: stack.push(arg3); // 29
- case 64: stack.push(stack.pop() + stack.pop()); // 96
- case 65: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfRangeACACAIAI(v0, v1, v2)); } // 184 1 173
- case 68: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 71: return; // 177
- }
-}
-function java_lang_String_consVAIII(arg0,arg1,arg2,arg3) {
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg2); // 28
- case 5: if (stack.pop() >= 0) { gt = 17; continue; } // 156 0 12
- case 8: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 11: stack.push(stack[stack.length - 1]); // 89
- case 12: stack.push(arg2); // 28
- case 13: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 16: // 191
- case 17: stack.push(arg3); // 29
- case 18: if (stack.pop() >= 0) { gt = 30; continue; } // 156 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg3); // 29
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg2); // 28
- case 31: stack.push(arg1); // 43
- case 32: stack.push(stack.pop().length); // 190
- case 33: stack.push(arg3); // 29
- case 34: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 35: if (stack.pop() >= stack.pop()) { gt = 49; continue; } // 164 0 14
- case 38: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 41: stack.push(stack[stack.length - 1]); // 89
- case 42: stack.push(arg2); // 28
- case 43: stack.push(arg3); // 29
- case 44: stack.push(stack.pop() + stack.pop()); // 96
- case 45: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 48: // 191
- case 49: stack.push(0); // 3
- case 50: arg4 = stack.pop() // 54 4
- case 52: stack.push(1); // 4
- case 53: arg5 = stack.pop() // 54 5
- case 55: stack.push(arg3); // 29
- case 56: stack.push(arg5); // 21 5
- case 58: stack.push(stack.pop() + stack.pop()); // 96
- case 59: stack.push(new Array(stack.pop())); // 188 5
- case 61: arg6 = stack.pop() // 58 6
- case 63: stack.push(arg2); // 28
- case 64: arg7 = stack.pop() // 54 7
- case 66: stack.push(0); // 3
- case 67: arg8 = stack.pop() // 54 8
- case 69: stack.push(0); // 3
- case 70: arg9 = stack.pop() // 54 9
- case 72: stack.push(arg9); // 21 9
- case 74: stack.push(arg3); // 29
- case 75: if (stack.pop() <= stack.pop()) { gt = 255; continue; } // 162 0 180
- case 78: stack.push(arg1); // 43
- case 79: stack.push(arg7); // 21 7
- case 81: arg7++; // 132 7 1
- case 84: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 46
- case 85: arg10 = stack.pop() // 54 10
- case 87: stack.push(arg10); // 21 10
- case 89: if (stack.pop() >= 0) { gt = 100; continue; } // 156 0 11
- case 92: stack.push(new java_lang_IllegalArgumentException); // 187 0 193
- case 95: stack.push(stack[stack.length - 1]); // 89
- case 96: { java_lang_IllegalArgumentException_consV(stack.pop()); } // 183 1 123
- case 99: // 191
- case 100: stack.push(arg5); // 21 5
- case 102: if (stack.pop() > 0) { gt = 195; continue; } // 157 0 93
- case 105: stack.push(arg8); // 21 8
- case 107: stack.push(1); // 4
- case 108: stack.push(stack.pop() + stack.pop()); // 96
- case 109: stack.push(arg6); // 25 6
- case 111: stack.push(stack.pop().length); // 190
- case 112: if (stack.pop() > stack.pop()) { gt = 195; continue; } // 161 0 83
- case 115: stack.push(arg4); // 21 4
- case 117: if (stack.pop() != 0) { gt = 153; continue; } // 154 0 36
- case 120: stack.push(arg5); // 21 5
- case 122: // 116
- case 123: stack.push(1); // 4
- case 124: stack.push(stack.pop() + stack.pop()); // 96
- case 125: stack.push(arg3); // 29
- case 126: stack.push(stack.pop() * stack.pop()); // 104
- case 127: stack.push(10); // 16 10
- case 129: // 120
- case 130: stack.push(arg9); // 21 9
- case 132: { var tmp = stack.pop(); stack.push(Math.floor(stack.pop() / tmp)); } // 108
- case 133: arg4 = stack.pop() // 54 4
- case 135: stack.push(arg4); // 21 4
- case 137: stack.push(10); // 16 10
- case 139: // 122
- case 140: arg4 = stack.pop() // 54 4
- case 142: stack.push(arg4); // 21 4
- case 144: if (stack.pop() > 0) { gt = 159; continue; } // 157 0 15
- case 147: stack.push(1); // 4
- case 148: arg4 = stack.pop() // 54 4
- case 150: gt = 159; continue; // 167 0 9
- case 153: stack.push(arg4); // 21 4
- case 155: stack.push(2); // 5
- case 156: stack.push(stack.pop() * stack.pop()); // 104
- case 157: arg4 = stack.pop() // 54 4
- case 159: stack.push(arg6); // 25 6
- case 161: stack.push(stack.pop().length); // 190
- case 162: stack.push(arg4); // 21 4
- case 164: stack.push(stack.pop() + stack.pop()); // 96
- case 165: stack.push(arg3); // 29
- case 166: stack.push(2); // 5
- case 167: stack.push(stack.pop() * stack.pop()); // 104
- case 168: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127
- case 171: arg11 = stack.pop() // 54 11
- case 173: stack.push(arg11); // 21 11
- case 175: stack.push(arg6); // 25 6
- case 177: stack.push(stack.pop().length); // 190
- case 178: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 179: stack.push(arg3); // 29
- case 180: stack.push(arg9); // 21 9
- case 182: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 183: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 184: arg5 = stack.pop() // 54 5
- case 186: stack.push(arg6); // 25 6
- case 188: stack.push(arg11); // 21 11
- case 190: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfACACAI(v0, v1)); } // 184 1 172
- case 193: arg6 = stack.pop() // 58 6
- case 195: stack.push(arg10); // 21 10
- case 197: stack.push(65536); // 18 3
- case 199: if (stack.pop() <= stack.pop()) { gt = 216; continue; } // 162 0 17
- case 202: stack.push(arg6); // 25 6
- case 204: stack.push(arg8); // 21 8
- case 206: arg8++; // 132 8 1
- case 209: stack.push(arg10); // 21 10
- case 211: // number conversion // 146
- case 212: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 213: gt = 249; continue; // 167 0 36
- case 216: stack.push(arg10); // 21 10
- case 218: stack.push(1114111); // 18 4
- case 220: if (stack.pop() < stack.pop()) { gt = 241; continue; } // 163 0 21
- case 223: stack.push(arg10); // 21 10
- case 225: stack.push(arg6); // 25 6
- case 227: stack.push(arg8); // 21 8
- case 229: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_Character_toSurrogatesVIACAI(v0, v1, v2); } // 184 1 112
- case 232: arg8 += 2; // 132 8 2
- case 235: arg5 += 255; // 132 5 255
- case 238: gt = 249; continue; // 167 0 11
- case 241: stack.push(new java_lang_IllegalArgumentException); // 187 0 193
- case 244: stack.push(stack[stack.length - 1]); // 89
- case 245: { java_lang_IllegalArgumentException_consV(stack.pop()); } // 183 1 123
- case 248: // 191
- case 249: arg9++; // 132 9 1
- case 252: gt = 72; continue; // 167 255 76
- case 255: stack.push(arg0); // 42
- case 256: stack.push(0); // 3
- case 257: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 260: stack.push(arg0); // 42
- case 261: stack.push(arg6); // 25 6
- case 263: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 266: stack.push(arg0); // 42
- case 267: stack.push(arg8); // 21 8
- case 269: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 272: return; // 177
- }
-}
-function java_lang_String_consVABIII(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
- var arg7;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg1); // 43
- case 5: stack.push(arg3); // 29
- case 6: stack.push(arg4); // 21 4
- case 8: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140
- case 11: stack.push(arg4); // 21 4
- case 13: stack.push(new Array(stack.pop())); // 188 5
- case 15: arg5 = stack.pop() // 58 5
- case 17: stack.push(arg2); // 28
- case 18: if (stack.pop() != 0) { gt = 55; continue; } // 154 0 37
- case 21: stack.push(arg4); // 21 4
- case 23: arg6 = stack.pop() // 54 6
- case 25: stack.push(arg6); // 21 6
- case 27: arg6 += 255; // 132 6 255
- case 30: if (stack.pop() <= 0) { gt = 52; continue; } // 158 0 22
- case 33: stack.push(arg5); // 25 5
- case 35: stack.push(arg6); // 21 6
- case 37: stack.push(arg1); // 43
- case 38: stack.push(arg6); // 21 6
- case 40: stack.push(arg3); // 29
- case 41: stack.push(stack.pop() + stack.pop()); // 96
- case 42: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 51
- case 43: stack.push(255); // 17 0 255
- case 46: stack.push(stack.pop() & stack.pop()); // 126
- case 47: // number conversion // 146
- case 48: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 49: gt = 25; continue; // 167 255 232
- case 52: gt = 93; continue; // 167 0 41
- case 55: stack.push(arg2); // 28
- case 56: stack.push(8); // 16 8
- case 58: // 120
- case 59: arg2 = stack.pop(); // 61
- case 60: stack.push(arg4); // 21 4
- case 62: arg6 = stack.pop() // 54 6
- case 64: stack.push(arg6); // 21 6
- case 66: arg6 += 255; // 132 6 255
- case 69: if (stack.pop() <= 0) { gt = 93; continue; } // 158 0 24
- case 72: stack.push(arg5); // 25 5
- case 74: stack.push(arg6); // 21 6
- case 76: stack.push(arg2); // 28
- case 77: stack.push(arg1); // 43
- case 78: stack.push(arg6); // 21 6
- case 80: stack.push(arg3); // 29
- case 81: stack.push(stack.pop() + stack.pop()); // 96
- case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 51
- case 83: stack.push(255); // 17 0 255
- case 86: stack.push(stack.pop() & stack.pop()); // 126
- case 87: stack.push(stack.pop() | stack.pop()); // 128
- case 88: // number conversion // 146
- case 89: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 90: gt = 64; continue; // 167 255 230
- case 93: stack.push(arg0); // 42
- case 94: stack.push(0); // 3
- case 95: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 98: stack.push(arg0); // 42
- case 99: stack.push(arg4); // 21 4
- case 101: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 104: stack.push(arg0); // 42
- case 105: stack.push(arg5); // 25 5
- case 107: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 110: return; // 177
- }
-}
-function java_lang_String_consVABI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(arg2); // 28
- case 3: stack.push(0); // 3
- case 4: stack.push(arg1); // 43
- case 5: stack.push(stack.pop().length); // 190
- case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIAI(stack.pop(), v0, v1, v2, v3); } // 183 1 141
- case 9: return; // 177
- }
-}
-function java_lang_String_checkBoundsVABII(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg2); // 28
- case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12
- case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: stack.push(arg2); // 28
- case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 12: // 191
- case 13: stack.push(arg1); // 27
- case 14: if (stack.pop() >= 0) { gt = 26; continue; } // 156 0 12
- case 17: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 20: stack.push(stack[stack.length - 1]); // 89
- case 21: stack.push(arg1); // 27
- case 22: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 25: // 191
- case 26: stack.push(arg1); // 27
- case 27: stack.push(arg0); // 42
- case 28: stack.push(stack.pop().length); // 190
- case 29: stack.push(arg2); // 28
- case 30: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 31: if (stack.pop() >= stack.pop()) { gt = 45; continue; } // 164 0 14
- case 34: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 37: stack.push(stack[stack.length - 1]); // 89
- case 38: stack.push(arg1); // 27
- case 39: stack.push(arg2); // 28
- case 40: stack.push(stack.pop() + stack.pop()); // 96
- case 41: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 44: // 191
- case 45: return; // 177
- }
-}
-function java_lang_String_consVABIILjava_lang_String(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg4); // 25 4
- case 6: if (stack.pop()) { gt = 19; continue; } // 199 0 13
- case 9: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 12: stack.push(stack[stack.length - 1]); // 89
- case 13: stack.push("charsetName"); // 18 7
- case 15: { var v0 = stack.pop(); java_lang_NullPointerException_consVLjava_lang_String(stack.pop(), v0); } // 183 1 129
- case 18: // 191
- case 19: stack.push(arg1); // 43
- case 20: stack.push(arg2); // 28
- case 21: stack.push(arg3); // 29
- case 22: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140
- case 25: stack.push(arg4); // 25 4
- case 27: stack.push(arg1); // 43
- case 28: stack.push(arg2); // 28
- case 29: stack.push(arg3); // 29
- case 30: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACLjava_lang_StringABAIAI(v0, v1, v2, v3)); } // 184 1 165
- case 33: arg5 = stack.pop() // 58 5
- case 35: stack.push(arg0); // 42
- case 36: stack.push(0); // 3
- case 37: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 40: stack.push(arg0); // 42
- case 41: stack.push(arg5); // 25 5
- case 43: stack.push(stack.pop().length); // 190
- case 44: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 47: stack.push(arg0); // 42
- case 48: stack.push(arg5); // 25 5
- case 50: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 53: return; // 177
- }
-}
-function java_lang_String_consVABIILjava_nio_charset_Charset(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg4); // 25 4
- case 6: if (stack.pop()) { gt = 19; continue; } // 199 0 13
- case 9: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 12: stack.push(stack[stack.length - 1]); // 89
- case 13: stack.push("charset"); // 18 6
- case 15: { var v0 = stack.pop(); java_lang_NullPointerException_consVLjava_lang_String(stack.pop(), v0); } // 183 1 129
- case 18: // 191
- case 19: stack.push(arg1); // 43
- case 20: stack.push(arg2); // 28
- case 21: stack.push(arg3); // 29
- case 22: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140
- case 25: stack.push(arg4); // 25 4
- case 27: stack.push(arg1); // 43
- case 28: stack.push(arg2); // 28
- case 29: stack.push(arg3); // 29
- case 30: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACLjava_nio_charset_CharsetABAIAI(v0, v1, v2, v3)); } // 184 1 167
- case 33: arg5 = stack.pop() // 58 5
- case 35: stack.push(arg0); // 42
- case 36: stack.push(0); // 3
- case 37: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 40: stack.push(arg0); // 42
- case 41: stack.push(arg5); // 25 5
- case 43: stack.push(stack.pop().length); // 190
- case 44: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 47: stack.push(arg0); // 42
- case 48: stack.push(arg5); // 25 5
- case 50: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 53: return; // 177
- }
-}
-function java_lang_String_consVABLjava_lang_String(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: stack.push(arg1); // 43
- case 4: stack.push(stack.pop().length); // 190
- case 5: stack.push(arg2); // 44
- case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIALjava_lang_String(stack.pop(), v0, v1, v2, v3); } // 183 1 154
- case 9: return; // 177
- }
-}
-function java_lang_String_consVABLjava_nio_charset_Charset(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: stack.push(arg1); // 43
- case 4: stack.push(stack.pop().length); // 190
- case 5: stack.push(arg2); // 44
- case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIALjava_nio_charset_Charset(stack.pop(), v0, v1, v2, v3); } // 183 1 156
- case 9: return; // 177
- }
-}
-function java_lang_String_consVABII(arg0,arg1,arg2,arg3) {
- var arg4;
- var arg5;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg1); // 43
- case 5: stack.push(arg2); // 28
- case 6: stack.push(arg3); // 29
- case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140
- case 10: stack.push(arg1); // 43
- case 11: stack.push(arg2); // 28
- case 12: stack.push(arg3); // 29
- case 13: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACABAIAI(v0, v1, v2)); } // 184 1 163
- case 16: arg4 = stack.pop() // 58 4
- case 18: stack.push(arg0); // 42
- case 19: stack.push(0); // 3
- case 20: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 23: stack.push(arg0); // 42
- case 24: stack.push(arg4); // 25 4
- case 26: stack.push(stack.pop().length); // 190
- case 27: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 30: stack.push(arg0); // 42
- case 31: stack.push(arg4); // 25 4
- case 33: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 36: return; // 177
- }
-}
-function java_lang_String_consVAB(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: stack.push(arg1); // 43
- case 4: stack.push(stack.pop().length); // 190
- case 5: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAI(stack.pop(), v0, v1, v2); } // 183 1 139
- case 8: return; // 177
- }
-}
-function java_lang_String_consVLjava_lang_StringBuffer(arg0,arg1) {
- var arg2;
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg1); // 43
- case 5: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 161
- case 8: arg2 = stack.pop(); // 77
- case 9: stack.push(arg0); // 42
- case 10: stack.push(arg2); // 44
- case 11: stack.push(stack.pop().value); // 180 1 100
- case 14: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(arg2); // 44
- case 19: stack.push(stack.pop().count); // 180 1 97
- case 22: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 25: stack.push(arg0); // 42
- case 26: stack.push(arg2); // 44
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 33: return; // 177
- }
-}
-function java_lang_String_consVLjava_lang_StringBuilder(arg0,arg1) {
- var arg2;
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg1); // 43
- case 5: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 162
- case 8: arg2 = stack.pop(); // 77
- case 9: stack.push(arg0); // 42
- case 10: stack.push(arg2); // 44
- case 11: stack.push(stack.pop().value); // 180 1 100
- case 14: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(arg2); // 44
- case 19: stack.push(stack.pop().count); // 180 1 97
- case 22: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 25: stack.push(arg0); // 42
- case 26: stack.push(arg2); // 44
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 33: return; // 177
- }
-}
-function java_lang_String_consVIIAC(arg0,arg1,arg2,arg3) {
- var arg4;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg3); // 45
- case 6: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100
- case 9: stack.push(arg0); // 42
- case 10: stack.push(arg1); // 27
- case 11: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99
- case 14: stack.push(arg0); // 42
- case 15: stack.push(arg2); // 28
- case 16: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97
- case 19: return; // 177
- }
-}
-*/
-
-function java_lang_String_charAtCI(arg0,arg1) {
- return arg0.toString().charAt(arg1);
-}
-function java_lang_String_lengthI(arg0) {
- return arg0.toString().length;
-}
-function java_lang_String_isEmptyZ(arg0) {
- return arg0.toString().length === 0;
-}
-
-/*
-function java_lang_String_codePointAtII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11
- case 4: stack.push(arg1); // 27
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() > stack.pop()) { gt = 21; continue; } // 161 0 12
- case 12: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 15: stack.push(stack[stack.length - 1]); // 89
- case 16: stack.push(arg1); // 27
- case 17: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 20: // 191
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().value); // 180 1 100
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().offset); // 180 1 99
- case 29: stack.push(arg1); // 27
- case 30: stack.push(stack.pop() + stack.pop()); // 96
- case 31: stack.push(arg0); // 42
- case 32: stack.push(stack.pop().offset); // 180 1 99
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().count); // 180 1 97
- case 39: stack.push(stack.pop() + stack.pop()); // 96
- case 40: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointAtImplAIACAIAI(v0, v1, v2)); } // 184 1 113
- case 43: return stack.pop(); // 172
- }
-}
-function java_lang_String_codePointBeforeII(arg0,arg1) {
- var arg2;
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: stack.push(1); // 4
- case 2: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 3: arg2 = stack.pop(); // 61
- case 4: stack.push(arg2); // 28
- case 5: if (stack.pop() < 0) { gt = 16; continue; } // 155 0 11
- case 8: stack.push(arg2); // 28
- case 9: stack.push(arg0); // 42
- case 10: stack.push(stack.pop().count); // 180 1 97
- case 13: if (stack.pop() > stack.pop()) { gt = 25; continue; } // 161 0 12
- case 16: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 19: stack.push(stack[stack.length - 1]); // 89
- case 20: stack.push(arg1); // 27
- case 21: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 24: // 191
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().value); // 180 1 100
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: stack.push(arg1); // 27
- case 34: stack.push(stack.pop() + stack.pop()); // 96
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointBeforeImplAIACAIAI(v0, v1, v2)); } // 184 1 114
- case 42: return stack.pop(); // 172
- }
-}
-function java_lang_String_codePointCountIII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 17; continue; } // 155 0 16
- case 4: stack.push(arg2); // 28
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() < stack.pop()) { gt = 17; continue; } // 163 0 8
- case 12: stack.push(arg1); // 27
- case 13: stack.push(arg2); // 28
- case 14: if (stack.pop() >= stack.pop()) { gt = 25; continue; } // 164 0 11
- case 17: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194
- case 20: stack.push(stack[stack.length - 1]); // 89
- case 21: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124
- case 24: // 191
- case 25: stack.push(arg0); // 42
- case 26: stack.push(stack.pop().value); // 180 1 100
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: stack.push(arg1); // 27
- case 34: stack.push(stack.pop() + stack.pop()); // 96
- case 35: stack.push(arg2); // 28
- case 36: stack.push(arg1); // 27
- case 37: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 38: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointCountImplAIACAIAI(v0, v1, v2)); } // 184 1 115
- case 41: return stack.pop(); // 172
- }
-}
-function java_lang_String_offsetByCodePointsIII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11
- case 4: stack.push(arg1); // 27
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: if (stack.pop() >= stack.pop()) { gt = 20; continue; } // 164 0 11
- case 12: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194
- case 15: stack.push(stack[stack.length - 1]); // 89
- case 16: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124
- case 19: // 191
- case 20: stack.push(arg0); // 42
- case 21: stack.push(stack.pop().value); // 180 1 100
- case 24: stack.push(arg0); // 42
- case 25: stack.push(stack.pop().offset); // 180 1 99
- case 28: stack.push(arg0); // 42
- case 29: stack.push(stack.pop().count); // 180 1 97
- case 32: stack.push(arg0); // 42
- case 33: stack.push(stack.pop().offset); // 180 1 99
- case 36: stack.push(arg1); // 27
- case 37: stack.push(stack.pop() + stack.pop()); // 96
- case 38: stack.push(arg2); // 28
- case 39: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_offsetByCodePointsImplAIACAIAIAIAI(v0, v1, v2, v3, v4)); } // 184 1 116
- case 42: stack.push(arg0); // 42
- case 43: stack.push(stack.pop().offset); // 180 1 99
- case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 47: return stack.pop(); // 172
- }
-}
-*/
-
-// public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
-function java_lang_String_getCharsVIIACAI(arg0,arg1,arg2,arg3,arg4) {
- var s = arg0.toString();
- while (arg1 < arg2) {
- arg3[arg4++] = s[arg1++];
- }
-}
-
-/*
-function java_lang_String_getBytesVIIABI(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12
- case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: stack.push(arg1); // 27
- case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 12: // 191
- case 13: stack.push(arg2); // 28
- case 14: stack.push(arg0); // 42
- case 15: stack.push(stack.pop().count); // 180 1 97
- case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg2); // 28
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg1); // 27
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14
- case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 38: stack.push(stack[stack.length - 1]); // 89
- case 39: stack.push(arg2); // 28
- case 40: stack.push(arg1); // 27
- case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 45: // 191
- case 46: stack.push(arg4); // 21 4
- case 48: arg5 = stack.pop() // 54 5
- case 50: stack.push(arg0); // 42
- case 51: stack.push(stack.pop().offset); // 180 1 99
- case 54: stack.push(arg2); // 28
- case 55: stack.push(stack.pop() + stack.pop()); // 96
- case 56: arg6 = stack.pop() // 54 6
- case 58: stack.push(arg0); // 42
- case 59: stack.push(stack.pop().offset); // 180 1 99
- case 62: stack.push(arg1); // 27
- case 63: stack.push(stack.pop() + stack.pop()); // 96
- case 64: arg7 = stack.pop() // 54 7
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().value); // 180 1 100
- case 70: arg8 = stack.pop() // 58 8
- case 72: stack.push(arg7); // 21 7
- case 74: stack.push(arg6); // 21 6
- case 76: if (stack.pop() <= stack.pop()) { gt = 98; continue; } // 162 0 22
- case 79: stack.push(arg3); // 45
- case 80: stack.push(arg5); // 21 5
- case 82: arg5++; // 132 5 1
- case 85: stack.push(arg8); // 25 8
- case 87: stack.push(arg7); // 21 7
- case 89: arg7++; // 132 7 1
- case 92: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 93: // number conversion // 145
- case 94: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 84
- case 95: gt = 72; continue; // 167 255 233
- case 98: return; // 177
- }
-}
-function java_lang_String_getBytesABLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(arg1); // 43
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().offset); // 180 1 99
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().count); // 180 1 97
- case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_lang_StringACAIAI(v0, v1, v2, v3)); } // 184 1 166
- case 28: return stack.pop(); // 176
- }
-}
-function java_lang_String_getBytesABLjava_nio_charset_Charset(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(arg1); // 43
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().offset); // 180 1 99
- case 21: stack.push(arg0); // 42
- case 22: stack.push(stack.pop().count); // 180 1 97
- case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_nio_charset_CharsetACAIAI(v0, v1, v2, v3)); } // 184 1 168
- case 28: return stack.pop(); // 176
- }
-}
-function java_lang_String_getBytesAB(arg0) {
- var arg1;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABACAIAI(v0, v1, v2)); } // 184 1 164
- case 15: return stack.pop(); // 176
- }
-}
-function java_lang_String_equalsZLjava_lang_Object(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: // 166
- case 3: // 0
- case 4: stack.push(2); // 5
- case 5: stack.push(1); // 4
- case 6: return stack.pop(); // 172
- case 7: stack.push(arg1); // 43
- case 8: stack.push(stack.pop().$instOf_java_lang_String ? 1 : 0); // 193 0 200
- case 11: if (stack.pop() == 0) { gt = 86; continue; } // 153 0 75
- case 14: stack.push(arg1); // 43
- case 15: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200
- case 18: arg2 = stack.pop(); // 77
- case 19: stack.push(arg0); // 42
- case 20: stack.push(stack.pop().count); // 180 1 97
- case 23: arg3 = stack.pop(); // 62
- case 24: stack.push(arg3); // 29
- case 25: stack.push(arg2); // 44
- case 26: stack.push(stack.pop().count); // 180 1 97
- case 29: if (stack.pop() != stack.pop()) { gt = 86; continue; } // 160 0 57
- case 32: stack.push(arg0); // 42
- case 33: stack.push(stack.pop().value); // 180 1 100
- case 36: arg4 = stack.pop() // 58 4
- case 38: stack.push(arg2); // 44
- case 39: stack.push(stack.pop().value); // 180 1 100
- case 42: arg5 = stack.pop() // 58 5
- case 44: stack.push(arg0); // 42
- case 45: stack.push(stack.pop().offset); // 180 1 99
- case 48: arg6 = stack.pop() // 54 6
- case 50: stack.push(arg2); // 44
- case 51: stack.push(stack.pop().offset); // 180 1 99
- case 54: arg7 = stack.pop() // 54 7
- case 56: stack.push(arg3); // 29
- case 57: arg3 += 255; // 132 3 255
- case 60: if (stack.pop() == 0) { gt = 84; continue; } // 153 0 24
- case 63: stack.push(arg4); // 25 4
- case 65: stack.push(arg6); // 21 6
- case 67: arg6++; // 132 6 1
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: stack.push(arg5); // 25 5
- case 73: stack.push(arg7); // 21 7
- case 75: arg7++; // 132 7 1
- case 78: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 79: if (stack.pop() == stack.pop()) { gt = 56; continue; } // 159 255 233
- case 82: stack.push(0); // 3
- case 83: return stack.pop(); // 172
- case 84: stack.push(1); // 4
- case 85: return stack.pop(); // 172
- case 86: stack.push(0); // 3
- case 87: return stack.pop(); // 172
- }
-}
-function java_lang_String_contentEqualsZLjava_lang_StringBuffer(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: stack.push(stack[stack.length - 1]); // 89
- case 2: arg2 = stack.pop(); // 77
- case 3: // 194
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 43
- case 6: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.contentEqualsZLjava_lang_CharSequence(self, v0)); } // 182 1 146
- case 9: stack.push(arg2); // 44
- case 10: // 195
- case 11: return stack.pop(); // 172
- case 12: arg3 = stack.pop(); // 78
- case 13: stack.push(arg2); // 44
- case 14: // 195
- case 15: stack.push(arg3); // 45
- case 16: // 191
- }
-}
-function java_lang_String_contentEqualsZLjava_lang_CharSequence(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: stack.push(arg1); // 43
- case 5: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 185 1 188
- case 8: // 1
- case 9: // 0
- case 10: if (stack.pop() == stack.pop()) { gt = 15; continue; } // 159 0 5
- case 13: stack.push(0); // 3
- case 14: return stack.pop(); // 172
- case 15: stack.push(arg1); // 43
- case 16: stack.push(stack.pop().$instOf_java_lang_AbstractStringBuilder ? 1 : 0); // 193 0 186
- case 19: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 58
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: arg2 = stack.pop(); // 77
- case 27: stack.push(arg1); // 43
- case 28: if(stack[stack.length - 1].$instOf_java_lang_AbstractStringBuilder != 1) throw {}; // 192 0 186
- case 31: { var self = stack.pop(); stack.push(self.getValueAC(self)); } // 182 1 103
- case 34: arg3 = stack.pop(); // 78
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: arg4 = stack.pop() // 54 4
- case 41: stack.push(0); // 3
- case 42: arg5 = stack.pop() // 54 5
- case 44: stack.push(arg0); // 42
- case 45: stack.push(stack.pop().count); // 180 1 97
- case 48: arg6 = stack.pop() // 54 6
- case 50: stack.push(arg6); // 21 6
- case 52: arg6 += 255; // 132 6 255
- case 55: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 22
- case 58: stack.push(arg2); // 44
- case 59: stack.push(arg4); // 21 4
- case 61: arg4++; // 132 4 1
- case 64: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 65: stack.push(arg3); // 45
- case 66: stack.push(arg5); // 21 5
- case 68: arg5++; // 132 5 1
- case 71: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 72: if (stack.pop() == stack.pop()) { gt = 50; continue; } // 159 255 234
- case 75: stack.push(0); // 3
- case 76: return stack.pop(); // 172
- case 77: stack.push(arg1); // 43
- case 78: stack.push(arg0); // 42
- case 79: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.equalsZLjava_lang_Object(self, v0)); } // 182 1 131
- case 82: if (stack.pop() == 0) { gt = 87; continue; } // 153 0 5
- case 85: stack.push(1); // 4
- case 86: return stack.pop(); // 172
- case 87: stack.push(arg0); // 42
- case 88: stack.push(stack.pop().value); // 180 1 100
- case 91: arg2 = stack.pop(); // 77
- case 92: stack.push(arg0); // 42
- case 93: stack.push(stack.pop().offset); // 180 1 99
- case 96: arg3 = stack.pop(); // 62
- case 97: stack.push(0); // 3
- case 98: arg4 = stack.pop() // 54 4
- case 100: stack.push(arg0); // 42
- case 101: stack.push(stack.pop().count); // 180 1 97
- case 104: arg5 = stack.pop() // 54 5
- case 106: stack.push(arg5); // 21 5
- case 108: arg5 += 255; // 132 5 255
- case 111: if (stack.pop() == 0) { gt = 136; continue; } // 153 0 25
- case 114: stack.push(arg2); // 44
- case 115: stack.push(arg3); // 29
- case 116: arg3++; // 132 3 1
- case 119: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 120: stack.push(arg1); // 43
- case 121: stack.push(arg4); // 21 4
- case 123: arg4++; // 132 4 1
- case 126: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.charAtCI(self, v0)); } // 185 1 189
- case 129: // 2
- case 130: // 0
- case 131: if (stack.pop() == stack.pop()) { gt = 106; continue; } // 159 255 231
- case 134: stack.push(0); // 3
- case 135: return stack.pop(); // 172
- case 136: stack.push(1); // 4
- case 137: return stack.pop(); // 172
- }
-}
-function java_lang_String_equalsIgnoreCaseZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: // 166
- case 3: // 0
- case 4: stack.push(4); // 7
- case 5: stack.push(1); // 4
- case 6: gt = 44; continue; // 167 0 38
- case 9: stack.push(arg1); // 43
- case 10: if (!stack.pop()) { gt = 43; continue; } // 198 0 33
- case 13: stack.push(arg1); // 43
- case 14: stack.push(stack.pop().count); // 180 1 97
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().count); // 180 1 97
- case 21: if (stack.pop() != stack.pop()) { gt = 43; continue; } // 160 0 22
- case 24: stack.push(arg0); // 42
- case 25: stack.push(1); // 4
- case 26: stack.push(0); // 3
- case 27: stack.push(arg1); // 43
- case 28: stack.push(0); // 3
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().count); // 180 1 97
- case 33: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.regionMatchesZZILjava_lang_StringII(self, v0, v1, v2, v3, v4)); } // 182 1 153
- case 36: if (stack.pop() == 0) { gt = 43; continue; } // 153 0 7
- case 39: stack.push(1); // 4
- case 40: gt = 44; continue; // 167 0 4
- case 43: stack.push(0); // 3
- case 44: return stack.pop(); // 172
- }
-}
-function java_lang_String_compareToILjava_lang_String(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: arg2 = stack.pop(); // 61
- case 5: stack.push(arg1); // 43
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg3 = stack.pop(); // 62
- case 10: stack.push(arg2); // 28
- case 11: stack.push(arg3); // 29
- case 12: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127
- case 15: arg4 = stack.pop() // 54 4
- case 17: stack.push(arg0); // 42
- case 18: stack.push(stack.pop().value); // 180 1 100
- case 21: arg5 = stack.pop() // 58 5
- case 23: stack.push(arg1); // 43
- case 24: stack.push(stack.pop().value); // 180 1 100
- case 27: arg6 = stack.pop() // 58 6
- case 29: stack.push(arg0); // 42
- case 30: stack.push(stack.pop().offset); // 180 1 99
- case 33: arg7 = stack.pop() // 54 7
- case 35: stack.push(arg1); // 43
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: arg8 = stack.pop() // 54 8
- case 41: stack.push(arg7); // 21 7
- case 43: stack.push(arg8); // 21 8
- case 45: if (stack.pop() != stack.pop()) { gt = 102; continue; } // 160 0 57
- case 48: stack.push(arg7); // 21 7
- case 50: arg9 = stack.pop() // 54 9
- case 52: stack.push(arg4); // 21 4
- case 54: stack.push(arg7); // 21 7
- case 56: stack.push(stack.pop() + stack.pop()); // 96
- case 57: arg10 = stack.pop() // 54 10
- case 59: stack.push(arg9); // 21 9
- case 61: stack.push(arg10); // 21 10
- case 63: if (stack.pop() <= stack.pop()) { gt = 99; continue; } // 162 0 36
- case 66: stack.push(arg5); // 25 5
- case 68: stack.push(arg9); // 21 9
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: arg11 = stack.pop() // 54 11
- case 73: stack.push(arg6); // 25 6
- case 75: stack.push(arg9); // 21 9
- case 77: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 78: arg12 = stack.pop() // 54 12
- case 80: stack.push(arg11); // 21 11
- case 82: stack.push(arg12); // 21 12
- case 84: if (stack.pop() == stack.pop()) { gt = 93; continue; } // 159 0 9
- case 87: stack.push(arg11); // 21 11
- case 89: stack.push(arg12); // 21 12
- case 91: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 92: return stack.pop(); // 172
- case 93: arg9++; // 132 9 1
- case 96: gt = 59; continue; // 167 255 219
- case 99: gt = 146; continue; // 167 0 47
- case 102: stack.push(arg4); // 21 4
- case 104: arg4 += 255; // 132 4 255
- case 107: if (stack.pop() == 0) { gt = 146; continue; } // 153 0 39
- case 110: stack.push(arg5); // 25 5
- case 112: stack.push(arg7); // 21 7
- case 114: arg7++; // 132 7 1
- case 117: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 118: arg9 = stack.pop() // 54 9
- case 120: stack.push(arg6); // 25 6
- case 122: stack.push(arg8); // 21 8
- case 124: arg8++; // 132 8 1
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: arg10 = stack.pop() // 54 10
- case 130: stack.push(arg9); // 21 9
- case 132: stack.push(arg10); // 21 10
- case 134: if (stack.pop() == stack.pop()) { gt = 143; continue; } // 159 0 9
- case 137: stack.push(arg9); // 21 9
- case 139: stack.push(arg10); // 21 10
- case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 142: return stack.pop(); // 172
- case 143: gt = 102; continue; // 167 255 215
- case 146: stack.push(arg2); // 28
- case 147: stack.push(arg3); // 29
- case 148: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 149: return stack.pop(); // 172
- }
-}
-function java_lang_String_compareToIgnoreCaseILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(java_lang_String_CASE_INSENSITIVE_ORDER); // 178 1 102
- case 3: stack.push(arg0); // 42
- case 4: stack.push(arg1); // 43
- case 5: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareILjava_lang_ObjectLjava_lang_Object(self, v0, v1)); } // 185 1 190
- case 8: stack.push(0); // 3
- case 9: // 0
- case 10: return stack.pop(); // 172
- }
-}
-function java_lang_String_regionMatchesZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4) {
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg5 = stack.pop() // 58 5
- case 6: stack.push(arg0); // 42
- case 7: stack.push(stack.pop().offset); // 180 1 99
- case 10: stack.push(arg1); // 27
- case 11: stack.push(stack.pop() + stack.pop()); // 96
- case 12: arg6 = stack.pop() // 54 6
- case 14: stack.push(arg2); // 44
- case 15: stack.push(stack.pop().value); // 180 1 100
- case 18: arg7 = stack.pop() // 58 7
- case 20: stack.push(arg2); // 44
- case 21: stack.push(stack.pop().offset); // 180 1 99
- case 24: stack.push(arg3); // 29
- case 25: stack.push(stack.pop() + stack.pop()); // 96
- case 26: arg8 = stack.pop() // 54 8
- case 28: stack.push(arg3); // 29
- case 29: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 37
- case 32: stack.push(arg1); // 27
- case 33: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 33
- case 36: stack.push(arg1); // 27
- case 37: // number conversion // 133
- case 38: stack.push(arg0); // 42
- case 39: stack.push(stack.pop().count); // 180 1 97
- case 42: // number conversion // 133
- case 43: stack.push(arg4); // 21 4
- case 45: // number conversion // 133
- case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 47: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 48: if (stack.pop() > 0) { gt = 66; continue; } // 157 0 18
- case 51: stack.push(arg3); // 29
- case 52: // number conversion // 133
- case 53: stack.push(arg2); // 44
- case 54: stack.push(stack.pop().count); // 180 1 97
- case 57: // number conversion // 133
- case 58: stack.push(arg4); // 21 4
- case 60: // number conversion // 133
- case 61: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 62: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 63: if (stack.pop() <= 0) { gt = 68; continue; } // 158 0 5
- case 66: stack.push(0); // 3
- case 67: return stack.pop(); // 172
- case 68: stack.push(arg4); // 21 4
- case 70: arg4 += 255; // 132 4 255
- case 73: if (stack.pop() <= 0) { gt = 97; continue; } // 158 0 24
- case 76: stack.push(arg5); // 25 5
- case 78: stack.push(arg6); // 21 6
- case 80: arg6++; // 132 6 1
- case 83: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 84: stack.push(arg7); // 25 7
- case 86: stack.push(arg8); // 21 8
- case 88: arg8++; // 132 8 1
- case 91: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 92: if (stack.pop() == stack.pop()) { gt = 68; continue; } // 159 255 232
- case 95: stack.push(0); // 3
- case 96: return stack.pop(); // 172
- case 97: stack.push(1); // 4
- case 98: return stack.pop(); // 172
- }
-}
-function java_lang_String_regionMatchesZZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4,arg5) {
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg6 = stack.pop() // 58 6
- case 6: stack.push(arg0); // 42
- case 7: stack.push(stack.pop().offset); // 180 1 99
- case 10: stack.push(arg2); // 28
- case 11: stack.push(stack.pop() + stack.pop()); // 96
- case 12: arg7 = stack.pop() // 54 7
- case 14: stack.push(arg3); // 45
- case 15: stack.push(stack.pop().value); // 180 1 100
- case 18: arg8 = stack.pop() // 58 8
- case 20: stack.push(arg3); // 45
- case 21: stack.push(stack.pop().offset); // 180 1 99
- case 24: stack.push(arg4); // 21 4
- case 26: stack.push(stack.pop() + stack.pop()); // 96
- case 27: arg9 = stack.pop() // 54 9
- case 29: stack.push(arg4); // 21 4
- case 31: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 38
- case 34: stack.push(arg2); // 28
- case 35: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 34
- case 38: stack.push(arg2); // 28
- case 39: // number conversion // 133
- case 40: stack.push(arg0); // 42
- case 41: stack.push(stack.pop().count); // 180 1 97
- case 44: // number conversion // 133
- case 45: stack.push(arg5); // 21 5
- case 47: // number conversion // 133
- case 48: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 49: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 50: if (stack.pop() > 0) { gt = 69; continue; } // 157 0 19
- case 53: stack.push(arg4); // 21 4
- case 55: // number conversion // 133
- case 56: stack.push(arg3); // 45
- case 57: stack.push(stack.pop().count); // 180 1 97
- case 60: // number conversion // 133
- case 61: stack.push(arg5); // 21 5
- case 63: // number conversion // 133
- case 64: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101
- case 65: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148
- case 66: if (stack.pop() <= 0) { gt = 71; continue; } // 158 0 5
- case 69: stack.push(0); // 3
- case 70: return stack.pop(); // 172
- case 71: stack.push(arg5); // 21 5
- case 73: arg5 += 255; // 132 5 255
- case 76: if (stack.pop() <= 0) { gt = 155; continue; } // 158 0 79
- case 79: stack.push(arg6); // 25 6
- case 81: stack.push(arg7); // 21 7
- case 83: arg7++; // 132 7 1
- case 86: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 87: arg10 = stack.pop() // 54 10
- case 89: stack.push(arg8); // 25 8
- case 91: stack.push(arg9); // 21 9
- case 93: arg9++; // 132 9 1
- case 96: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 97: arg11 = stack.pop() // 54 11
- case 99: stack.push(arg10); // 21 10
- case 101: stack.push(arg11); // 21 11
- case 103: if (stack.pop() != stack.pop()) { gt = 109; continue; } // 160 0 6
- case 106: gt = 71; continue; // 167 255 221
- case 109: stack.push(arg1); // 27
- case 110: if (stack.pop() == 0) { gt = 153; continue; } // 153 0 43
- case 113: stack.push(arg10); // 21 10
- case 115: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105
- case 118: arg12 = stack.pop() // 54 12
- case 120: stack.push(arg11); // 21 11
- case 122: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105
- case 125: arg13 = stack.pop() // 54 13
- case 127: stack.push(arg12); // 21 12
- case 129: stack.push(arg13); // 21 13
- case 131: if (stack.pop() != stack.pop()) { gt = 137; continue; } // 160 0 6
- case 134: gt = 71; continue; // 167 255 193
- case 137: stack.push(arg12); // 21 12
- case 139: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 142: stack.push(arg13); // 21 13
- case 144: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 147: if (stack.pop() != stack.pop()) { gt = 153; continue; } // 160 0 6
- case 150: gt = 71; continue; // 167 255 177
- case 153: stack.push(0); // 3
- case 154: return stack.pop(); // 172
- case 155: stack.push(1); // 4
- case 156: return stack.pop(); // 172
- }
-}
-function java_lang_String_startsWithZLjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: arg3 = stack.pop(); // 78
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().offset); // 180 1 99
- case 9: stack.push(arg2); // 28
- case 10: stack.push(stack.pop() + stack.pop()); // 96
- case 11: arg4 = stack.pop() // 54 4
- case 13: stack.push(arg1); // 43
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: arg5 = stack.pop() // 58 5
- case 19: stack.push(arg1); // 43
- case 20: stack.push(stack.pop().offset); // 180 1 99
- case 23: arg6 = stack.pop() // 54 6
- case 25: stack.push(arg1); // 43
- case 26: stack.push(stack.pop().count); // 180 1 97
- case 29: arg7 = stack.pop() // 54 7
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() < 0) { gt = 46; continue; } // 155 0 14
- case 35: stack.push(arg2); // 28
- case 36: stack.push(arg0); // 42
- case 37: stack.push(stack.pop().count); // 180 1 97
- case 40: stack.push(arg7); // 21 7
- case 42: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 43: if (stack.pop() >= stack.pop()) { gt = 48; continue; } // 164 0 5
- case 46: stack.push(0); // 3
- case 47: return stack.pop(); // 172
- case 48: arg7 += 255; // 132 7 255
- case 51: stack.push(arg7); // 21 7
- case 53: if (stack.pop() < 0) { gt = 76; continue; } // 155 0 23
- case 56: stack.push(arg3); // 45
- case 57: stack.push(arg4); // 21 4
- case 59: arg4++; // 132 4 1
- case 62: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 63: stack.push(arg5); // 25 5
- case 65: stack.push(arg6); // 21 6
- case 67: arg6++; // 132 6 1
- case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 71: if (stack.pop() == stack.pop()) { gt = 48; continue; } // 159 255 233
- case 74: stack.push(0); // 3
- case 75: return stack.pop(); // 172
- case 76: stack.push(1); // 4
- case 77: return stack.pop(); // 172
- }
-}
-function java_lang_String_startsWithZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_endsWithZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: stack.push(arg1); // 43
- case 7: stack.push(stack.pop().count); // 180 1 97
- case 10: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 11: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152
- case 14: return stack.pop(); // 172
- }
-}
-function java_lang_String_hashCodeI(arg0) {
- var arg1;
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().hash); // 180 1 98
- case 4: arg1 = stack.pop(); // 60
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg2 = stack.pop(); // 61
- case 10: stack.push(arg1); // 27
- case 11: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 51
- case 14: stack.push(arg2); // 28
- case 15: if (stack.pop() <= 0) { gt = 62; continue; } // 158 0 47
- case 18: stack.push(arg0); // 42
- case 19: stack.push(stack.pop().offset); // 180 1 99
- case 22: arg3 = stack.pop(); // 62
- case 23: stack.push(arg0); // 42
- case 24: stack.push(stack.pop().value); // 180 1 100
- case 27: arg4 = stack.pop() // 58 4
- case 29: stack.push(0); // 3
- case 30: arg5 = stack.pop() // 54 5
- case 32: stack.push(arg5); // 21 5
- case 34: stack.push(arg2); // 28
- case 35: if (stack.pop() <= stack.pop()) { gt = 57; continue; } // 162 0 22
- case 38: stack.push(31); // 16 31
- case 40: stack.push(arg1); // 27
- case 41: stack.push(stack.pop() * stack.pop()); // 104
- case 42: stack.push(arg4); // 25 4
- case 44: stack.push(arg3); // 29
- case 45: arg3++; // 132 3 1
- case 48: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 49: stack.push(stack.pop() + stack.pop()); // 96
- case 50: arg1 = stack.pop(); // 60
- case 51: arg5++; // 132 5 1
- case 54: gt = 32; continue; // 167 255 234
- case 57: stack.push(arg0); // 42
- case 58: stack.push(arg1); // 27
- case 59: { var v = stack.pop(); stack.pop().hash = v; } // 181 1 98
- case 62: stack.push(arg1); // 27
- case 63: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfIII(self, v0, v1)); } // 182 1 135
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfIII(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().offset); // 180 1 99
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().count); // 180 1 97
- case 8: stack.push(stack.pop() + stack.pop()); // 96
- case 9: arg3 = stack.pop(); // 62
- case 10: stack.push(arg0); // 42
- case 11: stack.push(stack.pop().value); // 180 1 100
- case 14: arg4 = stack.pop() // 58 4
- case 16: stack.push(arg2); // 28
- case 17: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 8
- case 20: stack.push(0); // 3
- case 21: arg2 = stack.pop(); // 61
- case 22: gt = 35; continue; // 167 0 13
- case 25: stack.push(arg2); // 28
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().count); // 180 1 97
- case 30: if (stack.pop() > stack.pop()) { gt = 35; continue; } // 161 0 5
- case 33: // 2
- case 34: return stack.pop(); // 172
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().offset); // 180 1 99
- case 39: stack.push(arg2); // 28
- case 40: stack.push(stack.pop() + stack.pop()); // 96
- case 41: arg5 = stack.pop() // 54 5
- case 43: stack.push(arg1); // 27
- case 44: stack.push(65536); // 18 3
- case 46: if (stack.pop() <= stack.pop()) { gt = 80; continue; } // 162 0 34
- case 49: stack.push(arg5); // 21 5
- case 51: stack.push(arg3); // 29
- case 52: if (stack.pop() <= stack.pop()) { gt = 78; continue; } // 162 0 26
- case 55: stack.push(arg4); // 25 4
- case 57: stack.push(arg5); // 21 5
- case 59: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 60: stack.push(arg1); // 27
- case 61: if (stack.pop() != stack.pop()) { gt = 72; continue; } // 160 0 11
- case 64: stack.push(arg5); // 21 5
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().offset); // 180 1 99
- case 70: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 71: return stack.pop(); // 172
- case 72: arg5++; // 132 5 1
- case 75: gt = 49; continue; // 167 255 230
- case 78: // 2
- case 79: return stack.pop(); // 172
- case 80: stack.push(arg1); // 27
- case 81: stack.push(1114111); // 18 4
- case 83: if (stack.pop() < stack.pop()) { gt = 149; continue; } // 163 0 66
- case 86: stack.push(arg1); // 27
- case 87: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 90: arg6 = stack.pop() // 58 6
- case 92: stack.push(arg5); // 21 5
- case 94: stack.push(arg3); // 29
- case 95: if (stack.pop() <= stack.pop()) { gt = 149; continue; } // 162 0 54
- case 98: stack.push(arg4); // 25 4
- case 100: stack.push(arg5); // 21 5
- case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 103: stack.push(arg6); // 25 6
- case 105: stack.push(0); // 3
- case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 107: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 36
- case 110: stack.push(arg5); // 21 5
- case 112: stack.push(1); // 4
- case 113: stack.push(stack.pop() + stack.pop()); // 96
- case 114: stack.push(arg3); // 29
- case 115: if (stack.pop() != stack.pop()) { gt = 121; continue; } // 160 0 6
- case 118: gt = 149; continue; // 167 0 31
- case 121: stack.push(arg4); // 25 4
- case 123: stack.push(arg5); // 21 5
- case 125: stack.push(1); // 4
- case 126: stack.push(stack.pop() + stack.pop()); // 96
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: stack.push(arg6); // 25 6
- case 130: stack.push(1); // 4
- case 131: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 132: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 11
- case 135: stack.push(arg5); // 21 5
- case 137: stack.push(arg0); // 42
- case 138: stack.push(stack.pop().offset); // 180 1 99
- case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 142: return stack.pop(); // 172
- case 143: arg5++; // 132 5 1
- case 146: gt = 92; continue; // 167 255 202
- case 149: // 2
- case 150: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfII(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(4);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: stack.push(1); // 4
- case 7: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 8: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfIII(self, v0, v1)); } // 182 1 136
- case 11: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfIII(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().offset); // 180 1 99
- case 4: arg3 = stack.pop(); // 62
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().value); // 180 1 100
- case 9: arg4 = stack.pop() // 58 4
- case 11: stack.push(arg0); // 42
- case 12: stack.push(stack.pop().offset); // 180 1 99
- case 15: stack.push(arg2); // 28
- case 16: stack.push(arg0); // 42
- case 17: stack.push(stack.pop().count); // 180 1 97
- case 20: if (stack.pop() > stack.pop()) { gt = 32; continue; } // 161 0 12
- case 23: stack.push(arg0); // 42
- case 24: stack.push(stack.pop().count); // 180 1 97
- case 27: stack.push(1); // 4
- case 28: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 29: gt = 33; continue; // 167 0 4
- case 32: stack.push(arg2); // 28
- case 33: stack.push(stack.pop() + stack.pop()); // 96
- case 34: arg5 = stack.pop() // 54 5
- case 36: stack.push(arg1); // 27
- case 37: stack.push(65536); // 18 3
- case 39: if (stack.pop() <= stack.pop()) { gt = 73; continue; } // 162 0 34
- case 42: stack.push(arg5); // 21 5
- case 44: stack.push(arg3); // 29
- case 45: if (stack.pop() > stack.pop()) { gt = 71; continue; } // 161 0 26
- case 48: stack.push(arg4); // 25 4
- case 50: stack.push(arg5); // 21 5
- case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 53: stack.push(arg1); // 27
- case 54: if (stack.pop() != stack.pop()) { gt = 65; continue; } // 160 0 11
- case 57: stack.push(arg5); // 21 5
- case 59: stack.push(arg0); // 42
- case 60: stack.push(stack.pop().offset); // 180 1 99
- case 63: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 64: return stack.pop(); // 172
- case 65: arg5 += 255; // 132 5 255
- case 68: gt = 42; continue; // 167 255 230
- case 71: // 2
- case 72: return stack.pop(); // 172
- case 73: stack.push(arg0); // 42
- case 74: stack.push(stack.pop().offset); // 180 1 99
- case 77: stack.push(arg0); // 42
- case 78: stack.push(stack.pop().count); // 180 1 97
- case 81: stack.push(stack.pop() + stack.pop()); // 96
- case 82: arg6 = stack.pop() // 54 6
- case 84: stack.push(arg1); // 27
- case 85: stack.push(1114111); // 18 4
- case 87: if (stack.pop() < stack.pop()) { gt = 154; continue; } // 163 0 67
- case 90: stack.push(arg1); // 27
- case 91: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 94: arg7 = stack.pop() // 58 7
- case 96: stack.push(arg5); // 21 5
- case 98: stack.push(arg3); // 29
- case 99: if (stack.pop() > stack.pop()) { gt = 154; continue; } // 161 0 55
- case 102: stack.push(arg4); // 25 4
- case 104: stack.push(arg5); // 21 5
- case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 107: stack.push(arg7); // 25 7
- case 109: stack.push(0); // 3
- case 110: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 111: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 37
- case 114: stack.push(arg5); // 21 5
- case 116: stack.push(1); // 4
- case 117: stack.push(stack.pop() + stack.pop()); // 96
- case 118: stack.push(arg6); // 21 6
- case 120: if (stack.pop() != stack.pop()) { gt = 126; continue; } // 160 0 6
- case 123: gt = 154; continue; // 167 0 31
- case 126: stack.push(arg4); // 25 4
- case 128: stack.push(arg5); // 21 5
- case 130: stack.push(1); // 4
- case 131: stack.push(stack.pop() + stack.pop()); // 96
- case 132: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 133: stack.push(arg7); // 25 7
- case 135: stack.push(1); // 4
- case 136: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 137: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 11
- case 140: stack.push(arg5); // 21 5
- case 142: stack.push(arg0); // 42
- case 143: stack.push(stack.pop().offset); // 180 1 99
- case 146: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 147: return stack.pop(); // 172
- case 148: arg5 += 255; // 132 5 255
- case 151: gt = 96; continue; // 167 255 201
- case 154: // 2
- case 155: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 150
- case 6: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfILjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(7);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: stack.push(arg1); // 43
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: stack.push(arg1); // 43
- case 17: stack.push(stack.pop().offset); // 180 1 99
- case 20: stack.push(arg1); // 43
- case 21: stack.push(stack.pop().count); // 180 1 97
- case 24: stack.push(arg2); // 28
- case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_indexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 144
- case 28: return stack.pop(); // 172
- }
-}
-function java_lang_String_indexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) {
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg6); // 21 6
- case 2: stack.push(arg2); // 28
- case 3: if (stack.pop() > stack.pop()) { gt = 17; continue; } // 161 0 14
- case 6: stack.push(arg5); // 21 5
- case 8: if (stack.pop() != 0) { gt = 15; continue; } // 154 0 7
- case 11: stack.push(arg2); // 28
- case 12: gt = 16; continue; // 167 0 4
- case 15: // 2
- case 16: return stack.pop(); // 172
- case 17: stack.push(arg6); // 21 6
- case 19: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 6
- case 22: stack.push(0); // 3
- case 23: arg6 = stack.pop() // 54 6
- case 25: stack.push(arg5); // 21 5
- case 27: if (stack.pop() != 0) { gt = 33; continue; } // 154 0 6
- case 30: stack.push(arg6); // 21 6
- case 32: return stack.pop(); // 172
- case 33: stack.push(arg3); // 45
- case 34: stack.push(arg4); // 21 4
- case 36: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 37: arg7 = stack.pop() // 54 7
- case 39: stack.push(arg1); // 27
- case 40: stack.push(arg2); // 28
- case 41: stack.push(arg5); // 21 5
- case 43: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 44: stack.push(stack.pop() + stack.pop()); // 96
- case 45: arg8 = stack.pop() // 54 8
- case 47: stack.push(arg1); // 27
- case 48: stack.push(arg6); // 21 6
- case 50: stack.push(stack.pop() + stack.pop()); // 96
- case 51: arg9 = stack.pop() // 54 9
- case 53: stack.push(arg9); // 21 9
- case 55: stack.push(arg8); // 21 8
- case 57: if (stack.pop() < stack.pop()) { gt = 164; continue; } // 163 0 107
- case 60: stack.push(arg0); // 42
- case 61: stack.push(arg9); // 21 9
- case 63: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 64: stack.push(arg7); // 21 7
- case 66: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 25
- case 69: arg9++; // 132 9 1
- case 72: stack.push(arg9); // 21 9
- case 74: stack.push(arg8); // 21 8
- case 76: if (stack.pop() < stack.pop()) { gt = 91; continue; } // 163 0 15
- case 79: stack.push(arg0); // 42
- case 80: stack.push(arg9); // 21 9
- case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 83: stack.push(arg7); // 21 7
- case 85: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 6
- case 88: gt = 69; continue; // 167 255 237
- case 91: stack.push(arg9); // 21 9
- case 93: stack.push(arg8); // 21 8
- case 95: if (stack.pop() < stack.pop()) { gt = 158; continue; } // 163 0 63
- case 98: stack.push(arg9); // 21 9
- case 100: stack.push(1); // 4
- case 101: stack.push(stack.pop() + stack.pop()); // 96
- case 102: arg10 = stack.pop() // 54 10
- case 104: stack.push(arg10); // 21 10
- case 106: stack.push(arg5); // 21 5
- case 108: stack.push(stack.pop() + stack.pop()); // 96
- case 109: stack.push(1); // 4
- case 110: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 111: arg11 = stack.pop() // 54 11
- case 113: stack.push(arg4); // 21 4
- case 115: stack.push(1); // 4
- case 116: stack.push(stack.pop() + stack.pop()); // 96
- case 117: arg12 = stack.pop() // 54 12
- case 119: stack.push(arg10); // 21 10
- case 121: stack.push(arg11); // 21 11
- case 123: if (stack.pop() <= stack.pop()) { gt = 146; continue; } // 162 0 23
- case 126: stack.push(arg0); // 42
- case 127: stack.push(arg10); // 21 10
- case 129: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 130: stack.push(arg3); // 45
- case 131: stack.push(arg12); // 21 12
- case 133: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 134: if (stack.pop() != stack.pop()) { gt = 146; continue; } // 160 0 12
- case 137: arg10++; // 132 10 1
- case 140: arg12++; // 132 12 1
- case 143: gt = 119; continue; // 167 255 232
- case 146: stack.push(arg10); // 21 10
- case 148: stack.push(arg11); // 21 11
- case 150: if (stack.pop() != stack.pop()) { gt = 158; continue; } // 160 0 8
- case 153: stack.push(arg9); // 21 9
- case 155: stack.push(arg1); // 27
- case 156: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 157: return stack.pop(); // 172
- case 158: arg9++; // 132 9 1
- case 161: gt = 53; continue; // 167 255 148
- case 164: // 2
- case 165: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfILjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 151
- case 9: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfILjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(7);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().value); // 180 1 100
- case 4: stack.push(arg0); // 42
- case 5: stack.push(stack.pop().offset); // 180 1 99
- case 8: stack.push(arg0); // 42
- case 9: stack.push(stack.pop().count); // 180 1 97
- case 12: stack.push(arg1); // 43
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: stack.push(arg1); // 43
- case 17: stack.push(stack.pop().offset); // 180 1 99
- case 20: stack.push(arg1); // 43
- case 21: stack.push(stack.pop().count); // 180 1 97
- case 24: stack.push(arg2); // 28
- case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_lastIndexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 145
- case 28: return stack.pop(); // 172
- }
-}
-function java_lang_String_lastIndexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) {
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg2); // 28
- case 1: stack.push(arg5); // 21 5
- case 3: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 4: arg7 = stack.pop() // 54 7
- case 6: stack.push(arg6); // 21 6
- case 8: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 5
- case 11: // 2
- case 12: return stack.pop(); // 172
- case 13: stack.push(arg6); // 21 6
- case 15: stack.push(arg7); // 21 7
- case 17: if (stack.pop() >= stack.pop()) { gt = 24; continue; } // 164 0 7
- case 20: stack.push(arg7); // 21 7
- case 22: arg6 = stack.pop() // 54 6
- case 24: stack.push(arg5); // 21 5
- case 26: if (stack.pop() != 0) { gt = 32; continue; } // 154 0 6
- case 29: stack.push(arg6); // 21 6
- case 31: return stack.pop(); // 172
- case 32: stack.push(arg4); // 21 4
- case 34: stack.push(arg5); // 21 5
- case 36: stack.push(stack.pop() + stack.pop()); // 96
- case 37: stack.push(1); // 4
- case 38: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 39: arg8 = stack.pop() // 54 8
- case 41: stack.push(arg3); // 45
- case 42: stack.push(arg8); // 21 8
- case 44: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 45: arg9 = stack.pop() // 54 9
- case 47: stack.push(arg1); // 27
- case 48: stack.push(arg5); // 21 5
- case 50: stack.push(stack.pop() + stack.pop()); // 96
- case 51: stack.push(1); // 4
- case 52: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 53: arg10 = stack.pop() // 54 10
- case 55: stack.push(arg10); // 21 10
- case 57: stack.push(arg6); // 21 6
- case 59: stack.push(stack.pop() + stack.pop()); // 96
- case 60: arg11 = stack.pop() // 54 11
- case 62: stack.push(arg11); // 21 11
- case 64: stack.push(arg10); // 21 10
- case 66: if (stack.pop() > stack.pop()) { gt = 84; continue; } // 161 0 18
- case 69: stack.push(arg0); // 42
- case 70: stack.push(arg11); // 21 11
- case 72: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 73: stack.push(arg9); // 21 9
- case 75: if (stack.pop() == stack.pop()) { gt = 84; continue; } // 159 0 9
- case 78: arg11 += 255; // 132 11 255
- case 81: gt = 62; continue; // 167 255 237
- case 84: stack.push(arg11); // 21 11
- case 86: stack.push(arg10); // 21 10
- case 88: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 5
- case 91: // 2
- case 92: return stack.pop(); // 172
- case 93: stack.push(arg11); // 21 11
- case 95: stack.push(1); // 4
- case 96: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 97: arg12 = stack.pop() // 54 12
- case 99: stack.push(arg12); // 21 12
- case 101: stack.push(arg5); // 21 5
- case 103: stack.push(1); // 4
- case 104: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 105: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 106: arg13 = stack.pop() // 54 13
- case 108: stack.push(arg8); // 21 8
- case 110: stack.push(1); // 4
- case 111: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 112: arg14 = stack.pop() // 54 14
- case 114: stack.push(arg12); // 21 12
- case 116: stack.push(arg13); // 21 13
- case 118: if (stack.pop() >= stack.pop()) { gt = 144; continue; } // 164 0 26
- case 121: stack.push(arg0); // 42
- case 122: stack.push(arg12); // 21 12
- case 124: arg12 += 255; // 132 12 255
- case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 128: stack.push(arg3); // 45
- case 129: stack.push(arg14); // 21 14
- case 131: arg14 += 255; // 132 14 255
- case 134: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 135: if (stack.pop() == stack.pop()) { gt = 114; continue; } // 159 255 235
- case 138: arg11 += 255; // 132 11 255
- case 141: gt = 62; continue; // 167 255 177
- case 144: stack.push(arg13); // 21 13
- case 146: stack.push(arg1); // 27
- case 147: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 148: stack.push(1); // 4
- case 149: stack.push(stack.pop() + stack.pop()); // 96
- case 150: return stack.pop(); // 172
- }
-}
-function java_lang_String_substringLjava_lang_StringI(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().count); // 180 1 97
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 9: return stack.pop(); // 176
- }
-}
-function java_lang_String_substringLjava_lang_StringII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12
- case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: stack.push(arg1); // 27
- case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 12: // 191
- case 13: stack.push(arg2); // 28
- case 14: stack.push(arg0); // 42
- case 15: stack.push(stack.pop().count); // 180 1 97
- case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12
- case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 24: stack.push(stack[stack.length - 1]); // 89
- case 25: stack.push(arg2); // 28
- case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 29: // 191
- case 30: stack.push(arg1); // 27
- case 31: stack.push(arg2); // 28
- case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14
- case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206
- case 38: stack.push(stack[stack.length - 1]); // 89
- case 39: stack.push(arg2); // 28
- case 40: stack.push(arg1); // 27
- case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169
- case 45: // 191
- case 46: stack.push(arg1); // 27
- case 47: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 15
- case 50: stack.push(arg2); // 28
- case 51: stack.push(arg0); // 42
- case 52: stack.push(stack.pop().count); // 180 1 97
- case 55: if (stack.pop() != stack.pop()) { gt = 62; continue; } // 160 0 7
- case 58: stack.push(arg0); // 42
- case 59: gt = 82; continue; // 167 0 23
- case 62: stack.push(new java_lang_String); // 187 0 200
- case 65: stack.push(stack[stack.length - 1]); // 89
- case 66: stack.push(arg0); // 42
- case 67: stack.push(stack.pop().offset); // 180 1 99
- case 70: stack.push(arg1); // 27
- case 71: stack.push(stack.pop() + stack.pop()); // 96
- case 72: stack.push(arg2); // 28
- case 73: stack.push(arg1); // 27
- case 74: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 75: stack.push(arg0); // 42
- case 76: stack.push(stack.pop().value); // 180 1 100
- case 79: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 82: return stack.pop(); // 176
- }
-}
-function java_lang_String_subSequenceLjava_lang_CharSequenceII(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 27
- case 2: stack.push(arg2); // 28
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_concatLjava_lang_StringLjava_lang_String(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 182 1 133
- case 4: arg2 = stack.pop(); // 61
- case 5: stack.push(arg2); // 28
- case 6: if (stack.pop() != 0) { gt = 11; continue; } // 154 0 5
- case 9: stack.push(arg0); // 42
- case 10: return stack.pop(); // 176
- case 11: stack.push(arg0); // 42
- case 12: stack.push(stack.pop().count); // 180 1 97
- case 15: stack.push(arg2); // 28
- case 16: stack.push(stack.pop() + stack.pop()); // 96
- case 17: stack.push(new Array(stack.pop())); // 188 5
- case 19: arg3 = stack.pop(); // 78
- case 20: stack.push(arg0); // 42
- case 21: stack.push(0); // 3
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().count); // 180 1 97
- case 26: stack.push(arg3); // 45
- case 27: stack.push(0); // 3
- case 28: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 31: stack.push(arg1); // 43
- case 32: stack.push(0); // 3
- case 33: stack.push(arg2); // 28
- case 34: stack.push(arg3); // 45
- case 35: stack.push(arg0); // 42
- case 36: stack.push(stack.pop().count); // 180 1 97
- case 39: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 42: stack.push(new java_lang_String); // 187 0 200
- case 45: stack.push(stack[stack.length - 1]); // 89
- case 46: stack.push(0); // 3
- case 47: stack.push(arg0); // 42
- case 48: stack.push(stack.pop().count); // 180 1 97
- case 51: stack.push(arg2); // 28
- case 52: stack.push(stack.pop() + stack.pop()); // 96
- case 53: stack.push(arg3); // 45
- case 54: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 57: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) {
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 27
- case 1: stack.push(arg2); // 28
- case 2: if (stack.pop() == stack.pop()) { gt = 140; continue; } // 159 0 138
- case 5: stack.push(arg0); // 42
- case 6: stack.push(stack.pop().count); // 180 1 97
- case 9: arg3 = stack.pop(); // 62
- case 10: // 2
- case 11: arg4 = stack.pop() // 54 4
- case 13: stack.push(arg0); // 42
- case 14: stack.push(stack.pop().value); // 180 1 100
- case 17: arg5 = stack.pop() // 58 5
- case 19: stack.push(arg0); // 42
- case 20: stack.push(stack.pop().offset); // 180 1 99
- case 23: arg6 = stack.pop() // 54 6
- case 25: arg4++; // 132 4 1
- case 28: stack.push(arg4); // 21 4
- case 30: stack.push(arg3); // 29
- case 31: if (stack.pop() <= stack.pop()) { gt = 49; continue; } // 162 0 18
- case 34: stack.push(arg5); // 25 5
- case 36: stack.push(arg6); // 21 6
- case 38: stack.push(arg4); // 21 4
- case 40: stack.push(stack.pop() + stack.pop()); // 96
- case 41: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 42: stack.push(arg1); // 27
- case 43: if (stack.pop() != stack.pop()) { gt = 25; continue; } // 160 255 238
- case 46: gt = 49; continue; // 167 0 3
- case 49: stack.push(arg4); // 21 4
- case 51: stack.push(arg3); // 29
- case 52: if (stack.pop() <= stack.pop()) { gt = 140; continue; } // 162 0 88
- case 55: stack.push(arg3); // 29
- case 56: stack.push(new Array(stack.pop())); // 188 5
- case 58: arg7 = stack.pop() // 58 7
- case 60: stack.push(0); // 3
- case 61: arg8 = stack.pop() // 54 8
- case 63: stack.push(arg8); // 21 8
- case 65: stack.push(arg4); // 21 4
- case 67: if (stack.pop() <= stack.pop()) { gt = 89; continue; } // 162 0 22
- case 70: stack.push(arg7); // 25 7
- case 72: stack.push(arg8); // 21 8
- case 74: stack.push(arg5); // 25 5
- case 76: stack.push(arg6); // 21 6
- case 78: stack.push(arg8); // 21 8
- case 80: stack.push(stack.pop() + stack.pop()); // 96
- case 81: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 82: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 83: arg8++; // 132 8 1
- case 86: gt = 63; continue; // 167 255 233
- case 89: stack.push(arg4); // 21 4
- case 91: stack.push(arg3); // 29
- case 92: if (stack.pop() <= stack.pop()) { gt = 128; continue; } // 162 0 36
- case 95: stack.push(arg5); // 25 5
- case 97: stack.push(arg6); // 21 6
- case 99: stack.push(arg4); // 21 4
- case 101: stack.push(stack.pop() + stack.pop()); // 96
- case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 103: arg8 = stack.pop() // 54 8
- case 105: stack.push(arg7); // 25 7
- case 107: stack.push(arg4); // 21 4
- case 109: stack.push(arg8); // 21 8
- case 111: stack.push(arg1); // 27
- case 112: if (stack.pop() != stack.pop()) { gt = 119; continue; } // 160 0 7
- case 115: stack.push(arg2); // 28
- case 116: gt = 121; continue; // 167 0 5
- case 119: stack.push(arg8); // 21 8
- case 121: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 122: arg4++; // 132 4 1
- case 125: gt = 89; continue; // 167 255 220
- case 128: stack.push(new java_lang_String); // 187 0 200
- case 131: stack.push(stack[stack.length - 1]); // 89
- case 132: stack.push(0); // 3
- case 133: stack.push(arg3); // 29
- case 134: stack.push(arg7); // 25 7
- case 136: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 139: return stack.pop(); // 176
- case 140: stack.push(arg0); // 42
- case 141: return stack.pop(); // 176
- }
-}
-function java_lang_String_matchesZLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: stack.push(arg0); // 42
- case 2: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_matchesZLjava_lang_StringLjava_lang_CharSequence(v0, v1)); } // 184 1 183
- case 5: return stack.pop(); // 172
- }
-}
-function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_String(self, v0)); } // 182 1 149
- case 8: // 2
- case 9: if (stack.pop() >= stack.pop()) { gt = 16; continue; } // 164 0 7
- case 12: stack.push(1); // 4
- case 13: gt = 17; continue; // 167 0 4
- case 16: stack.push(0); // 3
- case 17: return stack.pop(); // 172
- }
-}
-function java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 8: stack.push(arg2); // 44
- case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceFirstLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 182
- case 12: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 8: stack.push(arg2); // 44
- case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181
- case 12: return stack.pop(); // 176
- }
-}
-function java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 4: stack.push(16); // 16 16
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_StringI(v0, v1)); } // 184 1 187
- case 9: stack.push(arg0); // 42
- case 10: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185
- case 13: stack.push(arg2); // 44
- case 14: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 17: { var v0 = stack.pop(); stack.push(java_util_regex_Matcher_quoteReplacementLjava_lang_StringLjava_lang_String(v0)); } // 184 1 180
- case 20: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181
- case 23: return stack.pop(); // 176
- }
-}
-function java_lang_String_splitALjava_lang_StringLjava_lang_StringI(arg0,arg1,arg2) {
- var arg3;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg2); // 28
- case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_CharSequenceI(self, v0, v1)); } // 182 1 184
- case 9: return stack.pop(); // 176
- }
-}
-function java_lang_String_splitALjava_lang_StringLjava_lang_String(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: stack.push(0); // 3
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_StringI(self, v0, v1)); } // 182 1 157
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(0); // 3
- case 13: arg2 = stack.pop(); // 61
- case 14: stack.push(arg2); // 28
- case 15: stack.push(arg0); // 42
- case 16: stack.push(stack.pop().count); // 180 1 97
- case 19: if (stack.pop() <= stack.pop()) { gt = 94; continue; } // 162 0 75
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: stack.push(arg2); // 28
- case 31: stack.push(stack.pop() + stack.pop()); // 96
- case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 33: arg3 = stack.pop(); // 62
- case 34: stack.push(arg3); // 29
- case 35: stack.push(55296); // 18 1
- case 37: if (stack.pop() > stack.pop()) { gt = 77; continue; } // 161 0 40
- case 40: stack.push(arg3); // 29
- case 41: stack.push(56319); // 18 2
- case 43: if (stack.pop() < stack.pop()) { gt = 77; continue; } // 163 0 34
- case 46: stack.push(arg0); // 42
- case 47: stack.push(arg2); // 28
- case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 51: arg4 = stack.pop() // 54 4
- case 53: stack.push(arg4); // 21 4
- case 55: stack.push(arg4); // 21 4
- case 57: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107
- case 60: if (stack.pop() == stack.pop()) { gt = 66; continue; } // 159 0 6
- case 63: gt = 96; continue; // 167 0 33
- case 66: stack.push(arg2); // 28
- case 67: stack.push(arg4); // 21 4
- case 69: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 72: stack.push(stack.pop() + stack.pop()); // 96
- case 73: arg2 = stack.pop(); // 61
- case 74: gt = 91; continue; // 167 0 17
- case 77: stack.push(arg3); // 29
- case 78: stack.push(arg3); // 29
- case 79: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104
- case 82: if (stack.pop() == stack.pop()) { gt = 88; continue; } // 159 0 6
- case 85: gt = 96; continue; // 167 0 11
- case 88: arg2++; // 132 2 1
- case 91: gt = 14; continue; // 167 255 179
- case 94: stack.push(arg0); // 42
- case 95: return stack.pop(); // 176
- case 96: stack.push(arg0); // 42
- case 97: stack.push(stack.pop().count); // 180 1 97
- case 100: stack.push(new Array(stack.pop())); // 188 5
- case 102: arg3 = stack.pop(); // 78
- case 103: stack.push(0); // 3
- case 104: arg4 = stack.pop() // 54 4
- case 106: stack.push(arg0); // 42
- case 107: stack.push(stack.pop().value); // 180 1 100
- case 110: stack.push(arg0); // 42
- case 111: stack.push(stack.pop().offset); // 180 1 99
- case 114: stack.push(arg3); // 45
- case 115: stack.push(0); // 3
- case 116: stack.push(arg2); // 28
- case 117: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 120: stack.push(arg1); // 43
- case 121: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178
- case 124: arg5 = stack.pop() // 58 5
- case 126: stack.push(arg5); // 25 5
- case 128: stack.push("tr"); // 18 11
- case 130: // 165
- case 131: // 0
- case 132: stack.push(6405); // 17 25 5
- case 135: stack.push("az"); // 18 5
- case 137: // 165
- case 138: // 0
- case 139: stack.push(1); // 10
- case 140: stack.push(arg5); // 25 5
- case 142: stack.push("lt"); // 18 9
- case 144: // 166
- case 145: // 0
- case 146: stack.push(4); // 7
- case 147: stack.push(1); // 4
- case 148: gt = 152; continue; // 167 0 4
- case 151: stack.push(0); // 3
- case 152: arg6 = stack.pop() // 54 6
- case 154: stack.push(arg2); // 28
- case 155: arg11 = stack.pop() // 54 11
- case 157: stack.push(arg11); // 21 11
- case 159: stack.push(arg0); // 42
- case 160: stack.push(stack.pop().count); // 180 1 97
- case 163: if (stack.pop() <= stack.pop()) { gt = 419; continue; } // 162 1 0
- case 166: stack.push(arg0); // 42
- case 167: stack.push(stack.pop().value); // 180 1 100
- case 170: stack.push(arg0); // 42
- case 171: stack.push(stack.pop().offset); // 180 1 99
- case 174: stack.push(arg11); // 21 11
- case 176: stack.push(stack.pop() + stack.pop()); // 96
- case 177: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 178: arg9 = stack.pop() // 54 9
- case 180: stack.push(arg9); // 21 9
- case 182: // number conversion // 146
- case 183: stack.push(55296); // 18 1
- case 185: if (stack.pop() > stack.pop()) { gt = 214; continue; } // 161 0 29
- case 188: stack.push(arg9); // 21 9
- case 190: // number conversion // 146
- case 191: stack.push(56319); // 18 2
- case 193: if (stack.pop() < stack.pop()) { gt = 214; continue; } // 163 0 21
- case 196: stack.push(arg0); // 42
- case 197: stack.push(arg11); // 21 11
- case 199: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 202: arg9 = stack.pop() // 54 9
- case 204: stack.push(arg9); // 21 9
- case 206: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 209: arg10 = stack.pop() // 54 10
- case 211: gt = 217; continue; // 167 0 6
- case 214: stack.push(1); // 4
- case 215: arg10 = stack.pop() // 54 10
- case 217: stack.push(arg6); // 21 6
- case 219: if (stack.pop() != 0) { gt = 230; continue; } // 154 0 11
- case 222: stack.push(arg9); // 21 9
- case 224: stack.push(931); // 17 3 163
- case 227: if (stack.pop() != stack.pop()) { gt = 242; continue; } // 160 0 15
- case 230: stack.push(arg0); // 42
- case 231: stack.push(arg11); // 21 11
- case 233: stack.push(arg1); // 43
- case 234: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 117
- case 237: arg8 = stack.pop() // 54 8
- case 239: gt = 249; continue; // 167 0 10
- case 242: stack.push(arg9); // 21 9
- case 244: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107
- case 247: arg8 = stack.pop() // 54 8
- case 249: stack.push(arg8); // 21 8
- case 251: // 2
- case 252: if (stack.pop() == stack.pop()) { gt = 262; continue; } // 159 0 10
- case 255: stack.push(arg8); // 21 8
- case 257: stack.push(65536); // 18 3
- case 259: if (stack.pop() > stack.pop()) { gt = 399; continue; } // 161 0 140
- case 262: stack.push(arg8); // 21 8
- case 264: // 2
- case 265: if (stack.pop() != stack.pop()) { gt = 280; continue; } // 160 0 15
- case 268: stack.push(arg0); // 42
- case 269: stack.push(arg11); // 21 11
- case 271: stack.push(arg1); // 43
- case 272: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 119
- case 275: arg7 = stack.pop() // 58 7
- case 277: gt = 315; continue; // 167 0 38
- case 280: stack.push(arg10); // 21 10
- case 282: stack.push(2); // 5
- case 283: if (stack.pop() != stack.pop()) { gt = 308; continue; } // 160 0 25
- case 286: stack.push(arg4); // 21 4
- case 288: stack.push(arg8); // 21 8
- case 290: stack.push(arg3); // 45
- case 291: stack.push(arg11); // 21 11
- case 293: stack.push(arg4); // 21 4
- case 295: stack.push(stack.pop() + stack.pop()); // 96
- case 296: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111
- case 299: stack.push(arg10); // 21 10
- case 301: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 302: stack.push(stack.pop() + stack.pop()); // 96
- case 303: arg4 = stack.pop() // 54 4
- case 305: gt = 409; continue; // 167 0 104
- case 308: stack.push(arg8); // 21 8
- case 310: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 313: arg7 = stack.pop() // 58 7
- case 315: stack.push(arg7); // 25 7
- case 317: stack.push(stack.pop().length); // 190
- case 318: arg12 = stack.pop() // 54 12
- case 320: stack.push(arg12); // 21 12
- case 322: stack.push(arg10); // 21 10
- case 324: if (stack.pop() >= stack.pop()) { gt = 355; continue; } // 164 0 31
- case 327: stack.push(arg3); // 45
- case 328: stack.push(stack.pop().length); // 190
- case 329: stack.push(arg12); // 21 12
- case 331: stack.push(stack.pop() + stack.pop()); // 96
- case 332: stack.push(arg10); // 21 10
- case 334: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 335: stack.push(new Array(stack.pop())); // 188 5
- case 337: arg13 = stack.pop() // 58 13
- case 339: stack.push(arg3); // 45
- case 340: stack.push(0); // 3
- case 341: stack.push(arg13); // 25 13
- case 343: stack.push(0); // 3
- case 344: stack.push(arg11); // 21 11
- case 346: stack.push(arg4); // 21 4
- case 348: stack.push(stack.pop() + stack.pop()); // 96
- case 349: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 352: stack.push(arg13); // 25 13
- case 354: arg3 = stack.pop(); // 78
- case 355: stack.push(0); // 3
- case 356: arg13 = stack.pop() // 54 13
- case 358: stack.push(arg13); // 21 13
- case 360: stack.push(arg12); // 21 12
- case 362: if (stack.pop() <= stack.pop()) { gt = 386; continue; } // 162 0 24
- case 365: stack.push(arg3); // 45
- case 366: stack.push(arg11); // 21 11
- case 368: stack.push(arg4); // 21 4
- case 370: stack.push(stack.pop() + stack.pop()); // 96
- case 371: stack.push(arg13); // 21 13
- case 373: stack.push(stack.pop() + stack.pop()); // 96
- case 374: stack.push(arg7); // 25 7
- case 376: stack.push(arg13); // 21 13
- case 378: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 379: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 380: arg13++; // 132 13 1
- case 383: gt = 358; continue; // 167 255 231
- case 386: stack.push(arg4); // 21 4
- case 388: stack.push(arg12); // 21 12
- case 390: stack.push(arg10); // 21 10
- case 392: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 393: stack.push(stack.pop() + stack.pop()); // 96
- case 394: arg4 = stack.pop() // 54 4
- case 396: gt = 409; continue; // 167 0 13
- case 399: stack.push(arg3); // 45
- case 400: stack.push(arg11); // 21 11
- case 402: stack.push(arg4); // 21 4
- case 404: stack.push(stack.pop() + stack.pop()); // 96
- case 405: stack.push(arg8); // 21 8
- case 407: // number conversion // 146
- case 408: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 409: stack.push(arg11); // 21 11
- case 411: stack.push(arg10); // 21 10
- case 413: stack.push(stack.pop() + stack.pop()); // 96
- case 414: arg11 = stack.pop() // 54 11
- case 416: gt = 157; continue; // 167 254 253
- case 419: stack.push(new java_lang_String); // 187 0 200
- case 422: stack.push(stack[stack.length - 1]); // 89
- case 423: stack.push(0); // 3
- case 424: stack.push(arg0); // 42
- case 425: stack.push(stack.pop().count); // 180 1 97
- case 428: stack.push(arg4); // 21 4
- case 430: stack.push(stack.pop() + stack.pop()); // 96
- case 431: stack.push(arg3); // 45
- case 432: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 435: return stack.pop(); // 176
- }
-}
-function java_lang_String_toLowerCaseLjava_lang_String(arg0) {
- var arg1;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179
- case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toLowerCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 158
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) {
- var arg2;
- var arg3;
- var arg4;
- var arg5;
- var arg6;
- var arg7;
- var arg8;
- var arg9;
- var arg10;
- var arg11;
- var arg12;
- var arg13;
- var arg14;
-;
- var stack = new Array(6);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg1); // 43
- case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11
- case 4: stack.push(new java_lang_NullPointerException); // 187 0 198
- case 7: stack.push(stack[stack.length - 1]); // 89
- case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128
- case 11: // 191
- case 12: stack.push(0); // 3
- case 13: arg2 = stack.pop(); // 61
- case 14: stack.push(arg2); // 28
- case 15: stack.push(arg0); // 42
- case 16: stack.push(stack.pop().count); // 180 1 97
- case 19: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 74
- case 22: stack.push(arg0); // 42
- case 23: stack.push(stack.pop().value); // 180 1 100
- case 26: stack.push(arg0); // 42
- case 27: stack.push(stack.pop().offset); // 180 1 99
- case 30: stack.push(arg2); // 28
- case 31: stack.push(stack.pop() + stack.pop()); // 96
- case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 33: arg3 = stack.pop(); // 62
- case 34: stack.push(arg3); // 29
- case 35: stack.push(55296); // 18 1
- case 37: if (stack.pop() > stack.pop()) { gt = 61; continue; } // 161 0 24
- case 40: stack.push(arg3); // 29
- case 41: stack.push(56319); // 18 2
- case 43: if (stack.pop() < stack.pop()) { gt = 61; continue; } // 163 0 18
- case 46: stack.push(arg0); // 42
- case 47: stack.push(arg2); // 28
- case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 51: arg3 = stack.pop(); // 62
- case 52: stack.push(arg3); // 29
- case 53: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 56: arg4 = stack.pop() // 54 4
- case 58: gt = 64; continue; // 167 0 6
- case 61: stack.push(1); // 4
- case 62: arg4 = stack.pop() // 54 4
- case 64: stack.push(arg3); // 29
- case 65: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108
- case 68: arg5 = stack.pop() // 54 5
- case 70: stack.push(arg5); // 21 5
- case 72: // 2
- case 73: if (stack.pop() == stack.pop()) { gt = 95; continue; } // 159 0 22
- case 76: stack.push(arg3); // 29
- case 77: stack.push(arg5); // 21 5
- case 79: if (stack.pop() == stack.pop()) { gt = 85; continue; } // 159 0 6
- case 82: gt = 95; continue; // 167 0 13
- case 85: stack.push(arg2); // 28
- case 86: stack.push(arg4); // 21 4
- case 88: stack.push(stack.pop() + stack.pop()); // 96
- case 89: arg2 = stack.pop(); // 61
- case 90: gt = 14; continue; // 167 255 180
- case 93: stack.push(arg0); // 42
- case 94: return stack.pop(); // 176
- case 95: stack.push(arg0); // 42
- case 96: stack.push(stack.pop().count); // 180 1 97
- case 99: stack.push(new Array(stack.pop())); // 188 5
- case 101: arg3 = stack.pop(); // 78
- case 102: stack.push(0); // 3
- case 103: arg4 = stack.pop() // 54 4
- case 105: stack.push(arg0); // 42
- case 106: stack.push(stack.pop().value); // 180 1 100
- case 109: stack.push(arg0); // 42
- case 110: stack.push(stack.pop().offset); // 180 1 99
- case 113: stack.push(arg3); // 45
- case 114: stack.push(0); // 3
- case 115: stack.push(arg2); // 28
- case 116: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 119: stack.push(arg1); // 43
- case 120: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178
- case 123: arg5 = stack.pop() // 58 5
- case 125: stack.push(arg5); // 25 5
- case 127: stack.push("tr"); // 18 11
- case 129: // 165
- case 130: // 0
- case 131: stack.push(6405); // 17 25 5
- case 134: stack.push("az"); // 18 5
- case 136: // 165
- case 137: // 0
- case 138: stack.push(1); // 10
- case 139: stack.push(arg5); // 25 5
- case 141: stack.push("lt"); // 18 9
- case 143: // 166
- case 144: // 0
- case 145: stack.push(4); // 7
- case 146: stack.push(1); // 4
- case 147: gt = 151; continue; // 167 0 4
- case 150: stack.push(0); // 3
- case 151: arg6 = stack.pop() // 54 6
- case 153: stack.push(arg2); // 28
- case 154: arg11 = stack.pop() // 54 11
- case 156: stack.push(arg11); // 21 11
- case 158: stack.push(arg0); // 42
- case 159: stack.push(stack.pop().count); // 180 1 97
- case 162: if (stack.pop() <= stack.pop()) { gt = 425; continue; } // 162 1 7
- case 165: stack.push(arg0); // 42
- case 166: stack.push(stack.pop().value); // 180 1 100
- case 169: stack.push(arg0); // 42
- case 170: stack.push(stack.pop().offset); // 180 1 99
- case 173: stack.push(arg11); // 21 11
- case 175: stack.push(stack.pop() + stack.pop()); // 96
- case 176: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 177: arg9 = stack.pop() // 54 9
- case 179: stack.push(arg9); // 21 9
- case 181: // number conversion // 146
- case 182: stack.push(55296); // 18 1
- case 184: if (stack.pop() > stack.pop()) { gt = 213; continue; } // 161 0 29
- case 187: stack.push(arg9); // 21 9
- case 189: // number conversion // 146
- case 190: stack.push(56319); // 18 2
- case 192: if (stack.pop() < stack.pop()) { gt = 213; continue; } // 163 0 21
- case 195: stack.push(arg0); // 42
- case 196: stack.push(arg11); // 21 11
- case 198: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134
- case 201: arg9 = stack.pop() // 54 9
- case 203: stack.push(arg9); // 21 9
- case 205: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106
- case 208: arg10 = stack.pop() // 54 10
- case 210: gt = 216; continue; // 167 0 6
- case 213: stack.push(1); // 4
- case 214: arg10 = stack.pop() // 54 10
- case 216: stack.push(arg6); // 21 6
- case 218: if (stack.pop() == 0) { gt = 233; continue; } // 153 0 15
- case 221: stack.push(arg0); // 42
- case 222: stack.push(arg11); // 21 11
- case 224: stack.push(arg1); // 43
- case 225: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 118
- case 228: arg8 = stack.pop() // 54 8
- case 230: gt = 240; continue; // 167 0 10
- case 233: stack.push(arg9); // 21 9
- case 235: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108
- case 238: arg8 = stack.pop() // 54 8
- case 240: stack.push(arg8); // 21 8
- case 242: // 2
- case 243: if (stack.pop() == stack.pop()) { gt = 253; continue; } // 159 0 10
- case 246: stack.push(arg8); // 21 8
- case 248: stack.push(65536); // 18 3
- case 250: if (stack.pop() > stack.pop()) { gt = 405; continue; } // 161 0 155
- case 253: stack.push(arg8); // 21 8
- case 255: // 2
- case 256: if (stack.pop() != stack.pop()) { gt = 286; continue; } // 160 0 30
- case 259: stack.push(arg6); // 21 6
- case 261: if (stack.pop() == 0) { gt = 276; continue; } // 153 0 15
- case 264: stack.push(arg0); // 42
- case 265: stack.push(arg11); // 21 11
- case 267: stack.push(arg1); // 43
- case 268: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 120
- case 271: arg7 = stack.pop() // 58 7
- case 273: gt = 321; continue; // 167 0 48
- case 276: stack.push(arg9); // 21 9
- case 278: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCharArrayACI(v0)); } // 184 1 110
- case 281: arg7 = stack.pop() // 58 7
- case 283: gt = 321; continue; // 167 0 38
- case 286: stack.push(arg10); // 21 10
- case 288: stack.push(2); // 5
- case 289: if (stack.pop() != stack.pop()) { gt = 314; continue; } // 160 0 25
- case 292: stack.push(arg4); // 21 4
- case 294: stack.push(arg8); // 21 8
- case 296: stack.push(arg3); // 45
- case 297: stack.push(arg11); // 21 11
- case 299: stack.push(arg4); // 21 4
- case 301: stack.push(stack.pop() + stack.pop()); // 96
- case 302: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111
- case 305: stack.push(arg10); // 21 10
- case 307: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 308: stack.push(stack.pop() + stack.pop()); // 96
- case 309: arg4 = stack.pop() // 54 4
- case 311: gt = 415; continue; // 167 0 104
- case 314: stack.push(arg8); // 21 8
- case 316: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109
- case 319: arg7 = stack.pop() // 58 7
- case 321: stack.push(arg7); // 25 7
- case 323: stack.push(stack.pop().length); // 190
- case 324: arg12 = stack.pop() // 54 12
- case 326: stack.push(arg12); // 21 12
- case 328: stack.push(arg10); // 21 10
- case 330: if (stack.pop() >= stack.pop()) { gt = 361; continue; } // 164 0 31
- case 333: stack.push(arg3); // 45
- case 334: stack.push(stack.pop().length); // 190
- case 335: stack.push(arg12); // 21 12
- case 337: stack.push(stack.pop() + stack.pop()); // 96
- case 338: stack.push(arg10); // 21 10
- case 340: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 341: stack.push(new Array(stack.pop())); // 188 5
- case 343: arg13 = stack.pop() // 58 13
- case 345: stack.push(arg3); // 45
- case 346: stack.push(0); // 3
- case 347: stack.push(arg13); // 25 13
- case 349: stack.push(0); // 3
- case 350: stack.push(arg11); // 21 11
- case 352: stack.push(arg4); // 21 4
- case 354: stack.push(stack.pop() + stack.pop()); // 96
- case 355: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171
- case 358: stack.push(arg13); // 25 13
- case 360: arg3 = stack.pop(); // 78
- case 361: stack.push(0); // 3
- case 362: arg13 = stack.pop() // 54 13
- case 364: stack.push(arg13); // 21 13
- case 366: stack.push(arg12); // 21 12
- case 368: if (stack.pop() <= stack.pop()) { gt = 392; continue; } // 162 0 24
- case 371: stack.push(arg3); // 45
- case 372: stack.push(arg11); // 21 11
- case 374: stack.push(arg4); // 21 4
- case 376: stack.push(stack.pop() + stack.pop()); // 96
- case 377: stack.push(arg13); // 21 13
- case 379: stack.push(stack.pop() + stack.pop()); // 96
- case 380: stack.push(arg7); // 25 7
- case 382: stack.push(arg13); // 21 13
- case 384: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 385: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 386: arg13++; // 132 13 1
- case 389: gt = 364; continue; // 167 255 231
- case 392: stack.push(arg4); // 21 4
- case 394: stack.push(arg12); // 21 12
- case 396: stack.push(arg10); // 21 10
- case 398: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 399: stack.push(stack.pop() + stack.pop()); // 96
- case 400: arg4 = stack.pop() // 54 4
- case 402: gt = 415; continue; // 167 0 13
- case 405: stack.push(arg3); // 45
- case 406: stack.push(arg11); // 21 11
- case 408: stack.push(arg4); // 21 4
- case 410: stack.push(stack.pop() + stack.pop()); // 96
- case 411: stack.push(arg8); // 21 8
- case 413: // number conversion // 146
- case 414: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 415: stack.push(arg11); // 21 11
- case 417: stack.push(arg10); // 21 10
- case 419: stack.push(stack.pop() + stack.pop()); // 96
- case 420: arg11 = stack.pop() // 54 11
- case 422: gt = 156; continue; // 167 254 246
- case 425: stack.push(new java_lang_String); // 187 0 200
- case 428: stack.push(stack[stack.length - 1]); // 89
- case 429: stack.push(0); // 3
- case 430: stack.push(arg0); // 42
- case 431: stack.push(stack.pop().count); // 180 1 97
- case 434: stack.push(arg4); // 21 4
- case 436: stack.push(stack.pop() + stack.pop()); // 96
- case 437: stack.push(arg3); // 45
- case 438: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 441: return stack.pop(); // 176
- }
-}
-function java_lang_String_toUpperCaseLjava_lang_String(arg0) {
- var arg1;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179
- case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toUpperCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 159
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_trimLjava_lang_String(arg0) {
- var arg1;
- var arg2;
- var arg3;
- var arg4;
- var arg5;
-;
- var stack = new Array(3);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: arg1 = stack.pop(); // 60
- case 5: stack.push(0); // 3
- case 6: arg2 = stack.pop(); // 61
- case 7: stack.push(arg0); // 42
- case 8: stack.push(stack.pop().offset); // 180 1 99
- case 11: arg3 = stack.pop(); // 62
- case 12: stack.push(arg0); // 42
- case 13: stack.push(stack.pop().value); // 180 1 100
- case 16: arg4 = stack.pop() // 58 4
- case 18: stack.push(arg2); // 28
- case 19: stack.push(arg1); // 27
- case 20: if (stack.pop() <= stack.pop()) { gt = 40; continue; } // 162 0 20
- case 23: stack.push(arg4); // 25 4
- case 25: stack.push(arg3); // 29
- case 26: stack.push(arg2); // 28
- case 27: stack.push(stack.pop() + stack.pop()); // 96
- case 28: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 29: stack.push(32); // 16 32
- case 31: if (stack.pop() < stack.pop()) { gt = 40; continue; } // 163 0 9
- case 34: arg2++; // 132 2 1
- case 37: gt = 18; continue; // 167 255 237
- case 40: stack.push(arg2); // 28
- case 41: stack.push(arg1); // 27
- case 42: if (stack.pop() <= stack.pop()) { gt = 64; continue; } // 162 0 22
- case 45: stack.push(arg4); // 25 4
- case 47: stack.push(arg3); // 29
- case 48: stack.push(arg1); // 27
- case 49: stack.push(stack.pop() + stack.pop()); // 96
- case 50: stack.push(1); // 4
- case 51: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100
- case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
- case 53: stack.push(32); // 16 32
- case 55: if (stack.pop() < stack.pop()) { gt = 64; continue; } // 163 0 9
- case 58: arg1 += 255; // 132 1 255
- case 61: gt = 40; continue; // 167 255 235
- case 64: stack.push(arg2); // 28
- case 65: if (stack.pop() > 0) { gt = 76; continue; } // 157 0 11
- case 68: stack.push(arg1); // 27
- case 69: stack.push(arg0); // 42
- case 70: stack.push(stack.pop().count); // 180 1 97
- case 73: if (stack.pop() <= stack.pop()) { gt = 85; continue; } // 162 0 12
- case 76: stack.push(arg0); // 42
- case 77: stack.push(arg2); // 28
- case 78: stack.push(arg1); // 27
- case 79: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147
- case 82: gt = 86; continue; // 167 0 4
- case 85: stack.push(arg0); // 42
- case 86: return stack.pop(); // 176
- }
-}
-*/
-function java_lang_String_toStringLjava_lang_String(arg0) {
- return arg0.toString();
-}
-/*
-function java_lang_String_toCharArrayAC(arg0) {
- var arg1;
- var arg2;
-;
- var stack = new Array(5);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(stack.pop().count); // 180 1 97
- case 4: stack.push(new Array(stack.pop())); // 188 5
- case 6: arg1 = stack.pop(); // 76
- case 7: stack.push(arg0); // 42
- case 8: stack.push(0); // 3
- case 9: stack.push(arg0); // 42
- case 10: stack.push(stack.pop().count); // 180 1 97
- case 13: stack.push(arg1); // 43
- case 14: stack.push(0); // 3
- case 15: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
- case 18: stack.push(arg1); // 43
- case 19: return stack.pop(); // 176
- }
-}
-function java_lang_String_formatLjava_lang_StringLjava_lang_StringLjava_lang_Object(arg0,arg1) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_util_Formatter); // 187 0 211
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: { java_util_Formatter_consV(stack.pop()); } // 183 1 174
- case 7: stack.push(arg0); // 42
- case 8: stack.push(arg1); // 43
- case 9: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177
- case 12: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175
- case 15: return stack.pop(); // 176
- }
-}
-function java_lang_String_formatLjava_lang_StringLjava_util_LocaleLjava_lang_StringLjava_lang_Object(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_util_Formatter); // 187 0 211
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); java_util_Formatter_consVLjava_util_Locale(stack.pop(), v0); } // 183 1 176
- case 8: stack.push(arg1); // 43
- case 9: stack.push(arg2); // 44
- case 10: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177
- case 13: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175
- case 16: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringLjava_lang_Object(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: if (stack.pop()) { gt = 9; continue; } // 199 0 8
- case 4: stack.push("null"); // 18 10
- case 6: gt = 13; continue; // 167 0 7
- case 9: stack.push(arg0); // 42
- case 10: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
- case 13: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringAC(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: { var v0 = stack.pop(); java_lang_String_consVAC(stack.pop(), v0); } // 183 1 142
- case 8: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringACII(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 27
- case 6: stack.push(arg2); // 28
- case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143
- case 10: return stack.pop(); // 176
- }
-}
-function java_lang_String_copyValueOfLjava_lang_StringACII(arg0,arg1,arg2) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(new java_lang_String); // 187 0 200
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(arg0); // 42
- case 5: stack.push(arg1); // 27
- case 6: stack.push(arg2); // 28
- case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143
- case 10: return stack.pop(); // 176
- }
-}
-function java_lang_String_copyValueOfLjava_lang_StringAC(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(0); // 3
- case 2: stack.push(arg0); // 42
- case 3: stack.push(stack.pop().length); // 190
- case 4: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_copyValueOfALjava_lang_StringACAIAI(v0, v1, v2)); } // 184 1 155
- case 7: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringZ(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 26
- case 1: if (stack.pop() == 0) { gt = 9; continue; } // 153 0 8
- case 4: stack.push("true"); // 18 12
- case 6: gt = 11; continue; // 167 0 5
- case 9: stack.push("false"); // 18 8
- case 11: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringC(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(1); // 4
- case 1: stack.push(new Array(stack.pop())); // 188 5
- case 3: stack.push(stack[stack.length - 1]); // 89
- case 4: stack.push(0); // 3
- case 5: stack.push(arg0); // 26
- case 6: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
- case 7: arg1 = stack.pop(); // 76
- case 8: stack.push(new java_lang_String); // 187 0 200
- case 11: stack.push(stack[stack.length - 1]); // 89
- case 12: stack.push(0); // 3
- case 13: stack.push(1); // 4
- case 14: stack.push(arg1); // 43
- case 15: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
- case 18: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringI(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 26
- case 1: stack.push(10); // 16 10
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Integer_toStringLjava_lang_StringII(v0, v1)); } // 184 1 125
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringJ(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 30
- case 1: stack.push(10); // 16 10
- case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Long_toStringLjava_lang_StringJI(v0, v1)); } // 184 1 126
- case 6: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringF(arg0) {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 34
- case 1: { var v0 = stack.pop(); stack.push(java_lang_Float_toStringLjava_lang_StringF(v0)); } // 184 1 122
- case 4: return stack.pop(); // 176
- }
-}
-function java_lang_String_valueOfLjava_lang_StringD(arg0) {
- var arg1;
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 38
- case 1: { var v0 = stack.pop(); stack.push(java_lang_Double_toStringLjava_lang_StringD(v0)); } // 184 1 121
- case 4: return stack.pop(); // 176
- }
-}
-function java_lang_String_internLjava_lang_String(arg0) {
- // no code found for null
-}
-function java_lang_String_compareToILjava_lang_Object(arg0,arg1) {
- var arg2;
-;
- var stack = new Array(2);
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(arg0); // 42
- case 1: stack.push(arg1); // 43
- case 2: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200
- case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareToILjava_lang_String(self, v0)); } // 182 1 148
- case 8: return stack.pop(); // 172
- }
-}
-function java_lang_String_classV() {
- var stack = new Array();
- var gt = 0;
- for(;;) switch(gt) {
- case 0: stack.push(0); // 3
- case 1: stack.push(new Array(stack.pop())); // 189 0 183
- case 4: java_lang_String_serialPersistentFields = stack.pop(); // 179 1 101
- case 7: stack.push(new java_lang_String$CaseInsensitiveComparator); // 187 0 202
- case 10: stack.push(stack[stack.length - 1]); // 89
- case 11: // 1
- case 12: { var v0 = stack.pop(); java_lang_String$CaseInsensitiveComparator_consVLjava_lang_String$1(stack.pop(), v0); } // 183 1 160
- case 15: java_lang_String_CASE_INSENSITIVE_ORDER = stack.pop(); // 179 1 102
- case 18: return; // 177
- }
-}
-*/
-var java_lang_String_serialVersionUID = 0;
-var java_lang_String_serialPersistentFields = 0;
-var java_lang_String_CASE_INSENSITIVE_ORDER = 0;
-function java_lang_String() {
- /** the real value of this 'string' we delegate to */
- this.r = '';
-
- var self = this;
- /*
- this.value = 0;
- this.offset = 0;
- this.count = 0;
- this.hash = 0;
- */
- this.toString = function() { return self.r; };
-}
-java_lang_String.prototype = new String;
-//java_lang_String_classV();
-
-/* new method for JavaScript String */
-String.prototype.charAtCI = java_lang_String_charAtCI;
-String.prototype.lengthI = java_lang_String_lengthI;
-String.prototype.isEmptyZ = java_lang_String_isEmptyZ;
-String.prototype.getCharsVIIACAI = java_lang_String_getCharsVIIACAI;
-String.prototype.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
-String.prototype.$instOf_java_lang_String = true;
-String.prototype.$instOf_java_io_Serializable = true;
-String.prototype.$instOf_java_lang_Comparable = true;
-String.prototype.$instOf_java_lang_CharSequence = true;
-
-/*
- this.lengthI = java_lang_String_lengthI;
- this.isEmptyZ = java_lang_String_isEmptyZ;
- this.charAtCI = java_lang_String_charAtCI;
- this.codePointAtII = java_lang_String_codePointAtII;
- this.codePointBeforeII = java_lang_String_codePointBeforeII;
- this.codePointCountIII = java_lang_String_codePointCountIII;
- this.offsetByCodePointsIII = java_lang_String_offsetByCodePointsIII;
- this.getCharsVACI = java_lang_String_getCharsVACI;
- this.getCharsVIIACI = java_lang_String_getCharsVIIACI;
- this.getBytesVIIABI = java_lang_String_getBytesVIIABI;
- this.getBytesABLjava_lang_String = java_lang_String_getBytesABLjava_lang_String;
- this.getBytesABLjava_nio_charset_Charset = java_lang_String_getBytesABLjava_nio_charset_Charset;
- this.getBytesAB = java_lang_String_getBytesAB;
- this.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object;
- this.contentEqualsZLjava_lang_StringBuffer = java_lang_String_contentEqualsZLjava_lang_StringBuffer;
- this.contentEqualsZLjava_lang_CharSequence = java_lang_String_contentEqualsZLjava_lang_CharSequence;
- this.equalsIgnoreCaseZLjava_lang_String = java_lang_String_equalsIgnoreCaseZLjava_lang_String;
- this.compareToILjava_lang_String = java_lang_String_compareToILjava_lang_String;
- this.compareToIgnoreCaseILjava_lang_String = java_lang_String_compareToIgnoreCaseILjava_lang_String;
- this.regionMatchesZILjava_lang_StringII = java_lang_String_regionMatchesZILjava_lang_StringII;
- this.regionMatchesZZILjava_lang_StringII = java_lang_String_regionMatchesZZILjava_lang_StringII;
- this.startsWithZLjava_lang_StringI = java_lang_String_startsWithZLjava_lang_StringI;
- this.startsWithZLjava_lang_String = java_lang_String_startsWithZLjava_lang_String;
- this.endsWithZLjava_lang_String = java_lang_String_endsWithZLjava_lang_String;
- this.hashCodeI = java_lang_String_hashCodeI;
- this.indexOfII = java_lang_String_indexOfII;
- this.indexOfIII = java_lang_String_indexOfIII;
- this.lastIndexOfII = java_lang_String_lastIndexOfII;
- this.lastIndexOfIII = java_lang_String_lastIndexOfIII;
- this.indexOfILjava_lang_String = java_lang_String_indexOfILjava_lang_String;
- this.indexOfILjava_lang_StringI = java_lang_String_indexOfILjava_lang_StringI;
- this.lastIndexOfILjava_lang_String = java_lang_String_lastIndexOfILjava_lang_String;
- this.lastIndexOfILjava_lang_StringI = java_lang_String_lastIndexOfILjava_lang_StringI;
- this.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI;
- this.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII;
- this.subSequenceLjava_lang_CharSequenceII = java_lang_String_subSequenceLjava_lang_CharSequenceII;
- this.concatLjava_lang_StringLjava_lang_String = java_lang_String_concatLjava_lang_StringLjava_lang_String;
- this.replaceLjava_lang_StringCC = java_lang_String_replaceLjava_lang_StringCC;
- this.matchesZLjava_lang_String = java_lang_String_matchesZLjava_lang_String;
- this.containsZLjava_lang_CharSequence = java_lang_String_containsZLjava_lang_CharSequence;
- this.replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String;
- this.replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String;
- this.replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence = java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence;
- this.splitALjava_lang_StringLjava_lang_StringI = java_lang_String_splitALjava_lang_StringLjava_lang_StringI;
- this.splitALjava_lang_StringLjava_lang_String = java_lang_String_splitALjava_lang_StringLjava_lang_String;
- this.toLowerCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale;
- this.toLowerCaseLjava_lang_String = java_lang_String_toLowerCaseLjava_lang_String;
- this.toUpperCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale;
- this.toUpperCaseLjava_lang_String = java_lang_String_toUpperCaseLjava_lang_String;
- this.trimLjava_lang_String = java_lang_String_trimLjava_lang_String;
- this.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
- this.toCharArrayAC = java_lang_String_toCharArrayAC;
- this.internLjava_lang_String = java_lang_String_internLjava_lang_String;
- this.compareToILjava_lang_Object = java_lang_String_compareToILjava_lang_Object;
- */
-
-
-
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Array.java
--- a/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Thu Oct 11 06:15:22 2012 -0700
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Wed Jan 23 20:16:48 2013 +0100
@@ -1,20 +1,20 @@
-/*
-Java 4 Browser Bytecode Translator
-Copyright (C) 2012-2012 Jaroslav Tulach
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 2 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. Look for COPYING file in the top folder.
-If not, see http://opensource.org/licenses/GPL-2.0.
-*/
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
package org.apidesign.vm4brwsr;
/**
@@ -51,10 +51,24 @@
return doubles[4][0];
}
+ static double[][] dbls = new double[1][2];
+ public static double twoDoubles() {
+ return dbls[0][0] + dbls[0][0];
+ }
+
+ static int[][] tints = new int[1][2];
+ public static int twoInts() {
+ return tints[0][0] + tints[0][0];
+ }
+
private static final Array[] ARR = { new Array(), new Array(), new Array() };
- private static Array[] arr() {
- return ARR;
+ private static Array[][] arr() {
+ Array[][] matrix = new Array[3][3];
+ for (int i = 0; i < ARR.length; i++) {
+ matrix[i][i] = ARR[i];
+ }
+ return matrix;
}
private static T[] filter(T[] in) {
return in;
@@ -62,22 +76,52 @@
public static double sum() {
double sum = 0.0;
- for (int i = 0; i < arr().length; i++) {
- sum += arr()[i].bytes();
- sum += arr()[i].shorts();
- sum += arr()[i].ints()[2];
- sum += arr()[i].floats();
- sum += filter(arr())[i].doubles();
+ for (Array[] row : arr()) {
+ int indx = -1;
+ for (Array a : row) {
+ indx++;
+ if (a == null) {
+ continue;
+ }
+ sum += a.bytes();
+ sum += a.shorts();
+ sum += a.ints()[2];
+ sum += a.floats();
+ sum += filter(row)[indx].doubles();
+ }
}
return sum;
}
- public static int simple() {
- int[] arr = { 0, 1, 2, 3, 4, 5 };
+ private static final int[] arr = { 0, 1, 2, 3, 4, 5 };
+ public static int simple(boolean clone) {
+ int[] ar;
+ if (clone) {
+ ar = arr.clone();
+ } else {
+ ar = arr;
+ }
int sum = 0;
- for (int i = 0; i < arr.length; i++) {
- sum += arr[i];
+ for (int a : ar) {
+ sum += a;
}
return sum;
}
+
+ public static int sum(int size) {
+ int[] arr = new int[size];
+ return arr[0] + arr[1];
+ }
+
+ static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) {
+ while (count-- > 0) {
+ dst[dstBegin++] = value[srcBegin++];
+ }
+ }
+
+ public static char copyArray() {
+ char[] arr = { '0' };
+ arraycopy(arr()[0][0].chars, 0, arr, 0, 1);
+ return arr[0];
+ }
}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java
--- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Thu Oct 11 06:15:22 2012 -0700
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -1,63 +1,86 @@
-/*
-Java 4 Browser Bytecode Translator
-Copyright (C) 2012-2012 Jaroslav Tulach
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 2 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. Look for COPYING file in the top folder.
-If not, see http://opensource.org/licenses/GPL-2.0.
-*/
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
package org.apidesign.vm4brwsr;
import javax.script.Invocable;
-import javax.script.ScriptException;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import static org.testng.Assert.*;
/**
*
* @author Jaroslav Tulach
*/
public class ArrayTest {
- @Test public void verifySimpleIntOperation() throws Exception {
- assertExec("CheckTheSum", "org_apidesign_vm4brwsr_Array_simpleI",
- Double.valueOf(15)
+ @Test public void intArrayShouldBeFilledWithZeroes() throws Exception {
+ assertExec("0 + 0", Array.class, "sum__II",
+ Double.valueOf(0), 2
);
}
+ @Test public void verifySimpleIntOperation() throws Exception {
+ assertExec("CheckTheSum", Array.class, "simple__IZ",
+ Double.valueOf(15), false
+ );
+ }
+
+ @Test public void cloneOnArray() throws Exception {
+ assertExec("CheckTheSum on clone", Array.class, "simple__IZ",
+ Double.valueOf(15), true
+ );
+ }
+
+ @Test public void realOperationOnArrays() throws Exception {
+ assertEquals(Array.sum(), 105.0, "Computes to 105");
+ }
+
@Test public void verifyOperationsOnArrays() throws Exception {
- assertExec("The sum is 105", "org_apidesign_vm4brwsr_Array_sumD",
+ assertExec("The sum is 105", Array.class, "sum__D",
Double.valueOf(105)
);
}
+
+ @Test public void twoDoubles() throws Exception {
+ assertExec("Elements are initialized", Array.class, "twoDoubles__D",
+ Double.valueOf(0)
+ );
+ }
+ @Test public void twoInts() throws Exception {
+ assertExec("Elements are initialized", Array.class, "twoInts__I",
+ Double.valueOf(0)
+ );
+ }
- private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
+ @Test public void doesCopyArrayWork() throws Exception {
+ assertExec("Returns 'a'", Array.class, "copyArray__C", Double.valueOf('a'));
+ }
+
+ private static CharSequence codeSeq;
+ private static Invocable code;
+
+ @BeforeClass
+ public void compileTheCode() throws Exception {
StringBuilder sb = new StringBuilder();
- Invocable i = StaticMethodTest.compileClass(sb,
+ code = StaticMethodTest.compileClass(sb,
"org/apidesign/vm4brwsr/Array"
);
-
- Object ret = null;
- try {
- ret = i.invokeFunction(methodName, args);
- } catch (ScriptException ex) {
- fail("Execution failed in " + sb, ex);
- } catch (NoSuchMethodException ex) {
- fail("Cannot find method in " + sb, ex);
- }
- if (ret == null && expRes == null) {
- return;
- }
- if (expRes.equals(ret)) {
- return;
- }
- assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb);
+ codeSeq = sb;
+ }
+ private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
+ StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
}
}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,55 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class ByteCodeToJavaScriptTest {
+
+ public ByteCodeToJavaScriptTest() {
+ }
+
+ @Test
+ public void findMethodNameManglesObjectsCorrectly() {
+ StringBuilder cnt = new StringBuilder();
+ char[] returnType = { 'V' };
+ String ret = ByteCodeToJavaScript.findMethodName(new String[] {
+ "StringTest", "replace", "(Ljava/lang/String;CC)Ljava/lang/String;"
+ }, cnt, returnType);
+ assertEquals(cnt.toString(), "000", "No doubles or longs");
+ assertTrue(returnType[0] != 'V', "Returns string");
+ assertEquals(ret, "replace__Ljava_lang_String_2Ljava_lang_String_2CC");
+ }
+
+ @Test
+ public void manglingArrays() {
+ StringBuilder cnt = new StringBuilder();
+ char[] returnType = { 'V' };
+ String ret = ByteCodeToJavaScript.findMethodName(new String[] {
+ "VMinVM", "toJavaScript", "([B)Ljava/lang/String;"
+ }, cnt, returnType);
+ assertEquals(cnt.toString(), "0", "No doubles or longs");
+ assertTrue(returnType[0] != 'V', "Returns string");
+ assertEquals(ret, "toJavaScript__Ljava_lang_String_2_3B");
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,76 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class BytesLoader {
+ private static Set requested = new TreeSet();
+
+ public byte[] get(String name) throws IOException {
+ if (!requested.add(name)) {
+ throw new IllegalStateException("Requested for second time: " + name);
+ }
+ byte[] arr = readClass(name);
+ /*
+ System.err.print("loader['" + name + "'] = [");
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) {
+ System.err.print(", ");
+ }
+ System.err.print(arr[i]);
+ }
+ System.err.println("]");
+ */
+ return arr;
+ }
+
+ static byte[] readClass(String name) throws IOException {
+ URL u = null;
+ Enumeration en = BytesLoader.class.getClassLoader().getResources(name);
+ while (en.hasMoreElements()) {
+ u = en.nextElement();
+ }
+ if (u == null) {
+ throw new IOException("Can't find " + name);
+ }
+ try (InputStream is = u.openStream()) {
+ byte[] arr;
+ arr = new byte[is.available()];
+ int offset = 0;
+ while (offset < arr.length) {
+ int len = is.read(arr, offset, arr.length - offset);
+ if (len == -1) {
+ throw new IOException("Can't read " + name);
+ }
+ offset += len;
+ }
+ return arr;
+ }
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,185 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import javax.script.Invocable;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeClass;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class ClassTest {
+
+ @Test public void superClassEqualsGetSuperclass() {
+ assertTrue(Classes.equalsClassesOfExceptions(), "Classes are equal");
+ }
+
+ @Test public void jsSuperClassEqualsGetSuperclass() throws Exception {
+ assertExec("Classes are equal", Classes.class, "equalsClassesOfExceptions__Z", Double.valueOf(1.0));
+ }
+
+ @Test public void classesAreDifferent() {
+ assertTrue(Classes.differenceInClasses(), "Classes are not equal");
+ }
+
+ @Test public void jsClassesAreDifferent() throws Exception {
+ assertExec("Classes are not equal", Classes.class, "differenceInClasses__Z", Double.valueOf(1.0));
+ }
+
+ @Test public void javaInstanceName() throws Exception {
+ assertEquals(Classes.classForInstance(), "java.io.IOException");
+ }
+ @Test public void jsInstanceName() throws Exception {
+ assertExec("I/O name", Classes.class, "classForInstance__Ljava_lang_String_2", "java.io.IOException");
+ }
+ @Test public void javaName() throws Exception {
+ assertEquals(Classes.name(), "java.io.IOException");
+ }
+ @Test public void jsName() throws Exception {
+ assertExec("I/O name", Classes.class, "name__Ljava_lang_String_2", "java.io.IOException");
+ }
+ @Test public void javaSimpleName() throws Exception {
+ assertEquals(Classes.simpleName(), "IOException");
+ }
+ @Test public void jsGetsSimpleName() throws Exception {
+ assertExec("I/O simple name", Classes.class, "simpleName__Ljava_lang_String_2", "IOException");
+ }
+ @Test public void javaCanonicalName() {
+ assertEquals(Classes.canonicalName(), "java.io.IOException");
+ }
+ @Test public void jsCanonicalName() throws Exception {
+ assertExec("I/O simple name", Classes.class, "canonicalName__Ljava_lang_String_2", "java.io.IOException");
+ }
+ @Test public void javaNewInstance() throws Exception {
+ assertTrue(Classes.newInstance());
+ }
+ @Test public void jsNewInstance() throws Exception {
+ assertExec("Check new instance", Classes.class, "newInstance__Z", Double.valueOf(1));
+ }
+ @Test public void javaNoNewInstance() throws Exception {
+ assertEquals("java.lang.InstantiationException:java.lang.Float",
+ Classes.newInstanceNoPubConstructor()
+ );
+ }
+ @Test public void jsNoNewInstance() throws Exception {
+ assertExec("Check problems with new instance", Classes.class, "newInstanceNoPubConstructor__Ljava_lang_String_2",
+ "java.lang.InstantiationException:java.lang.Float"
+ );
+ }
+ @Test public void jsAnnotation() throws Exception {
+ assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
+ }
+ @Test public void jsStringAnnotation() throws Exception {
+ assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
+ }
+ @Test public void jsStringAnnotationFromArray() throws Exception {
+ assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false);
+ }
+ @Test public void javaInvokeMethod() throws Exception {
+ assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection");
+ }
+ @Test public void jsInvokeMethod() throws Exception {
+ assertExec("Calls the name() method via reflection", Classes.class,
+ "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2",
+ "java.io.IOException", true, "name"
+ );
+ }
+ @Test public void jsInvokeParamMethod() throws Exception {
+ assertExec("sums two numbers via reflection", Classes.class,
+ "reflectiveSum__III", Double.valueOf(5), 2, 3
+ );
+ }
+ @Test public void javaFindMethod() throws Exception {
+ assertEquals(Classes.reflectiveMethodCall(false, "name"), "java.io.IOException", "Calls the name() method via reflection");
+ }
+ @Test public void jsFindMethod() throws Exception {
+ assertExec("Calls the name() method via reflection", Classes.class,
+ "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2",
+ "java.io.IOException", false, "name"
+ );
+ }
+ @Test public void primitiveReturnType() throws Exception {
+ assertExec("Tries to get an integer via reflection", Classes.class,
+ "primitiveType__Ljava_lang_String_2Ljava_lang_String_2",
+ Classes.primitiveType("primitive"), "primitive"
+ );
+ }
+ @Test public void primitiveBoolReturnType() throws Exception {
+ assertExec("Tries to get an integer via reflection", Classes.class,
+ "primitiveType__Ljava_lang_String_2Ljava_lang_String_2",
+ Classes.primitiveType("primitiveB"), "primitiveB"
+ );
+ }
+ @Test public void javaAnnotatedMethod() throws Exception {
+ assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection");
+ }
+ @Test public void jsAnnotatedMethod() throws Exception {
+ assertExec("Calls the name() method via reflection", Classes.class,
+ "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2",
+ "java.io.IOException", false, null
+ );
+ }
+ @Test public void jsClassParam() throws Exception {
+ assertExec("Calls the nameOfIO()", Classes.class,
+ "nameOfIO__Ljava_lang_String_2",
+ "java.io.IOException"
+ );
+ }
+ @Test public void noInterface() throws Exception {
+ assertExec("Calls Class.isInterface", Classes.class,
+ "isInterface__ZLjava_lang_String_2",
+ 0.0, "java.lang.String"
+ );
+ }
+ /*
+ @Test public void isInterface() throws Exception {
+ assertExec("Calls Class.isInterface", Classes.class,
+ "isInterface__ZLjava_lang_String_2",
+ 1.0, "java.lang.Runnable"
+ );
+ }
+ */
+ @Test public void integerType() throws Exception {
+ assertExec("Computes the type", Classes.class,
+ "intType__Ljava_lang_String_2",
+ Classes.intType()
+ );
+ }
+
+ private static CharSequence codeSeq;
+ private static Invocable code;
+
+ @BeforeClass
+ public void compileTheCode() throws Exception {
+ if (codeSeq == null) {
+ StringBuilder sb = new StringBuilder();
+ code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes");
+ codeSeq = sb;
+ }
+ }
+
+ private void assertExec(
+ String msg, Class clazz, String method, Object expRes, Object... args
+ ) throws Exception {
+ StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
+ }
+
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Classes.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,154 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@ClassesMarker(number = 10)
+@ClassesNamer(name = "my text")
+public class Classes {
+ public static String nameOfIO() {
+ return nameFor(IOException.class);
+ }
+
+ private static String nameFor(Class> c) {
+ return c.getName();
+ }
+
+ public static boolean isInterface(String s) throws ClassNotFoundException {
+ return Class.forName(s).isInterface();
+ }
+
+ public static boolean equalsClassesOfExceptions() {
+ return MalformedURLException.class.getSuperclass() == IOException.class;
+ }
+ public static boolean differenceInClasses() {
+ Class> c1 = MalformedURLException.class;
+ Class> c2 = IOException.class;
+ return c1 != c2;
+ }
+
+ public static String classForInstance() {
+ return new IOException().getClass().getName().toString();
+ }
+
+ @ClassesMarker(number = 1)
+ public static String name() {
+ return IOException.class.getName().toString();
+ }
+ public static String simpleName() {
+ return IOException.class.getSimpleName();
+ }
+ public static String canonicalName() {
+ return IOException.class.getCanonicalName();
+ }
+ public static boolean newInstance() throws Exception {
+ IOException ioe = IOException.class.newInstance();
+ if (ioe instanceof IOException) {
+ return ioe.getClass() == IOException.class;
+ }
+ throw new IllegalStateException("Not a subtype: " + ioe);
+ }
+ public static String newInstanceNoPubConstructor() throws Exception {
+ try {
+ Float f = Float.class.newInstance();
+ return "wrong, can't instantiate: " + f;
+ } catch (Exception ex) {
+ return (ex.getClass().getName() + ":" + ex.getMessage()).toString().toString();
+ }
+ }
+ public static int getMarker() {
+ if (!Classes.class.isAnnotationPresent(ClassesMarker.class)) {
+ return -2;
+ }
+ ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
+ return cm == null ? -1 : cm.number();
+ }
+ public static String getNamer(boolean direct) {
+ if (direct) {
+ ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
+ return cm == null ? null : cm.name();
+ }
+ for (Annotation a : Classes.class.getAnnotations()) {
+ if (a instanceof ClassesNamer) {
+ return ((ClassesNamer)a).name();
+ }
+ }
+ return null;
+ }
+
+ public static String intType() {
+ return Integer.TYPE.getName();
+ }
+
+ public static int primitive() {
+ return 1;
+ }
+ public static boolean primitiveB() {
+ return true;
+ }
+
+ public static String primitiveType(String method) throws Exception {
+ return reflectiveMethodCall(false, method).getClass().getName();
+ }
+
+ @JavaScriptBody(args = "msg", body = "throw msg;")
+ private static native void thrw(String msg);
+
+ public static Object reflectiveMethodCall(boolean direct, String mn) throws Exception {
+ Method find = null;
+ StringBuilder sb = new StringBuilder();
+ if (!direct) {
+ final Class extends Annotation> v = ClassesMarker.class;
+ for (Method m : Classes.class.getMethods()) {
+ sb.append("\n").append(m.getName());
+ if (mn != null) {
+ if (m.getName().equals(mn)) {
+ find = m;
+ break;
+ }
+ } else {
+ if (m.getAnnotation(v) != null) {
+ find = m;
+ break;
+ }
+ }
+ }
+ } else {
+ find = Classes.class.getMethod(mn);
+ }
+ if (find == null) {
+ thrw(sb.toString());
+ throw new NullPointerException(sb.toString());
+ }
+ return find.invoke(null);
+ }
+
+ public static int reflectiveSum(int a, int b) throws Exception {
+ Method m = StaticMethod.class.getMethod("sum", int.class, int.class);
+ return (int) m.invoke(null, a, b);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,30 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ClassesMarker {
+ int number();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,30 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ClassesNamer {
+ String name();
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,88 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import org.apidesign.bck2brwsr.core.JavaScriptBody;
+
+/**
+ *
+ * @author tom
+ */
+public class Exceptions {
+ private Exceptions() {
+ }
+
+ public static int methodWithTryCatchNoThrow() {
+ int res = 0;
+ try {
+ res = 1;
+ } catch (IllegalArgumentException e) {
+ res = 2;
+ }
+ //join point
+ return res;
+ }
+
+ public static int methodWithTryCatchThrow() {
+ int res = 0;
+ try {
+ res = 1;
+ throw new IllegalArgumentException();
+ } catch (IllegalArgumentException e) {
+ res = 2;
+ }
+ //join point
+ return res;
+ }
+
+ @JavaScriptBody(args = "msg", body = "throw msg;")
+ public static void thrw(String msg) {}
+
+ public static String catchThrowableCatchesAll() {
+ try {
+ thrw("Hello!");
+ return "Not here!";
+ } catch (Throwable ex) {
+ return ex.getMessage();
+ }
+ }
+
+ public static String newInstance(String n) {
+ try {
+ Class c;
+ try {
+ c = Class.forName(n);
+ } catch (ClassNotFoundException ex) {
+ return ("CNFE:" + ex.getMessage()).toString();
+ }
+ return c.newInstance().getClass().getName();
+ } catch (InstantiationException | IllegalAccessException ex) {
+ return ex.getMessage();
+ }
+ }
+
+ private static int counter;
+ public static int readCounter(String n) throws ClassNotFoundException {
+ try {
+ Class.forName(n);
+ } finally {
+ counter++;
+ }
+ return counter;
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Wed Jan 23 20:16:48 2013 +0100
@@ -0,0 +1,121 @@
+/**
+ * Back 2 Browser Bytecode Translator
+ * Copyright (C) 2012 Jaroslav Tulach
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. Look for COPYING file in the top folder.
+ * If not, see http://opensource.org/licenses/GPL-2.0.
+ */
+package org.apidesign.vm4brwsr;
+
+import javax.script.Invocable;
+import javax.script.ScriptException;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+public class ExceptionsTest {
+ @Test
+ public void verifyMethodWithTryCatchNoThrow() throws Exception {
+ assertExec(
+ "No throw",
+ Exceptions.class,
+ "methodWithTryCatchNoThrow__I",
+ new Double(1.0));
+ }
+
+ @Test
+ public void catchJavaScriptStringAsThrowable() throws Exception {
+ assertExec(
+ "Throw hello!",
+ Exceptions.class,
+ "catchThrowableCatchesAll__Ljava_lang_String_2",
+ "Hello!"
+ );
+ }
+
+ @Test
+ public void verifyMethodWithTryCatchThrow() throws Exception {
+ assertExec(
+ "Throw",
+ Exceptions.class,
+ "methodWithTryCatchThrow__I",
+ new Double(2.0));
+ }
+
+ @Test public void createObject() throws Exception {
+ assertExec("Object created", Exceptions.class,
+ "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
+ "java.lang.Object",
+ "java.lang.Object"
+ );
+ }
+
+ @Test public void createFloatFails() throws Exception {
+ assertExec("Float not created", Exceptions.class,
+ "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
+ "java.lang.Float",
+ "java.lang.Float"
+ );
+ }
+
+ @Test public void createUnknownFails() throws Exception {
+ assertExec("Object created", Exceptions.class,
+ "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
+ "CNFE:org.apidesign.Unknown",
+ "org.apidesign.Unknown"
+ );
+ }
+
+ @Test public void testThreeCalls() throws Exception {
+ Object vm = code.invokeFunction("bck2brwsr");
+ Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName());
+
+ String method = "readCounter__ILjava_lang_String_2";
+
+ try {
+ Object ret = code.invokeMethod(clazz, method, "org.apidesign.Unknown");
+ fail("We expect an CNFE!");
+ } catch (ScriptException scriptException) {
+ // script exception should be OK
+ }
+ {
+ // 2nd invocation
+ Object ret = code.invokeMethod(clazz, method, "java.lang.String");
+ assertEquals(ret, Double.valueOf(2));
+ }
+ {
+ // 3rd invocation
+ Object ret = code.invokeMethod(clazz, method, "java.lang.Integer");
+ assertEquals(ret, Double.valueOf(3));
+ }
+ }
+
+ private static CharSequence codeSeq;
+ private static Invocable code;
+
+ @BeforeClass
+ public void compileTheCode() throws Exception {
+ StringBuilder sb = new StringBuilder();
+ code = StaticMethodTest.compileClass(sb,
+ "org/apidesign/vm4brwsr/Exceptions"
+ );
+ codeSeq = sb;
+ }
+ private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
+ StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
+ }
+}
diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java
--- a/vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java Thu Oct 11 06:15:22 2012 -0700
+++ b/vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java Wed Jan 23 20:16:48 2013 +0100
@@ -1,6 +1,6 @@
/**
- * Java 4 Browser Bytecode Translator
- * Copyright (C) 2012-2012 Jaroslav Tulach