diff options
Diffstat (limited to 'JavaScriptCore/runtime/NumberPrototype.cpp')
-rw-r--r-- | JavaScriptCore/runtime/NumberPrototype.cpp | 310 |
1 files changed, 0 insertions, 310 deletions
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp deleted file mode 100644 index 0b86c00..0000000 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org) - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - * - */ - -#include "config.h" -#include "NumberPrototype.h" - -#include "Error.h" -#include "JSFunction.h" -#include "JSString.h" -#include "Operations.h" -#include "PrototypeFunction.h" -#include "dtoa.h" -#include <wtf/Assertions.h> -#include <wtf/DecimalNumber.h> -#include <wtf/MathExtras.h> -#include <wtf/Vector.h> - -namespace JSC { - -ASSERT_CLASS_FITS_IN_CELL(NumberPrototype); - -static EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*); -static EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*); -static EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*); -static EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*); -static EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*); -static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*); - -// ECMA 15.7.4 - -NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) - : NumberObject(structure) -{ - setInternalValue(jsNumber(0)); - - // The constructor will be added later, after NumberConstructor has been constructed - - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum); -} - -// ------------------------------ Functions --------------------------- - -// ECMA 15.7.4.2 - 15.7.4.7 - -static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double &x) -{ - JSValue v = thisValue.getJSNumber(); - if (UNLIKELY(!v)) - return false; - x = v.uncheckedGetNumber(); - return true; -} - -static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined) -{ - result = 0; - isUndefined = false; - - JSValue argument0 = exec->argument(0); - if (argument0.isUndefined()) { - isUndefined = true; - return true; - } - - double asDouble = argument0.toInteger(exec); - if (asDouble < low || asDouble > high) - return false; - - result = static_cast<int>(asDouble); - return true; -} - -// toExponential converts a number to a string, always formatting as an expoential. -// This method takes an optional argument specifying a number of *decimal places* -// to round the significand to (or, put another way, this method optionally rounds -// to argument-plus-one significant figures). -EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec) -{ - // Get x (the double value of this, which should be a Number). - double x; - if (!toThisNumber(exec->hostThisValue(), x)) - return throwVMTypeError(exec); - - // Get the argument. - int decimalPlacesInExponent; - bool isUndefined; - if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlacesInExponent, isUndefined)) - return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20")); - - // Handle NaN and Infinity. - if (isnan(x) || isinf(x)) - return JSValue::encode(jsString(exec, UString::number(x))); - - // Round if the argument is not undefined, always format as exponential. - NumberToStringBuffer buffer; - unsigned length = isUndefined - ? DecimalNumber(x).toStringExponential(buffer, WTF::NumberToStringBufferLength) - : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer, WTF::NumberToStringBufferLength); - - return JSValue::encode(jsString(exec, UString(buffer, length))); -} - -// toFixed converts a number to a string, always formatting as an a decimal fraction. -// This method takes an argument specifying a number of decimal places to round the -// significand to. However when converting large values (1e+21 and above) this -// method will instead fallback to calling ToString. -EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) -{ - // Get x (the double value of this, which should be a Number). - JSValue thisValue = exec->hostThisValue(); - JSValue v = thisValue.getJSNumber(); - if (!v) - return throwVMTypeError(exec); - double x = v.uncheckedGetNumber(); - - // Get the argument. - int decimalPlaces; - bool isUndefined; // This is ignored; undefined treated as 0. - if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlaces, isUndefined)) - return throwVMError(exec, createRangeError(exec, "toFixed() argument must be between 0 and 20")); - - // 15.7.4.5.7 states "If x >= 10^21, then let m = ToString(x)" - // This also covers Ininity, and structure the check so that NaN - // values are also handled by numberToString - if (!(fabs(x) < 1e+21)) - return JSValue::encode(jsString(exec, UString::number(x))); - - // The check above will return false for NaN or Infinity, these will be - // handled by numberToString. - ASSERT(!isnan(x) && !isinf(x)); - - // Convert to decimal with rounding, and format as decimal. - NumberToStringBuffer buffer; - unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer, WTF::NumberToStringBufferLength); - return JSValue::encode(jsString(exec, UString(buffer, length))); -} - -// toPrecision converts a number to a string, takeing an argument specifying a -// number of significant figures to round the significand to. For positive -// exponent, all values that can be represented using a decimal fraction will -// be, e.g. when rounding to 3 s.f. any value up to 999 will be formated as a -// decimal, whilst 1000 is converted to the exponential representation 1.00e+3. -// For negative exponents values >= 1e-6 are formated as decimal fractions, -// with smaller values converted to exponential representation. -EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) -{ - // Get x (the double value of this, which should be a Number). - JSValue thisValue = exec->hostThisValue(); - JSValue v = thisValue.getJSNumber(); - if (!v) - return throwVMTypeError(exec); - double x = v.uncheckedGetNumber(); - - // Get the argument. - int significantFigures; - bool isUndefined; - if (!getIntegerArgumentInRange(exec, 1, 21, significantFigures, isUndefined)) - return throwVMError(exec, createRangeError(exec, "toPrecision() argument must be between 1 and 21")); - - // To precision called with no argument is treated as ToString. - if (isUndefined) - return JSValue::encode(jsString(exec, UString::number(x))); - - // Handle NaN and Infinity. - if (isnan(x) || isinf(x)) - return JSValue::encode(jsString(exec, UString::number(x))); - - // Convert to decimal with rounding. - DecimalNumber number(x, RoundingSignificantFigures, significantFigures); - // If number is in the range 1e-6 <= x < pow(10, significantFigures) then format - // as decimal. Otherwise, format the number as an exponential. Decimal format - // demands a minimum of (exponent + 1) digits to represent a number, for example - // 1234 (1.234e+3) requires 4 digits. (See ECMA-262 15.7.4.7.10.c) - NumberToStringBuffer buffer; - unsigned length = number.exponent() >= -6 && number.exponent() < significantFigures - ? number.toStringDecimal(buffer, WTF::NumberToStringBufferLength) - : number.toStringExponential(buffer, WTF::NumberToStringBufferLength); - return JSValue::encode(jsString(exec, UString(buffer, length))); -} - -EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec) -{ - JSValue thisValue = exec->hostThisValue(); - JSValue v = thisValue.getJSNumber(); - if (!v) - return throwVMTypeError(exec); - - JSValue radixValue = exec->argument(0); - int radix; - if (radixValue.isInt32()) - radix = radixValue.asInt32(); - else if (radixValue.isUndefined()) - radix = 10; - else - radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0 - - if (radix == 10) - return JSValue::encode(jsString(exec, v.toString(exec))); - - static const char* const digits = "0123456789abcdefghijklmnopqrstuvwxyz"; - - // Fast path for number to character conversion. - if (radix == 36) { - if (v.isInt32()) { - int x = v.asInt32(); - if (static_cast<unsigned>(x) < 36) { // Exclude negatives - JSGlobalData* globalData = &exec->globalData(); - return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, digits[x])); - } - } - } - - if (radix < 2 || radix > 36) - return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36")); - - // INT_MAX results in 1024 characters left of the dot with radix 2 - // give the same space on the right side. safety checks are in place - // unless someone finds a precise rule. - char s[2048 + 3]; - const char* lastCharInString = s + sizeof(s) - 1; - double x = v.uncheckedGetNumber(); - if (isnan(x) || isinf(x)) - return JSValue::encode(jsString(exec, UString::number(x))); - - bool isNegative = x < 0.0; - if (isNegative) - x = -x; - - double integerPart = floor(x); - char* decimalPoint = s + sizeof(s) / 2; - - // convert integer portion - char* p = decimalPoint; - double d = integerPart; - do { - int remainderDigit = static_cast<int>(fmod(d, radix)); - *--p = digits[remainderDigit]; - d /= radix; - } while ((d <= -1.0 || d >= 1.0) && s < p); - - if (isNegative) - *--p = '-'; - char* startOfResultString = p; - ASSERT(s <= startOfResultString); - - d = x - integerPart; - p = decimalPoint; - const double epsilon = 0.001; // TODO: guessed. base on radix ? - bool hasFractionalPart = (d < -epsilon || d > epsilon); - if (hasFractionalPart) { - *p++ = '.'; - do { - d *= radix; - const int digit = static_cast<int>(d); - *p++ = digits[digit]; - d -= digit; - } while ((d < -epsilon || d > epsilon) && p < lastCharInString); - } - *p = '\0'; - ASSERT(p < s + sizeof(s)); - - return JSValue::encode(jsString(exec, startOfResultString)); -} - -EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec) -{ - JSValue thisValue = exec->hostThisValue(); - // FIXME: Not implemented yet. - - JSValue v = thisValue.getJSNumber(); - if (!v) - return throwVMTypeError(exec); - - return JSValue::encode(jsString(exec, v.toString(exec))); -} - -EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec) -{ - JSValue thisValue = exec->hostThisValue(); - JSValue v = thisValue.getJSNumber(); - if (!v) - return throwVMTypeError(exec); - - return JSValue::encode(v); -} - -} // namespace JSC |