Changeset 65588 in webkit for trunk/JavaScriptCore/wtf/dtoa.cpp


Ignore:
Timestamp:
Aug 18, 2010, 12:41:22 AM (15 years ago)
Author:
[email protected]
Message:

Bug 44146 - Remove toDouble/toUInt32 methods from UString.

Reviewed by Sam Weinig.

JavaScriptCore:

These methods all implement JavaScript language specific behaviour, and as such
are not suited to being on a generic string object. They are also inefficient
and incorrectly used, refactor & cleanup. Uses of these methods really divide
out into two cases.

ToNumber:
Uses of toDouble from JSString and from parseFloat are implementing ecma's
ToNumber conversion from strings (see ecma-262 9.3.1), so UString::toDouble
should largely just be moved out to a global jsToNumber function. ToNumber is
capable of recognizing either decimal or hexadecimal numbers, but parseFloat
should only recognize decimal values. This is currently handled by testing for
hexadecimal before calling toDouble, which should unnecessary - instead we can
just split out the two parts to the grammar into separate functions. Also,
strtod recognizes a set of literals (nan, inf, and infinity - all with any
capitalization) - which are not defined by any of the specs we are implementing.
To handle this we need to perform additional work in toDouble to convert the
unsupported cases of infinities back to NaNs. Instead we should simply remove
support for this literals from strtod. This should provide a more desirable
behaviour for all clients of strtod.

Indexed properties:
Uses of the toStrictUInt32 methods are were all converting property names to
indices, and all uses of toUInt32 were incorrect; in all cases we should have
been calling toUInt32. This error results in some incorrect behaviour in the
DOM (accessing property "0 " of a NodeList should fail; it currently does not).
Move this method onto Identifier (our canonical property name), and make it
always perform a strict conversion. Add a layout test to check NodeList does
convert indexed property names correctly.

(JSC::Arguments::getOwnPropertySlot):
(JSC::Arguments::getOwnPropertyDescriptor):
(JSC::Arguments::put):
(JSC::Arguments::deleteProperty):

  • runtime/Identifier.cpp:

(JSC::Identifier::toUInt32):

  • runtime/Identifier.h:

(JSC::Identifier::toUInt32):

  • runtime/JSArray.cpp:

(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::deleteProperty):

  • runtime/JSArray.h:

(JSC::Identifier::toArrayIndex):

  • runtime/JSByteArray.cpp:

(JSC::JSByteArray::getOwnPropertySlot):
(JSC::JSByteArray::getOwnPropertyDescriptor):
(JSC::JSByteArray::put):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::isInfinity):
(JSC::jsHexIntegerLiteral):
(JSC::jsStrDecimalLiteral):
(JSC::jsToNumber):
(JSC::parseFloat):

  • runtime/JSGlobalObjectFunctions.h:
  • runtime/JSString.cpp:

(JSC::JSString::getPrimitiveNumber):
(JSC::JSString::toNumber):
(JSC::JSString::getStringPropertyDescriptor):

  • runtime/JSString.h:

(JSC::JSString::getStringPropertySlot):

  • runtime/ObjectPrototype.cpp:

(JSC::ObjectPrototype::put):

  • runtime/StringObject.cpp:

(JSC::StringObject::deleteProperty):

  • runtime/UString.cpp:
  • runtime/UString.h:
  • wtf/dtoa.cpp:

(WTF::strtod):

WebCore:

These methods all implement JavaScript language specific behaviour, and as such
are not suited to being on a generic string object. They are also inefficient
and incorrectly used, refactor & cleanup. Uses of these methods really divide
out into two cases.

ToNumber:
Uses of toDouble from JSString and from parseFloat are implementing ecma's
ToNumber conversion from strings (see ecma-262 9.3.1), so UString::toDouble
should largely just be moved out to a global jsToNumber function. ToNumber is
capable of recognizing either decimal or hexadecimal numbers, but parseFloat
should only recognize decimal values. This is currently handled by testing for
hexadecimal before calling toDouble, which should unnecessary - instead we can
just split out the two parts to the grammar into separate functions. Also,
strtod recognizes a set of literals (nan, inf, and infinity - all with any
capitalization) - which are not defined by any of the specs we are implementing.
To handle this we need to perform additional work in toDouble to convert the
unsupported cases of infinities back to NaNs. Instead we should simply remove
support for this literals from strtod. This should provide a more desirable
behaviour for all clients of strtod.

Indexed properties:
Uses of the toStrictUInt32 methods are were all converting property names to
indices, and all uses of toUInt32 were incorrect; in all cases we should have
been calling toUInt32. This error results in some incorrect behaviour in the
DOM (accessing property "0 " of a NodeList should fail; it currently does not).
Move this method onto Identifier (our canonical property name), and make it
always perform a strict conversion. Add a layout test to check NodeList does
convert indexed property names correctly.

Test: fast/dom/NodeList/nodelist-item-with-index.html

  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertyDescriptor):

  • bindings/js/JSHTMLAllCollectionCustom.cpp:

(WebCore::callHTMLAllCollection):
(WebCore::JSHTMLAllCollection::item):

  • bindings/js/JSHTMLCollectionCustom.cpp:

(WebCore::callHTMLCollection):
(WebCore::JSHTMLCollection::item):

  • bindings/js/JSNodeListCustom.cpp:

(WebCore::callNodeList):

  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::getOwnPropertySlot):
