1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime; 27 28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 30 31 import java.util.Locale; 32 import jdk.internal.dynalink.beans.StaticClass; 33 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 34 import jdk.nashorn.internal.parser.Lexer; 35 36 /** 37 * Representation for ECMAScript types - this maps directly to the ECMA script standard 38 */ 39 public enum JSType { 40 /** The undefined type */ 41 UNDEFINED, 42 43 /** The null type */ 44 NULL, 45 46 /** The boolean type */ 47 BOOLEAN, 48 49 /** The number type */ 50 NUMBER, 51 52 /** The string type */ 53 STRING, 54 55 /** The object type */ 56 OBJECT, 57 58 /** The function type */ 59 FUNCTION; 60 61 /** Max value for an uint32 in JavaScript */ 62 public static final long MAX_UINT = 0xFFFF_FFFFL; 63 64 /** JavaScript compliant conversion function from Object to boolean */ 65 public static final Call TO_BOOLEAN = staticCall(JSType.class, "toBoolean", boolean.class, Object.class); 66 67 /** JavaScript compliant conversion function from number to boolean */ 68 public static final Call TO_BOOLEAN_D = staticCall(JSType.class, "toBoolean", boolean.class, double.class); 69 70 /** JavaScript compliant conversion function from Object to integer */ 71 public static final Call TO_INTEGER = staticCall(JSType.class, "toInteger", int.class, Object.class); 72 73 /** JavaScript compliant conversion function from Object to long */ 74 public static final Call TO_LONG = staticCall(JSType.class, "toLong", long.class, Object.class); 75 76 /** JavaScript compliant conversion function from Object to number */ 77 public static final Call TO_NUMBER = staticCall(JSType.class, "toNumber", double.class, Object.class); 78 79 /** JavaScript compliant conversion function from Object to int32 */ 80 public static final Call TO_INT32 = staticCall(JSType.class, "toInt32", int.class, Object.class); 81 82 /** JavaScript compliant conversion function from double to int32 */ 83 public static final Call TO_INT32_D = staticCall(JSType.class, "toInt32", int.class, double.class); 84 85 /** JavaScript compliant conversion function from Object to uint32 */ 86 public static final Call TO_UINT32 = staticCall(JSType.class, "toUint32", long.class, Object.class); 87 88 /** JavaScript compliant conversion function from number to uint32 */ 89 public static final Call TO_UINT32_D = staticCall(JSType.class, "toUint32", long.class, double.class); 90 91 /** JavaScript compliant conversion function from Object to int64 */ 92 public static final Call TO_INT64 = staticCall(JSType.class, "toInt64", long.class, Object.class); 93 94 /** JavaScript compliant conversion function from number to int64 */ 95 public static final Call TO_INT64_D = staticCall(JSType.class, "toInt64", long.class, double.class); 96 97 /** JavaScript compliant conversion function from Object to String */ 98 public static final Call TO_STRING = staticCall(JSType.class, "toString", String.class, Object.class); 99 100 /** JavaScript compliant conversion function from number to String */ 101 public static final Call TO_STRING_D = staticCall(JSType.class, "toString", String.class, double.class); 102 103 /** JavaScript compliant conversion function from Object to primitive */ 104 public static final Call TO_PRIMITIVE = staticCall(JSType.class, "toPrimitive", Object.class, Object.class); 105 106 private static final double INT32_LIMIT = 4294967296.0; 107 108 /** 109 * The external type name as returned by ECMAScript "typeof" operator 110 * 111 * @return type name for this type 112 */ 113 public final String typeName() { 114 // For NULL, "object" has to be returned! 115 return ((this == NULL) ? OBJECT : this).name().toLowerCase(Locale.ENGLISH); 116 } 117 118 /** 119 * Return the JSType for a given object 120 * 121 * @param obj an object 122 * 123 * @return the JSType for the object 124 */ 125 public static JSType of(final Object obj) { 126 if (obj == ScriptRuntime.UNDEFINED) { 127 return JSType.UNDEFINED; 128 } 129 130 if (obj == null) { 131 return JSType.NULL; 132 } 133 134 if (obj instanceof Boolean) { 135 return JSType.BOOLEAN; 136 } 137 138 if (obj instanceof Number) { 139 return JSType.NUMBER; 140 } 141 142 if (obj instanceof String || obj instanceof ConsString) { 143 return JSType.STRING; 144 } 145 146 if (obj instanceof ScriptObject) { 147 return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT; 148 } 149 150 if (obj instanceof StaticClass) { 151 return JSType.FUNCTION; 152 } 153 154 return JSType.OBJECT; 155 } 156 157 /** 158 * Returns true if double number can be represented as an int 159 * 160 * @param number a long to inspect 161 * 162 * @return true for int representable longs 163 */ 164 public static boolean isRepresentableAsInt(final long number) { 165 return (int)number == number; 166 } 167 168 /** 169 * Returns true if double number can be represented as an int 170 * 171 * @param number a double to inspect 172 * 173 * @return true for int representable doubles 174 */ 175 public static boolean isRepresentableAsInt(final double number) { 176 return (int)number == number; 177 } 178 179 /** 180 * Returns true if double number can be represented as a long 181 * 182 * @param number a double to inspect 183 * @return true for long representable doubles 184 */ 185 public static boolean isRepresentableAsLong(final double number) { 186 return (long)number == number; 187 } 188 189 /** 190 * Get the smallest integer representation of a number. Returns an Integer 191 * for something that is int representable, and Long for something that 192 * is long representable. If the number needs to be a double, this is an 193 * identity function 194 * 195 * @param number number to check 196 * 197 * @return Number instanceof the narrowest possible integer representation for number 198 */ 199 public static Number narrowestIntegerRepresentation(final double number) { 200 if (isRepresentableAsInt(number)) { 201 return (int)number; 202 } else if (isRepresentableAsLong(number)) { 203 return (long)number; 204 } else { 205 return number; 206 } 207 } 208 209 /** 210 * Check whether an object is primitive 211 * 212 * @param obj an object 213 * 214 * @return true if object is primitive (includes null and undefined) 215 */ 216 public static boolean isPrimitive(final Object obj) { 217 return obj == null || 218 obj == ScriptRuntime.UNDEFINED || 219 obj instanceof Boolean || 220 obj instanceof Number || 221 obj instanceof String || 222 obj instanceof ConsString; 223 } 224 225 /** 226 * Primitive converter for an object 227 * 228 * @param obj an object 229 * 230 * @return primitive form of the object 231 */ 232 public static Object toPrimitive(final Object obj) { 233 return toPrimitive(obj, null); 234 } 235 236 /** 237 * Primitive converter for an object including type hint 238 * See ECMA 9.1 ToPrimitive 239 * 240 * @param obj an object 241 * @param hint a type hint 242 * 243 * @return the primitive form of the object 244 */ 245 public static Object toPrimitive(final Object obj, final Class<?> hint) { 246 if (!(obj instanceof ScriptObject)) { 247 return obj; 248 } 249 250 final ScriptObject sobj = (ScriptObject)obj; 251 final Object result = sobj.getDefaultValue(hint); 252 253 if (!isPrimitive(result)) { 254 throw typeError("bad.default.value", result.toString()); 255 } 256 257 return result; 258 } 259 260 /** 261 * JavaScript compliant conversion of number to boolean 262 * 263 * @param num a number 264 * 265 * @return a boolean 266 */ 267 public static boolean toBoolean(final double num) { 268 return num != 0 && !Double.isNaN(num); 269 } 270 271 /** 272 * JavaScript compliant conversion of Object to boolean 273 * See ECMA 9.2 ToBoolean 274 * 275 * @param obj an object 276 * 277 * @return a boolean 278 */ 279 public static boolean toBoolean(final Object obj) { 280 if (obj instanceof Boolean) { 281 return (Boolean)obj; 282 } 283 284 if (nullOrUndefined(obj)) { 285 return false; 286 } 287 288 if (obj instanceof Number) { 289 final double num = ((Number)obj).doubleValue(); 290 return num != 0 && !Double.isNaN(num); 291 } 292 293 if (obj instanceof String || obj instanceof ConsString) { 294 return ((CharSequence)obj).length() > 0; 295 } 296 297 return true; 298 } 299 300 301 /** 302 * JavaScript compliant converter of Object to String 303 * See ECMA 9.8 ToString 304 * 305 * @param obj an object 306 * 307 * @return a string 308 */ 309 public static String toString(final Object obj) { 310 return toStringImpl(obj, false); 311 } 312 313 /** 314 * If obj is an instance of {@link ConsString} cast to CharSequence, else return 315 * result of {@link #toString(Object)}. 316 * 317 * @param obj an object 318 * @return an instance of String or ConsString 319 */ 320 public static CharSequence toCharSequence(final Object obj) { 321 if (obj instanceof ConsString) { 322 return (CharSequence) obj; 323 } 324 return toString(obj); 325 } 326 327 /** 328 * Check whether a string is representable as a JavaScript number 329 * 330 * @param str a string 331 * 332 * @return true if string can be represented as a number 333 */ 334 public static boolean isNumber(final String str) { 335 try { 336 Double.parseDouble(str); 337 return true; 338 } catch (final NumberFormatException e) { 339 return false; 340 } 341 } 342 343 /** 344 * JavaScript compliant conversion of integer to String 345 * 346 * @param num an integer 347 * 348 * @return a string 349 */ 350 public static String toString(final int num) { 351 return Integer.toString(num); 352 } 353 354 /** 355 * JavaScript compliant conversion of number to String 356 * See ECMA 9.8.1 357 * 358 * @param num a number 359 * 360 * @return a string 361 */ 362 public static String toString(final double num) { 363 if (isRepresentableAsInt(num)) { 364 return Integer.toString((int)num); 365 } 366 367 if (num == Double.POSITIVE_INFINITY) { 368 return "Infinity"; 369 } 370 371 if (num == Double.NEGATIVE_INFINITY) { 372 return "-Infinity"; 373 } 374 375 if (Double.isNaN(num)) { 376 return "NaN"; 377 } 378 379 return NumberToString.stringFor(num); 380 } 381 382 /** 383 * JavaScript compliant conversion of number to String 384 * 385 * @param num a number 386 * @param radix a radix for the conversion 387 * 388 * @return a string 389 */ 390 public static String toString(final double num, final int radix) { 391 assert radix >= 2 && radix <= 36 : "invalid radix"; 392 393 if (isRepresentableAsInt(num)) { 394 return Integer.toString((int)num, radix); 395 } 396 397 if (num == Double.POSITIVE_INFINITY) { 398 return "Infinity"; 399 } 400 401 if (num == Double.NEGATIVE_INFINITY) { 402 return "-Infinity"; 403 } 404 405 if (Double.isNaN(num)) { 406 return "NaN"; 407 } 408 409 if (num == 0.0) { 410 return "0"; 411 } 412 413 final String chars = "0123456789abcdefghijklmnopqrstuvwxyz"; 414 final StringBuilder sb = new StringBuilder(); 415 416 final boolean negative = num < 0.0; 417 final double signedNum = negative ? -num : num; 418 419 double intPart = Math.floor(signedNum); 420 double decPart = signedNum - intPart; 421 422 // encode integer part from least significant digit, then reverse 423 do { 424 sb.append(chars.charAt((int) (intPart % radix))); 425 intPart /= radix; 426 } while (intPart >= 1.0); 427 428 if (negative) { 429 sb.append('-'); 430 } 431 sb.reverse(); 432 433 // encode decimal part 434 if (decPart > 0.0) { 435 final int dot = sb.length(); 436 sb.append('.'); 437 do { 438 decPart *= radix; 439 final double d = Math.floor(decPart); 440 sb.append(chars.charAt((int)d)); 441 decPart -= d; 442 } while (decPart > 0.0 && sb.length() - dot < 1100); 443 // somewhat arbitrarily use same limit as V8 444 } 445 446 return sb.toString(); 447 } 448 449 /** 450 * JavaScript compliant conversion of Object to number 451 * See ECMA 9.3 ToNumber 452 * 453 * @param obj an object 454 * 455 * @return a number 456 */ 457 public static double toNumber(final Object obj) { 458 if (obj instanceof Number) { 459 return ((Number)obj).doubleValue(); 460 } 461 return toNumberGeneric(obj); 462 } 463 464 /** 465 * Digit representation for a character 466 * 467 * @param ch a character 468 * @param radix radix 469 * 470 * @return the digit for this character 471 */ 472 public static int digit(final char ch, final int radix) { 473 return digit(ch, radix, false); 474 } 475 476 /** 477 * Digit representation for a character 478 * 479 * @param ch a character 480 * @param radix radix 481 * @param onlyIsoLatin1 iso latin conversion only 482 * 483 * @return the digit for this character 484 */ 485 public static int digit(final char ch, final int radix, final boolean onlyIsoLatin1) { 486 final char maxInRadix = (char)('a' + (radix - 1) - 10); 487 final char c = Character.toLowerCase(ch); 488 489 if (c >= 'a' && c <= maxInRadix) { 490 return Character.digit(ch, radix); 491 } 492 493 if (Character.isDigit(ch)) { 494 if (!onlyIsoLatin1 || ch >= '0' && ch <= '9') { 495 return Character.digit(ch, radix); 496 } 497 } 498 499 return -1; 500 } 501 502 /** 503 * JavaScript compliant String to number conversion 504 * 505 * @param str a string 506 * 507 * @return a number 508 */ 509 public static double toNumber(final String str) { 510 int end = str.length(); 511 if (end == 0) { 512 return 0.0; // Empty string 513 } 514 515 int start = 0; 516 char f = str.charAt(0); 517 518 while (Lexer.isJSWhitespace(f)) { 519 if (++start == end) { 520 return 0.0d; // All whitespace string 521 } 522 f = str.charAt(start); 523 } 524 525 // Guaranteed to terminate even without start >= end check, as the previous loop found at least one 526 // non-whitespace character. 527 while (Lexer.isJSWhitespace(str.charAt(end - 1))) { 528 end--; 529 } 530 531 final boolean negative; 532 if (f == '-') { 533 if(++start == end) { 534 return Double.NaN; // Single-char "-" string 535 } 536 f = str.charAt(start); 537 negative = true; 538 } else { 539 if (f == '+') { 540 if (++start == end) { 541 return Double.NaN; // Single-char "+" string 542 } 543 f = str.charAt(start); 544 } 545 negative = false; 546 } 547 548 final double value; 549 if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') { 550 //decode hex string 551 value = parseRadix(str.toCharArray(), start + 2, end, 16); 552 } else { 553 // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or 554 // "N" to allow for parsing "NaN" and "Infinity" correctly. 555 if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') { 556 return Double.NaN; 557 } 558 try { 559 value = Double.parseDouble(str.substring(start, end)); 560 } catch (final NumberFormatException e) { 561 return Double.NaN; 562 } 563 } 564 565 return negative ? -value : value; 566 } 567 568 /** 569 * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger 570 * 571 * <p>Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE} 572 * for double values that exceed the int range, including positive and negative Infinity. It is the 573 * caller's responsibility to handle such values correctly.</p> 574 * 575 * @param obj an object 576 * @return an integer 577 */ 578 public static int toInteger(final Object obj) { 579 return (int)toNumber(obj); 580 } 581 582 /** 583 * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger 584 * 585 * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE} 586 * for double values that exceed the long range, including positive and negative Infinity. It is the 587 * caller's responsibility to handle such values correctly.</p> 588 * 589 * @param obj an object 590 * @return a long 591 */ 592 public static long toLong(final Object obj) { 593 return (long)toNumber(obj); 594 } 595 596 /** 597 * JavaScript compliant Object to int32 conversion 598 * See ECMA 9.5 ToInt32 599 * 600 * @param obj an object 601 * @return an int32 602 */ 603 public static int toInt32(final Object obj) { 604 return toInt32(toNumber(obj)); 605 } 606 607 /** 608 * JavaScript compliant long to int32 conversion 609 * 610 * @param num a long 611 * @return an int32 612 */ 613 public static int toInt32(final long num) { 614 return (int)num; 615 } 616 617 /** 618 * JavaScript compliant number to int32 conversion 619 * 620 * @param num a number 621 * @return an int32 622 */ 623 public static int toInt32(final double num) { 624 return (int)doubleToInt32(num); 625 } 626 627 /** 628 * JavaScript compliant Object to int64 conversion 629 * 630 * @param obj an object 631 * @return an int64 632 */ 633 public static long toInt64(final Object obj) { 634 return toInt64(toNumber(obj)); 635 } 636 637 /** 638 * JavaScript compliant number to int64 conversion 639 * 640 * @param num a number 641 * @return an int64 642 */ 643 public static long toInt64(final double num) { 644 if (Double.isInfinite(num)) { 645 return 0L; 646 } 647 return (long)num; 648 } 649 650 /** 651 * JavaScript compliant Object to uint32 conversion 652 * 653 * @param obj an object 654 * @return a uint32 655 */ 656 public static long toUint32(final Object obj) { 657 return toUint32(toNumber(obj)); 658 } 659 660 /** 661 * JavaScript compliant number to uint32 conversion 662 * 663 * @param num a number 664 * @return a uint32 665 */ 666 public static long toUint32(final double num) { 667 return doubleToInt32(num) & MAX_UINT; 668 } 669 670 /** 671 * JavaScript compliant Object to uint16 conversion 672 * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) 673 * 674 * @param obj an object 675 * @return a uint16 676 */ 677 public static int toUint16(final Object obj) { 678 return toUint16(toNumber(obj)); 679 } 680 681 /** 682 * JavaScript compliant number to uint16 conversion 683 * 684 * @param num a number 685 * @return a uint16 686 */ 687 public static int toUint16(final int num) { 688 return num & 0xffff; 689 } 690 691 /** 692 * JavaScript compliant number to uint16 conversion 693 * 694 * @param num a number 695 * @return a uint16 696 */ 697 public static int toUint16(final long num) { 698 return ((int)num) & 0xffff; 699 } 700 701 /** 702 * JavaScript compliant number to uint16 conversion 703 * 704 * @param num a number 705 * @return a uint16 706 */ 707 public static int toUint16(final double num) { 708 return ((int)doubleToInt32(num)) & 0xffff; 709 } 710 711 private static long doubleToInt32(final double num) { 712 final int exponent = Math.getExponent(num); 713 if (exponent < 31) { 714 return (long) num; // Fits into 32 bits 715 } 716 if (exponent >= 84) { 717 // Either infinite or NaN or so large that shift / modulo will produce 0 718 // (52 bit mantissa + 32 bit target width). 719 return 0; 720 } 721 // This is rather slow and could probably be sped up using bit-fiddling. 722 final double d = (num >= 0) ? Math.floor(num) : Math.ceil(num); 723 return (long)(d % INT32_LIMIT); 724 } 725 726 /** 727 * Check whether a number is finite 728 * 729 * @param num a number 730 * @return true if finite 731 */ 732 public static boolean isFinite(final double num) { 733 return !Double.isInfinite(num) && !Double.isNaN(num); 734 } 735 736 /** 737 * Convert a primitive to a double 738 * 739 * @param num a double 740 * @return a boxed double 741 */ 742 public static Double toDouble(final double num) { 743 return num; 744 } 745 746 /** 747 * Convert a primitive to a double 748 * 749 * @param num a long 750 * @return a boxed double 751 */ 752 public static Double toDouble(final long num) { 753 return (double)num; 754 } 755 756 /** 757 * Convert a primitive to a double 758 * 759 * @param num an int 760 * @return a boxed double 761 */ 762 public static Double toDouble(final int num) { 763 return (double)num; 764 } 765 766 /** 767 * Convert a boolean to an Object 768 * 769 * @param bool a boolean 770 * @return a boxed boolean, its Object representation 771 */ 772 public static Object toObject(final boolean bool) { 773 return bool; 774 } 775 776 /** 777 * Convert a number to an Object 778 * 779 * @param num an integer 780 * @return the boxed number 781 */ 782 public static Object toObject(final int num) { 783 return num; 784 } 785 786 /** 787 * Convert a number to an Object 788 * 789 * @param num a long 790 * @return the boxed number 791 */ 792 public static Object toObject(final long num) { 793 return num; 794 } 795 796 /** 797 * Convert a number to an Object 798 * 799 * @param num a double 800 * @return the boxed number 801 */ 802 public static Object toObject(final double num) { 803 return num; 804 } 805 806 /** 807 * Identity converter for objects. 808 * 809 * @param obj an object 810 * @return the boxed number 811 */ 812 public static Object toObject(final Object obj) { 813 return obj; 814 } 815 816 /** 817 * Object conversion. This is used to convert objects and numbers to their corresponding 818 * NativeObject type 819 * See ECMA 9.9 ToObject 820 * 821 * @param obj the object to convert 822 * 823 * @return the wrapped object 824 */ 825 public static Object toScriptObject(final Object obj) { 826 return toScriptObject(Context.getGlobalTrusted(), obj); 827 } 828 829 /** 830 * Object conversion. This is used to convert objects and numbers to their corresponding 831 * NativeObject type 832 * See ECMA 9.9 ToObject 833 * 834 * @param global the global object 835 * @param obj the object to convert 836 * 837 * @return the wrapped object 838 */ 839 public static Object toScriptObject(final ScriptObject global, final Object obj) { 840 if (nullOrUndefined(obj)) { 841 throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj)); 842 } 843 844 if (obj instanceof ScriptObject) { 845 return obj; 846 } 847 848 return ((GlobalObject)global).wrapAsObject(obj); 849 } 850 851 /** 852 * Check if an object is null or undefined 853 * 854 * @param obj object to check 855 * 856 * @return true if null or undefined 857 */ 858 public static boolean nullOrUndefined(final Object obj) { 859 return obj == null || obj == ScriptRuntime.UNDEFINED; 860 } 861 862 static String toStringImpl(final Object obj, final boolean safe) { 863 if (obj instanceof String) { 864 return (String)obj; 865 } 866 867 if (obj instanceof Number) { 868 return toString(((Number)obj).doubleValue()); 869 } 870 871 if (obj == ScriptRuntime.UNDEFINED) { 872 return "undefined"; 873 } 874 875 if (obj == null) { 876 return "null"; 877 } 878 879 if (obj instanceof ScriptObject) { 880 if (safe) { 881 final ScriptObject sobj = (ScriptObject)obj; 882 final GlobalObject gobj = (GlobalObject)Context.getGlobalTrusted(); 883 return gobj.isError(sobj) ? 884 ECMAException.safeToString(sobj) : 885 sobj.safeToString(); 886 } 887 888 return toString(toPrimitive(obj, String.class)); 889 } 890 891 if (obj instanceof StaticClass) { 892 return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]"; 893 } 894 895 return obj.toString(); 896 } 897 898 // trim from left for JS whitespaces. 899 static String trimLeft(final String str) { 900 int start = 0; 901 902 while (start < str.length() && Lexer.isJSWhitespace(str.charAt(start))) { 903 start++; 904 } 905 906 return str.substring(start); 907 } 908 909 private static double parseRadix(final char chars[], final int start, final int length, final int radix) { 910 int pos = 0; 911 912 for (int i = start; i < length ; i++) { 913 if (digit(chars[i], radix) == -1) { 914 break; 915 } 916 pos++; 917 } 918 919 if (pos == 0) { 920 return Double.NaN; 921 } 922 923 double value = 0.0; 924 for (int i = start; i < start + pos; i++) { 925 value *= radix; 926 value += digit(chars[i], radix); 927 } 928 929 return value; 930 } 931 932 private static double toNumberGeneric(final Object obj) { 933 if (obj == null) { 934 return +0.0; 935 } 936 937 if (obj instanceof String) { 938 return toNumber((String)obj); 939 } 940 941 if (obj instanceof ConsString) { 942 return toNumber(obj.toString()); 943 } 944 945 if (obj instanceof Boolean) { 946 return (Boolean)obj ? 1 : +0.0; 947 } 948 949 if (obj instanceof ScriptObject) { 950 return toNumber(toPrimitive(obj, Number.class)); 951 } 952 953 return Double.NaN; 954 } 955 956 } --- EOF ---