+
+ public static class Global extends JS.Immutable {
+ private final static JS NaN = JSU.N(Double.NaN);
+ private final static JS POSITIVE_INFINITY = JSU.N(Double.POSITIVE_INFINITY);
+ private final static JS.Method METHOD = new JS.Method();
+
+ public Global() { }
+ public JS get(JS key) throws JSExn {
+ //#jsswitch(key)
+ case "NaN": return NaN;
+ case "Infinity": return POSITIVE_INFINITY;
+ case "undefined": return null;
+ case "stringFromCharCode": return METHOD;
+ case "parseInt": return METHOD;
+ case "isNaN": return METHOD;
+ case "isFinite": return METHOD;
+ case "decodeURI": return METHOD;
+ case "decodeURIComponent": return METHOD;
+ case "encodeURI": return METHOD;
+ case "encodeURIComponent": return METHOD;
+ case "escape": return METHOD;
+ case "unescape": return METHOD;
+ case "parseInt": return METHOD;
+ //#end
+ return super.get(key);
+ }
+
+ public JS call(JS method, JS[] args) throws JSExn {
+ switch(args.length) {
+ case 0: {
+ //#jsswitch(method)
+ case "stringFromCharCode":
+ char buf[] = new char[args.length];
+ for(int i=0; i<args.length; i++) buf[i] = (char)(JSU.toInt(args[i]) & 0xffff);
+ return JSU.S(new String(buf));
+ //#end
+ break;
+ }
+ case 1: {
+ //#jsswitch(method)
+ case "parseInt": return parseInt(args[0], JSU.N(0));
+ case "isNaN": { double d = JSU.toDouble(args[0]); return d == d ? JSU.F : JSU.T; }
+ case "isFinite": { double d = JSU.toDouble(args[0]); return (d==d && !Double.isInfinite(d)) ? JSU.T : JSU.F; }
+ case "decodeURI": throw new JSExn("unimplemented");
+ case "decodeURIComponent": throw new JSExn("unimplemented");
+ case "encodeURI": throw new JSExn("unimplemented");
+ case "encodeURIComponent": throw new JSExn("unimplemented");
+ case "escape": throw new JSExn("unimplemented");
+ case "unescape": throw new JSExn("unimplemented");
+ //#end
+ break;
+ }
+ case 2: {
+ //#jsswitch(method)
+ case "parseInt": return parseInt(args[0], args[1]);
+ //#end
+ break;
+ }
+ }
+ return super.call(method, args);
+ }
+
+ private JS parseInt(JS arg, JS r) throws JSExn {
+ int radix = JSU.toInt(r);
+ String s = JSU.toString(arg);
+ int start = 0;
+ int length = s.length();
+ int sign = 1;
+ long n = 0;
+ if (radix != 0 && (radix < 2 || radix > 36)) return NaN;
+ while (start < length && Character.isWhitespace(s.charAt(start))) start++;
+ if ((length >= start+1) && (s.charAt(start) == '+' || s.charAt(start) == '-')) {
+ sign = s.charAt(start) == '+' ? 1 : -1;
+ start++;
+ }
+ if(radix == 0 && length >= start+1 && s.charAt(start) == '0') {
+ start++;
+ if(length >= start+1 && (s.charAt(start) == 'x' || s.charAt(start) == 'X')) {
+ start++;
+ radix = 16;
+ } else {
+ radix = 8;
+ if(length == start || Character.digit(s.charAt(start+1),8)==-1) return JSU.ZERO;
+ }
+ }
+ if(radix == 0) radix = 10;
+ if(length == start || Character.digit(s.charAt(start),radix) == -1) return NaN;
+ // try the fast way first
+ try {
+ String s2 = start == 0 ? s : s.substring(start);
+ return JSU.N(sign*Integer.parseInt(s2,radix));
+ } catch(NumberFormatException e) { }
+ // fall through to a slower but emca-compliant method
+ for(int i=start;i<length;i++) {
+ int digit = Character.digit(s.charAt(i),radix);
+ if(digit < 0) break;
+ n = n*radix + digit;
+ if(n < 0) return NaN; // overflow;
+ }
+ if(n <= Integer.MAX_VALUE) return JSU.N(sign*(int)n);
+ return JSU.N((long)sign*n);
+ }
+
+ private JS parseFloat(JS arg) throws JSExn {
+ String s = JSU.toString(arg);
+ int start = 0;
+ int length = s.length();
+ while(start < length && Character.isWhitespace(s.charAt(0))) start++;
+ int end = length;
+ // as long as the string has no trailing garbage,this is fast, its slow with
+ // trailing garbage
+ while(start < end) {
+ try {
+ return JSU.N(Float.parseFloat(s.substring(start,length)));
+ } catch(NumberFormatException e) { }
+ end--;
+ }
+ return NaN;
+ }
+ }