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