(JSC::RuntimeArray::getOwnPropertyDescriptor):
(JSC::RuntimeArray::put):

LayoutTests:

Test that indexing into nodelists works correctly, particularly
wrt indices passed as strings that contain whitespace.

  • fast/dom/NodeList/nodelist-item-with-index-expected.txt: Added.
  • fast/dom/NodeList/nodelist-item-with-index.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/dtoa.cpp

    r64706 r65588  
    8989 *    define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
    9090 *    FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
    91  * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
    92  *    Infinity and NaN (case insensitively).  On some systems (e.g.,
    93  *    some HP systems), it may be necessary to #define NAN_WORD0
    94  *    appropriately -- to the most significant word of a quiet NaN.
    95  *    (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
    96  *    When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
    97  *    strtod also accepts (case insensitively) strings of the form
    98  *    NaN(x), where x is a string of hexadecimal digits and spaces;
    99  *    if there is only one string of hexadecimal digits, it is taken
    100  *    for the 52 fraction bits of the resulting NaN; if there are two
    101  *    or more strings of hex digits, the first is for the high 20 bits,
    102  *    the second and subsequent for the low 32 bits, with intervening
    103  *    white space ignored; but if this results in none of the 52
    104  *    fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
    105  *    and NAN_WORD1 are used instead.
    10691 * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
    10792 *    avoids underflows on inputs whose result does not underflow.
     
    167152#endif
    168153
    169 #define INFNAN_CHECK
    170 #define No_Hex_NaN
    171 
    172154#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1
    173155Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined.
     
    10411023#define n_bigtens 5
    10421024
    1043 #if defined(INFNAN_CHECK)
    1044 
    1045 #ifndef NAN_WORD0
    1046 #define NAN_WORD0 0x7ff80000
    1047 #endif
    1048 
    1049 #ifndef NAN_WORD1
    1050 #define NAN_WORD1 0
    1051 #endif
    1052 
    1053 static int match(const char** sp, const char* t)
    1054 {
    1055     int c, d;
    1056     const char* s = *sp;
    1057 
    1058     while ((d = *t++)) {
    1059         if ((c = *++s) >= 'A' && c <= 'Z')
    1060             c += 'a' - 'A';
    1061         if (c != d)
    1062             return 0;
    1063     }
    1064     *sp = s + 1;
    1065     return 1;
    1066 }
    1067 
    1068 #ifndef No_Hex_NaN
    1069 static void hexnan(U* rvp, const char** sp)
    1070 {
    1071     uint32_t c, x[2];
    1072     const char* s;
    1073     int havedig, udx0, xshift;
    1074 
    1075     x[0] = x[1] = 0;
    1076     havedig = xshift = 0;
    1077     udx0 = 1;
    1078     s = *sp;
    1079     while ((c = *(const unsigned char*)++s)) {
    1080         if (c >= '0' && c <= '9')
    1081             c -= '0';
    1082         else if (c >= 'a' && c <= 'f')
    1083             c += 10 - 'a';
    1084         else if (c >= 'A' && c <= 'F')
    1085             c += 10 - 'A';
    1086         else if (c <= ' ') {
    1087             if (udx0 && havedig) {
    1088                 udx0 = 0;
    1089                 xshift = 1;
    1090             }
    1091             continue;
    1092         } else if (/*(*/ c == ')' && havedig) {
    1093             *sp = s + 1;
    1094             break;
    1095         } else
    1096             return;    /* invalid form: don't change *sp */
    1097         havedig = 1;
    1098         if (xshift) {
    1099             xshift = 0;
    1100             x[0] = x[1];
    1101             x[1] = 0;
    1102         }
    1103         if (udx0)
    1104             x[0] = (x[0] << 4) | (x[1] >> 28);
    1105         x[1] = (x[1] << 4) | c;
    1106     }
    1107     if ((x[0] &= 0xfffff) || x[1]) {
    1108         word0(rvp) = Exp_mask | x[0];
    1109         word1(rvp) = x[1];
    1110     }
    1111 }
    1112 #endif /*No_Hex_NaN*/
    1113 #endif /* INFNAN_CHECK */
    1114 
    11151025double strtod(const char* s00, char** se)
    11161026{
     
    12371147    if (!nd) {
    12381148        if (!nz && !nz0) {
    1239 #ifdef INFNAN_CHECK
    1240             /* Check for Nan and Infinity */
    1241             switch (c) {
    1242             case 'i':
    1243             case 'I':
    1244                 if (match(&s, "nf")) {
    1245                     --s;
    1246                     if (!match(&s, "inity"))
    1247                         ++s;
    1248                     word0(&rv) = 0x7ff00000;
    1249                     word1(&rv) = 0;
    1250                     goto ret;
    1251                 }
    1252                 break;
    1253             case 'n':
    1254             case 'N':
    1255                 if (match(&s, "an")) {
    1256                     word0(&rv) = NAN_WORD0;
    1257                     word1(&rv) = NAN_WORD1;
    1258 #ifndef No_Hex_NaN
    1259                     if (*s == '(') /*)*/
    1260                         hexnan(&rv, &s);
    1261 #endif
    1262                     goto ret;
    1263                 }
    1264             }
    1265 #endif /* INFNAN_CHECK */
    12661149ret0:
    12671150            s = s00;
Note: See TracChangeset for help on using the changeset viewer.