Example #1
0
double
js::ecmaPow(double x, double y)
{
    /*
     * Use powi if the exponent is an integer-valued double. We don't have to
     * check for NaN since a comparison with NaN is always false.
     */
    int32_t yi;
    if (NumberEqualsInt32(y, &yi))
        return powi(x, yi);

    /*
     * Because C99 and ECMA specify different behavior for pow(),
     * we need to wrap the libm call to make it ECMA compliant.
     */
    if (!IsFinite(y) && (x == 1.0 || x == -1.0))
        return GenericNaN();

    /* pow(x, +-0) is always 1, even for x = NaN (MSVC gets this wrong). */
    if (y == 0)
        return 1;

    /*
     * Special case for square roots. Note that pow(x, 0.5) != sqrt(x)
     * when x = -0.0, so we have to guard for this.
     */
    if (IsFinite(x) && x != 0.0) {
        if (y == 0.5)
            return sqrt(x);
        if (y == -0.5)
            return 1.0 / sqrt(x);
    }
    return pow(x, y);
}
Example #2
0
static bool
Str(JSContext* cx, const Value& v, StringifyContext* scx)
{
    /* Step 11 must be handled by the caller. */
    MOZ_ASSERT(!IsFilteredValue(v));

    JS_CHECK_RECURSION(cx, return false);

    /*
     * This method implements the Str algorithm in ES5 15.12.3, but:
     *
     *   * We move property retrieval (step 1) into callers to stream the
     *     stringification process and avoid constantly copying strings.
     *   * We move the preprocessing in steps 2-4 into a helper function to
     *     allow both JO and JA to use this method.  While JA could use it
     *     without this move, JO must omit any |undefined|-valued property per
     *     so it can't stream out a value using the Str method exactly as
     *     defined by ES5.
     *   * We move step 11 into callers, again to ease streaming.
     */

    /* Step 8. */
    if (v.isString())
        return Quote(cx, scx->sb, v.toString());

    /* Step 5. */
    if (v.isNull())
        return scx->sb.append("null");

    /* Steps 6-7. */
    if (v.isBoolean())
        return v.toBoolean() ? scx->sb.append("true") : scx->sb.append("false");

    /* Step 9. */
    if (v.isNumber()) {
        if (v.isDouble()) {
            if (!IsFinite(v.toDouble()))
                return scx->sb.append("null");
        }

        return NumberValueToStringBuffer(cx, v, scx->sb);
    }

    /* Step 10. */
    MOZ_ASSERT(v.isObject());
    RootedObject obj(cx, &v.toObject());

    scx->depth++;
    bool ok;
    if (IsArray(obj, cx))
        ok = JA(cx, obj, scx);
    else
        ok = JO(cx, obj, scx);
    scx->depth--;

    return ok;
}
Example #3
0
T
js::GetBiggestNumberLessThan(T x)
{
    MOZ_ASSERT(!IsNegative(x));
    MOZ_ASSERT(IsFinite(x));
    typedef typename mozilla::FloatingPoint<T>::Bits Bits;
    Bits bits = mozilla::BitwiseCast<Bits>(x);
    MOZ_ASSERT(bits > 0, "will underflow");
    return mozilla::BitwiseCast<T>(bits - 1);
}
Example #4
0
double
js::ecmaPow(double x, double y)
{
    /*
     * Use powi if the exponent is an integer-valued double. We don't have to
     * check for NaN since a comparison with NaN is always false.
     */
    if (int32_t(y) == y)
        return powi(x, int32_t(y));

    /*
     * Because C99 and ECMA specify different behavior for pow(),
     * we need to wrap the libm call to make it ECMA compliant.
     */
    if (!IsFinite(y) && (x == 1.0 || x == -1.0))
        return js_NaN;
    /* pow(x, +-0) is always 1, even for x = NaN (MSVC gets this wrong). */
    if (y == 0)
        return 1;
    return pow(x, y);
}
Example #5
0
JSBool
js_math_pow(JSContext *cx, unsigned argc, Value *vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (args.length() <= 1) {
        args.rval().setDouble(js_NaN);
        return true;
    }

    double x, y;
    if (!ToNumber(cx, args[0], &x) || !ToNumber(cx, args[1], &y))
        return false;

    /*
     * Special case for square roots. Note that pow(x, 0.5) != sqrt(x)
     * when x = -0.0, so we have to guard for this.
     */
    if (IsFinite(x) && x != 0.0) {
        if (y == 0.5) {
            args.rval().setNumber(sqrt(x));
            return true;
        }
        if (y == -0.5) {
            args.rval().setNumber(1.0/sqrt(x));
            return true;
        }
    }

    /* pow(x, +-0) is always 1, even for x = NaN. */
    if (y == 0) {
        args.rval().setInt32(1);
        return true;
    }

    double z = ecmaPow(x, y);

    args.rval().setNumber(z);
    return true;
}
Example #6
0
static bool
Str(JSContext* cx, const Value& v, StringifyContext* scx)
{
    /* Step 11 must be handled by the caller. */
    MOZ_ASSERT(!IsFilteredValue(v));

    JS_CHECK_RECURSION(cx, return false);

    /*
     * This method implements the Str algorithm in ES5 15.12.3, but:
     *
     *   * We move property retrieval (step 1) into callers to stream the
     *     stringification process and avoid constantly copying strings.
     *   * We move the preprocessing in steps 2-4 into a helper function to
     *     allow both JO and JA to use this method.  While JA could use it
     *     without this move, JO must omit any |undefined|-valued property per
     *     so it can't stream out a value using the Str method exactly as
     *     defined by ES5.
     *   * We move step 11 into callers, again to ease streaming.
     */

    /* Step 8. */
    if (v.isString())
        return Quote(cx, scx->sb, v.toString());

    /* Step 5. */
    if (v.isNull())
        return scx->sb.append("null");

    /* Steps 6-7. */
    if (v.isBoolean())
        return v.toBoolean() ? scx->sb.append("true") : scx->sb.append("false");

    /* Step 9. */
    if (v.isNumber()) {
        if (v.isDouble()) {
            if (!IsFinite(v.toDouble())) {
                MOZ_ASSERT(!scx->maybeSafely,
                           "input JS::ToJSONMaybeSafely must not include "
                           "reachable non-finite numbers");
                return scx->sb.append("null");
            }
        }

        return NumberValueToStringBuffer(cx, v, scx->sb);
    }

    /* Step 10. */
    MOZ_ASSERT(v.isObject());
    RootedObject obj(cx, &v.toObject());

    MOZ_ASSERT(!scx->maybeSafely || obj->is<PlainObject>() || obj->is<ArrayObject>(),
               "input to JS::ToJSONMaybeSafely must not include reachable "
               "objects that are neither arrays nor plain objects");

    scx->depth++;
    auto dec = mozilla::MakeScopeExit([&] { scx->depth--; });

    bool isArray;
    if (!IsArray(cx, obj, &isArray))
        return false;

    return isArray ? JA(cx, obj, scx) : JO(cx, obj, scx);
}
Example #7
0
static void
TestPredicates()
{
  MOZ_ASSERT(IsNaN(UnspecifiedNaN()));
  MOZ_ASSERT(IsNaN(SpecificNaN(1, 17)));;
  MOZ_ASSERT(IsNaN(SpecificNaN(0, 0xfffffffffff0fULL)));
  MOZ_ASSERT(!IsNaN(0));
  MOZ_ASSERT(!IsNaN(-0.0));
  MOZ_ASSERT(!IsNaN(1.0));
  MOZ_ASSERT(!IsNaN(PositiveInfinity()));
  MOZ_ASSERT(!IsNaN(NegativeInfinity()));

  MOZ_ASSERT(IsInfinite(PositiveInfinity()));
  MOZ_ASSERT(IsInfinite(NegativeInfinity()));
  MOZ_ASSERT(!IsInfinite(UnspecifiedNaN()));
  MOZ_ASSERT(!IsInfinite(0));
  MOZ_ASSERT(!IsInfinite(-0.0));
  MOZ_ASSERT(!IsInfinite(1.0));

  MOZ_ASSERT(!IsFinite(PositiveInfinity()));
  MOZ_ASSERT(!IsFinite(NegativeInfinity()));
  MOZ_ASSERT(!IsFinite(UnspecifiedNaN()));
  MOZ_ASSERT(IsFinite(0));
  MOZ_ASSERT(IsFinite(-0.0));
  MOZ_ASSERT(IsFinite(1.0));

  MOZ_ASSERT(!IsNegative(PositiveInfinity()));
  MOZ_ASSERT(IsNegative(NegativeInfinity()));
  MOZ_ASSERT(IsNegative(-0.0));
  MOZ_ASSERT(!IsNegative(0.0));
  MOZ_ASSERT(IsNegative(-1.0));
  MOZ_ASSERT(!IsNegative(1.0));

  MOZ_ASSERT(!IsNegativeZero(PositiveInfinity()));
  MOZ_ASSERT(!IsNegativeZero(NegativeInfinity()));
  MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));;
  MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 0xfffffffffff0fULL)));
  MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));;
  MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 0xfffffffffff0fULL)));
  MOZ_ASSERT(!IsNegativeZero(UnspecifiedNaN()));
  MOZ_ASSERT(IsNegativeZero(-0.0));
  MOZ_ASSERT(!IsNegativeZero(0.0));
  MOZ_ASSERT(!IsNegativeZero(-1.0));
  MOZ_ASSERT(!IsNegativeZero(1.0));

  int32_t i;
  MOZ_ASSERT(DoubleIsInt32(0.0, &i)); MOZ_ASSERT(i == 0);
  MOZ_ASSERT(!DoubleIsInt32(-0.0, &i));
  MOZ_ASSERT(DoubleEqualsInt32(0.0, &i)); MOZ_ASSERT(i == 0);
  MOZ_ASSERT(DoubleEqualsInt32(-0.0, &i)); MOZ_ASSERT(i == 0);
  MOZ_ASSERT(DoubleIsInt32(INT32_MIN, &i)); MOZ_ASSERT(i == INT32_MIN);
  MOZ_ASSERT(DoubleIsInt32(INT32_MAX, &i)); MOZ_ASSERT(i == INT32_MAX);
  MOZ_ASSERT(DoubleEqualsInt32(INT32_MIN, &i)); MOZ_ASSERT(i == INT32_MIN);
  MOZ_ASSERT(DoubleEqualsInt32(INT32_MAX, &i)); MOZ_ASSERT(i == INT32_MAX);
  MOZ_ASSERT(!DoubleIsInt32(0.5, &i));
  MOZ_ASSERT(!DoubleIsInt32(double(INT32_MAX) + 0.1, &i));
  MOZ_ASSERT(!DoubleIsInt32(double(INT32_MIN) - 0.1, &i));
  MOZ_ASSERT(!DoubleIsInt32(NegativeInfinity(), &i));
  MOZ_ASSERT(!DoubleIsInt32(PositiveInfinity(), &i));
  MOZ_ASSERT(!DoubleIsInt32(UnspecifiedNaN(), &i));
  MOZ_ASSERT(!DoubleEqualsInt32(0.5, &i));
  MOZ_ASSERT(!DoubleEqualsInt32(double(INT32_MAX) + 0.1, &i));
  MOZ_ASSERT(!DoubleEqualsInt32(double(INT32_MIN) - 0.1, &i));
  MOZ_ASSERT(!DoubleEqualsInt32(NegativeInfinity(), &i));
  MOZ_ASSERT(!DoubleEqualsInt32(PositiveInfinity(), &i));
  MOZ_ASSERT(!DoubleEqualsInt32(UnspecifiedNaN(), &i));
}