Changeset 63120 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jul 12, 2010, 2:32:34 PM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r63118 r63120 1 2010-07-09 Darin Adler <[email protected]> 2 3 Reviewed by Geoffrey Garen. 4 5 String to number coercion is not spec compliant 6 https://bugs.webkit.org/show_bug.cgi?id=31349 7 8 ToNumber should ignore NBSP (\u00a0) 9 https://bugs.webkit.org/show_bug.cgi?id=25490 10 11 * runtime/JSGlobalObjectFunctions.cpp: 12 (JSC::parseIntOverflow): Added a version that works on UChar. 13 * runtime/JSGlobalObjectFunctions.h: Ditto. 14 15 * runtime/UString.cpp: 16 (JSC::isInfinity): Added helper functions. 17 (JSC::UString::toDouble): Use isStrWhiteSpace instead of 18 isSASCIISpace to define what we should skip. Got rid of the 19 code that used CString and UTF8String, instead processing the 20 UChar of the string directly, except for when we call strtod. 21 For strtod, use our own home-grown conversion function that 22 does not try to do any UTF-16 processing. Tidied up the logic 23 a bit as well. 24 1 25 2010-07-12 Martin Robinson <[email protected]> 2 26 -
trunk/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r62819 r63120 197 197 } 198 198 199 double parseIntOverflow(const UChar* s, int length, int radix) 200 { 201 double number = 0.0; 202 double radixMultiplier = 1.0; 203 204 for (const UChar* p = s + length - 1; p >= s; p--) { 205 if (radixMultiplier == Inf) { 206 if (*p != '0') { 207 number = Inf; 208 break; 209 } 210 } else { 211 int digit = parseDigit(*p, radix); 212 number += digit * radixMultiplier; 213 } 214 215 radixMultiplier *= radix; 216 } 217 218 return number; 219 } 220 199 221 static double parseInt(const UString& s, int radix) 200 222 { -
trunk/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
r60631 r63120 1 1 /* 2 2 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 3 * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.3 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 4 4 * Copyright (C) 2007 Cameron Zwarich ([email protected]) 5 5 * Copyright (C) 2007 Maks Orlovich … … 54 54 static const double mantissaOverflowLowerBound = 9007199254740992.0; 55 55 double parseIntOverflow(const char*, int length, int radix); 56 double parseIntOverflow(const UChar*, int length, int radix); 56 57 bool isStrWhiteSpace(UChar); 57 58 -
trunk/JavaScriptCore/runtime/UString.cpp
r62457 r63120 243 243 } 244 244 245 static inline bool isInfinity(double number) 246 { 247 return number == Inf || number == -Inf; 248 } 249 250 static bool isInfinity(const UChar* data, const UChar* end) 251 { 252 return data + 7 < end 253 && data[0] == 'I' 254 && data[1] == 'n' 255 && data[2] == 'f' 256 && data[3] == 'i' 257 && data[4] == 'n' 258 && data[5] == 'i' 259 && data[6] == 't' 260 && data[7] == 'y'; 261 } 262 245 263 double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const 246 264 { 247 if (size() == 1) { 265 unsigned size = this->size(); 266 267 if (size == 1) { 248 268 UChar c = data()[0]; 249 269 if (isASCIIDigit(c)) 250 270 return c - '0'; 251 if (is ASCIISpace(c) && tolerateEmptyString)271 if (isStrWhiteSpace(c) && tolerateEmptyString) 252 272 return 0; 253 273 return NaN; … … 265 285 // right thing but requires UChar, not char, for its argument. 266 286 267 CString s = UTF8String();268 if (s.isNull())269 return NaN; 270 const char* c = s.data();271 272 // skip leading white space273 while (isASCIISpace(*c))274 c++;275 276 // empty string ?277 if ( *c == '\0')287 const UChar* data = this->data(); 288 const UChar* end = data + size; 289 290 // Skip leading white space. 291 for (; data < end; ++data) { 292 if (!isStrWhiteSpace(*data)) 293 break; 294 } 295 296 // Empty string. 297 if (data == end) 278 298 return tolerateEmptyString ? 0.0 : NaN; 279 299 280 double d; 281 282 // hex number ? 283 if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) { 284 const char* firstDigitPosition = c + 2; 285 c++; 286 d = 0.0; 287 while (*(++c)) { 288 if (*c >= '0' && *c <= '9') 289 d = d * 16.0 + *c - '0'; 290 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')) 291 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0; 292 else 300 double number; 301 302 if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2])) { 303 // Hex number. 304 data += 2; 305 const UChar* firstDigitPosition = data; 306 number = 0; 307 while (true) { 308 number = number * 16 + toASCIIHexValue(*data); 309 ++data; 310 if (data == end) 293 311 break; 294 } 295 296 if (d >= mantissaOverflowLowerBound) 297 d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16); 312 if (!isASCIIHexDigit(*data)) 313 break; 314 } 315 if (number >= mantissaOverflowLowerBound) 316 number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16); 298 317 } else { 299 // regular number ? 300 char* end; 301 d = WTF::strtod(c, &end); 302 if ((d != 0.0 || end != c) && d != Inf && d != -Inf) { 303 c = end; 304 } else { 305 double sign = 1.0; 306 307 if (*c == '+') 308 c++; 309 else if (*c == '-') { 310 sign = -1.0; 311 c++; 312 } 313 318 // Decimal number. 319 320 // Put into a null-terminated byte buffer. 321 Vector<char, 32> byteBuffer; 322 for (const UChar* characters = data; characters < end; ++characters) { 323 UChar character = *characters; 324 byteBuffer.append(isASCII(character) ? character : 0); 325 } 326 byteBuffer.append(0); 327 328 char* byteBufferEnd; 329 number = WTF::strtod(byteBuffer.data(), &byteBufferEnd); 330 const UChar* pastNumber = data + (byteBufferEnd - byteBuffer.data()); 331 332 if ((number || pastNumber != data) && !isInfinity(number)) 333 data = pastNumber; 334 else { 314 335 // We used strtod() to do the conversion. However, strtod() handles 315 336 // infinite values slightly differently than JavaScript in that it … … 317 338 // whereas the ECMA spec requires that it be converted to NaN. 318 339 319 if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') { 320 d = sign * Inf; 321 c += 8; 322 } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i') 323 c = end; 340 double signedInfinity = Inf; 341 if (data < end) { 342 if (*data == '+') 343 data++; 344 else if (*data == '-') { 345 signedInfinity = -Inf; 346 data++; 347 } 348 } 349 if (isInfinity(data, end)) { 350 number = signedInfinity; 351 data += 8; 352 } else if (isInfinity(number) && data < end && (*data | 0x20) != 'i') 353 data = pastNumber; 324 354 else 325 355 return NaN; … … 327 357 } 328 358 359 // Look for trailing junk. 329 360 if (!tolerateTrailingJunk) { 330 // allow trailing white space 331 while (isASCIISpace(*c)) 332 c++; 333 if (c != s.data() + s.length()) 334 d = NaN; 335 } 336 337 return d; 361 // Allow trailing white space. 362 for (; data < end; ++data) { 363 if (!isStrWhiteSpace(*data)) 364 break; 365 } 366 if (data != end) 367 return NaN; 368 } 369 370 return number; 338 371 } 339 372
Note:
See TracChangeset
for help on using the changeset viewer.