// 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) { double x; if (!toThisNumber(exec->thisValue(), x)) return throwVMTypeError(exec); // 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, ASCIILiteral("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, String::numberToStringECMAScript(x))); // The check above will return false for NaN or Infinity, these will be // handled by numberToString. ASSERT(std::isfinite(x)); NumberToStringBuffer buffer; return JSValue::encode(jsString(exec, String(numberToFixedWidthString(x, decimalPlaces, buffer)))); }
// 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) { double x; if (!toThisNumber(exec->thisValue(), x)) return throwVMTypeError(exec); // Get the argument. int decimalPlacesInExponent; bool isUndefined; if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlacesInExponent, isUndefined)) return throwVMError(exec, createRangeError(exec, ASCIILiteral("toExponential() argument must be between 0 and 20"))); // Handle NaN and Infinity. if (!std::isfinite(x)) return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(x))); // Round if the argument is not undefined, always format as exponential. char buffer[WTF::NumberToStringBufferLength]; DoubleConversionStringBuilder builder(buffer, WTF::NumberToStringBufferLength); const DoubleToStringConverter& converter = DoubleToStringConverter::EcmaScriptConverter(); builder.Reset(); isUndefined ? converter.ToExponential(x, -1, &builder) : converter.ToExponential(x, decimalPlacesInExponent, &builder); return JSValue::encode(jsString(exec, String(builder.Finalize()))); }
// 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. EncodedTiValue JSC_HOST_CALL numberProtoFuncToPrecision(TiExcState* exec) { // Get x (the double value of this, which should be a Number). TiValue thisValue = exec->hostThisValue(); TiValue 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 TiValue::encode(jsString(exec, UString::number(x))); // Handle NaN and Infinity. if (isnan(x) || isinf(x)) return TiValue::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, WTI::NumberToStringBufferLength) : number.toStringExponential(buffer, WTI::NumberToStringBufferLength); return TiValue::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. EncodedTiValue JSC_HOST_CALL numberProtoFuncToFixed(TiExcState* exec) { // Get x (the double value of this, which should be a Number). TiValue thisValue = exec->hostThisValue(); TiValue 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 TiValue::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, WTI::NumberToStringBufferLength); return TiValue::encode(jsString(exec, UString(buffer, length))); }
// 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). EncodedTiValue JSC_HOST_CALL numberProtoFuncToExponential(TiExcState* 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 TiValue::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, WTI::NumberToStringBufferLength) : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer, WTI::NumberToStringBufferLength); return TiValue::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) { double x; if (!toThisNumber(exec->thisValue(), x)) return throwVMTypeError(exec); // Get the argument. int significantFigures; bool isUndefined; if (!getIntegerArgumentInRange(exec, 1, 21, significantFigures, isUndefined)) return throwVMError(exec, createRangeError(exec, ASCIILiteral("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, String::numberToStringECMAScript(x))); // Handle NaN and Infinity. if (!std::isfinite(x)) return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(x))); NumberToStringBuffer buffer; return JSValue::encode(jsString(exec, String(numberToFixedPrecisionString(x, significantFigures, buffer)))); }