Bug 552574 - de-mystify js_ValueToNumber API (r=igor)

This commit is contained in:
Luke Wagner 2010-04-07 13:18:50 -07:00
parent d0f2401879
commit b9f8c249e6
15 changed files with 388 additions and 423 deletions

View File

@ -439,8 +439,7 @@ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
CHECK_REQUEST(cx);
AutoValueRooter tvr(cx, v);
*dp = js_ValueToNumber(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
return ValueToNumber(cx, v, dp);
}
JS_PUBLIC_API(JSBool)
@ -455,8 +454,7 @@ JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
CHECK_REQUEST(cx);
AutoValueRooter tvr(cx, v);
*ip = js_ValueToECMAInt32(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
return ValueToECMAInt32(cx, v, (int32_t *)ip);
}
JS_PUBLIC_API(JSBool)
@ -465,8 +463,7 @@ JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
CHECK_REQUEST(cx);
AutoValueRooter tvr(cx, v);
*ip = js_ValueToECMAUint32(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
return ValueToECMAUint32(cx, v, (uint32_t *)ip);
}
JS_PUBLIC_API(JSBool)
@ -475,8 +472,7 @@ JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
CHECK_REQUEST(cx);
AutoValueRooter tvr(cx, v);
*ip = js_ValueToInt32(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
return ValueToInt32(cx, v, (int32_t *)ip);
}
JS_PUBLIC_API(JSBool)
@ -485,8 +481,7 @@ JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
CHECK_REQUEST(cx);
AutoValueRooter tvr(cx, v);
*ip = js_ValueToUint16(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
return ValueToUint16(cx, v, (uint16_t *)ip);
}
JS_PUBLIC_API(JSBool)

View File

@ -196,7 +196,6 @@ static jsuint
ValueIsLength(JSContext *cx, jsval* vp)
{
jsint i;
jsdouble d;
jsuint length;
if (JSVAL_IS_INT(*vp)) {
@ -206,8 +205,8 @@ ValueIsLength(JSContext *cx, jsval* vp)
return (jsuint) i;
}
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
jsdouble d;
if (!ValueToNumber(cx, *vp, &d))
goto error;
if (JSDOUBLE_IS_NaN(d))
@ -246,8 +245,8 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
return true;
}
*lengthp = js_ValueToECMAUint32(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
JS_STATIC_ASSERT(sizeof(jsuint) == sizeof(uint32_t));
return ValueToECMAUint32(cx, tvr.value(), (uint32_t *)lengthp);
}
static JSBool
@ -2014,7 +2013,6 @@ sort_compare(void *arg, const void *a, const void *b, int *result)
CompareArgs *ca = (CompareArgs *) arg;
JSContext *cx = ca->context;
jsval *invokevp, *sp;
jsdouble cmp;
/**
* array_sort deals with holes and undefs on its own and they should not
@ -2036,8 +2034,8 @@ sort_compare(void *arg, const void *a, const void *b, int *result)
if (!js_Invoke(cx, 2, invokevp, 0))
return JS_FALSE;
cmp = js_ValueToNumber(cx, invokevp);
if (JSVAL_IS_NULL(*invokevp))
jsdouble cmp;
if (!ValueToNumber(cx, *invokevp, &cmp))
return JS_FALSE;
/* Clamp cmp to -1, 0, 1. */
@ -2610,7 +2608,6 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
jsval *argv;
JSObject *obj;
jsuint length, begin, end, count, delta, last;
jsdouble d;
JSBool hole;
JSObject *obj2;
@ -2634,8 +2631,8 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
/* Convert the first argument into a starting index. */
d = js_ValueToNumber(cx, argv);
if (JSVAL_IS_NULL(*argv))
jsdouble d;
if (!ValueToNumber(cx, *argv, &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d < 0) {
@ -2655,8 +2652,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
count = delta;
end = length;
} else {
d = js_ValueToNumber(cx, argv);
if (JSVAL_IS_NULL(*argv))
if (!ValueToNumber(cx, *argv, &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d < 0)
@ -2859,7 +2855,6 @@ array_slice(JSContext *cx, uintN argc, jsval *vp)
jsval *argv;
JSObject *nobj, *obj;
jsuint length, begin, end, slot;
jsdouble d;
JSBool hole;
argv = JS_ARGV(cx, vp);
@ -2871,8 +2866,8 @@ array_slice(JSContext *cx, uintN argc, jsval *vp)
end = length;
if (argc > 0) {
d = js_ValueToNumber(cx, &argv[0]);
if (JSVAL_IS_NULL(argv[0]))
jsdouble d;
if (!ValueToNumber(cx, argv[0], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d < 0) {
@ -2885,8 +2880,7 @@ array_slice(JSContext *cx, uintN argc, jsval *vp)
begin = (jsuint)d;
if (argc > 1) {
d = js_ValueToNumber(cx, &argv[1]);
if (JSVAL_IS_NULL(argv[1]))
if (!ValueToNumber(cx, argv[1], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d < 0) {
@ -2956,8 +2950,7 @@ array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, jsval *vp)
jsdouble start;
tosearch = vp[2];
start = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &start))
return JS_FALSE;
start = js_DoubleToInteger(start);
if (start < 0) {

View File

@ -71,6 +71,8 @@
#include "jsobj.h"
#include "jsstr.h"
using namespace js;
/*
* The JS 'Date' object is patterned after the Java 'Date' object.
* Here is an script:
@ -585,13 +587,12 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
{
uintN loop;
jsdouble array[MAXARGS];
jsdouble d;
jsdouble msec_time;
for (loop = 0; loop < MAXARGS; loop++) {
if (loop < argc) {
d = js_ValueToNumber(cx, &argv[loop]);
if (JSVAL_IS_NULL(argv[loop]))
jsdouble d;
if (!ValueToNumber(cx, argv[loop], &d))
return JS_FALSE;
/* return NaN if any arg is not finite */
if (!JSDOUBLE_IS_FINITE(d)) {
@ -1529,8 +1530,8 @@ date_setTime(JSContext *cx, uintN argc, jsval *vp)
return true;
}
jsdouble result = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
jsdouble result;
if (!ValueToNumber(cx, vp[2], &result))
return false;
return SetUTCTime(cx, obj, TIMECLIP(result), vp);
@ -1576,8 +1577,7 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
argv = vp + 2;
for (i = 0; i < argc; i++) {
args[i] = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
if (!ValueToNumber(cx, argv[i], &args[i]))
return false;
if (!JSDOUBLE_IS_FINITE(args[i])) {
SetDateToNaN(cx, obj, vp);
@ -1700,8 +1700,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
argv = vp + 2;
for (i = 0; i < argc; i++) {
args[i] = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
if (!ValueToNumber(cx, argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
SetDateToNaN(cx, obj, vp);
@ -1797,8 +1796,8 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
return true;
}
jsdouble year = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
jsdouble year;
if (!ValueToNumber(cx, vp[2], &year))
return false;
if (!JSDOUBLE_IS_FINITE(year)) {
SetDateToNaN(cx, obj, vp);
@ -2333,8 +2332,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
} else if (argc == 1) {
if (!JSVAL_IS_STRING(argv[0])) {
/* the argument is a millisecond number */
d = js_ValueToNumber(cx, &argv[0]);
if (JSVAL_IS_NULL(argv[0]))
if (!ValueToNumber(cx, argv[0], &d))
return JS_FALSE;
d = TIMECLIP(d);
} else {

View File

@ -44,7 +44,7 @@
#include "jsstdint.h"
#include "jsdtoa.h"
#include "jsprf.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsapi.h"
#include "jsprvtd.h"
#include "jsnum.h"
#include "jsbit.h"

View File

@ -685,7 +685,6 @@ StringToFilename(JSContext *cx, JSString *str)
static JSBool
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
uint32 lineno;
JSString *message, *filename;
JSStackFrame *fp;
@ -745,9 +744,9 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Set the 'lineNumber' property. */
uint32_t lineno;
if (argc > 2) {
lineno = js_ValueToECMAUint32(cx, &argv[2]);
if (JSVAL_IS_NULL(argv[2]))
if (!ValueToECMAUint32(cx, argv[2], &lineno))
return JS_FALSE;
} else {
if (!fp)
@ -826,7 +825,6 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
JSObject *obj;
JSString *name, *message, *filename, *lineno_as_str, *result;
jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
uint32 lineno;
size_t lineno_length, name_length, message_length, filename_length, length;
jschar *chars, *cp;
@ -858,8 +856,8 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
if (!JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]))
return false;
lineno = js_ValueToECMAUint32 (cx, &localroots[2]);
if (JSVAL_IS_NULL(localroots[2]))
uint32_t lineno;
if (!ValueToECMAUint32(cx, localroots[2], &lineno))
return false;
if (lineno != 0) {
@ -1243,7 +1241,6 @@ js_ReportUncaughtException(JSContext *cx)
if (!reportp && exnObject && exnObject->getClass() == &js_ErrorClass) {
const char *filename;
uint32 lineno;
if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2]))
return false;
@ -1264,8 +1261,8 @@ js_ReportUncaughtException(JSContext *cx)
if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
return false;
lineno = js_ValueToECMAUint32 (cx, &roots[4]);
if (JSVAL_IS_NULL(roots[4]))
uint32_t lineno;
if (!ValueToECMAUint32 (cx, roots[4], &lineno))
return false;
reportp = &report;

View File

@ -1896,7 +1896,7 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
};
static JSBool
fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
fun_toStringHelper(JSContext *cx, uint32_t indent, uintN argc, jsval *vp)
{
jsval fval;
JSObject *obj;
@ -1930,8 +1930,7 @@ fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
obj = JSVAL_TO_OBJECT(fval);
if (argc != 0) {
indent = js_ValueToECMAUint32(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToECMAUint32(cx, vp[2], &indent))
return JS_FALSE;
}

View File

@ -1502,34 +1502,21 @@ js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
JS_STATIC_INTERPRET JSBool
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
{
jsval v;
jsdouble d;
v = *vp;
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
} else if (JSVAL_IS_INT(v)) {
d = JSVAL_TO_INT(v);
} else {
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
if (cs->format & JOF_POST) {
double d;
if (!ValueToNumberValue(cx, vp, &d))
return JS_FALSE;
JS_ASSERT(JSVAL_IS_NUMBER(*vp) || *vp == JSVAL_TRUE);
/* Store the result of v conversion back in vp for post increments. */
if ((cs->format & JOF_POST) &&
*vp == JSVAL_TRUE
&& !js_NewNumberInRootedValue(cx, d, vp)) {
return JS_FALSE;
}
(cs->format & JOF_INC) ? ++d : --d;
return js_NewNumberInRootedValue(cx, d, vp2);
}
(cs->format & JOF_INC) ? d++ : d--;
double d;
if (!ValueToNumber(cx, *vp, &d))
return JS_FALSE;
(cs->format & JOF_INC) ? ++d : --d;
if (!js_NewNumberInRootedValue(cx, d, vp2))
return JS_FALSE;
if (!(cs->format & JOF_POST))
*vp = *vp2;
*vp = *vp2;
return JS_TRUE;
}
@ -1994,55 +1981,25 @@ namespace reprmeter {
jsval v_; \
\
v_ = FETCH_OPND(n); \
VALUE_TO_NUMBER(cx, n, v_, d); \
VALUE_TO_NUMBER(cx, v_, d); \
JS_END_MACRO
#define FETCH_INT(cx, n, i) \
JS_BEGIN_MACRO \
jsval v_; \
\
v_= FETCH_OPND(n); \
if (JSVAL_IS_INT(v_)) { \
i = JSVAL_TO_INT(v_); \
} else { \
i = js_ValueToECMAInt32(cx, &regs.sp[n]); \
if (JSVAL_IS_NULL(regs.sp[n])) \
goto error; \
} \
if (!ValueToECMAInt32(cx, regs.sp[n], &i)) \
goto error; \
JS_END_MACRO
#define FETCH_UINT(cx, n, ui) \
JS_BEGIN_MACRO \
jsval v_; \
\
v_= FETCH_OPND(n); \
if (JSVAL_IS_INT(v_)) { \
ui = (uint32) JSVAL_TO_INT(v_); \
} else { \
ui = js_ValueToECMAUint32(cx, &regs.sp[n]); \
if (JSVAL_IS_NULL(regs.sp[n])) \
goto error; \
} \
if (!ValueToECMAUint32(cx, regs.sp[n], &ui)) \
goto error; \
JS_END_MACRO
/*
* Optimized conversion macros that test for the desired type in v before
* homing sp and calling a conversion function.
*/
#define VALUE_TO_NUMBER(cx, n, v, d) \
#define VALUE_TO_NUMBER(cx, v, d) \
JS_BEGIN_MACRO \
JS_ASSERT(v == regs.sp[n]); \
if (JSVAL_IS_INT(v)) { \
d = (jsdouble)JSVAL_TO_INT(v); \
} else if (JSVAL_IS_DOUBLE(v)) { \
d = *JSVAL_TO_DOUBLE(v); \
} else { \
d = js_ValueToNumber(cx, &regs.sp[n]); \
if (JSVAL_IS_NULL(regs.sp[n])) \
goto error; \
JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[n]) || \
regs.sp[n] == JSVAL_TRUE); \
} \
if (!ValueToNumber(cx, v, &d)) \
goto error; \
JS_END_MACRO
#define POP_BOOLEAN(cx, v, b) \
@ -2316,7 +2273,7 @@ js_Interpret(JSContext *cx)
JSProperty *prop;
JSScopeProperty *sprop;
JSString *str, *str2;
jsint i, j;
int32_t i, j;
jsdouble d, d2;
JSClass *clasp;
JSFunction *fun;

View File

@ -56,6 +56,8 @@
#include "jslibmath.h"
#include "jsobj.h"
using namespace js;
#ifndef M_E
#define M_E 2.7182818284590452354
#endif
@ -110,8 +112,7 @@ math_abs(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = fabs(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -126,8 +127,7 @@ math_acos(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
#if defined(SOLARIS) && defined(__GNUC__)
if (x < -1 || 1 < x) {
@ -148,8 +148,7 @@ math_asin(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
#if defined(SOLARIS) && defined(__GNUC__)
if (x < -1 || 1 < x) {
@ -170,8 +169,7 @@ math_atan(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = atan(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -216,11 +214,9 @@ math_atan2(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
y = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &y))
return JS_FALSE;
return js_NewNumberInRootedValue(cx, math_atan2_kernel (x, y), vp);
}
@ -244,8 +240,7 @@ js_math_ceil(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = math_ceil_kernel(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -260,8 +255,7 @@ math_cos(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = cos(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -276,8 +270,7 @@ math_exp(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
#ifdef _WIN32
if (!JSDOUBLE_IS_NaN(x)) {
@ -304,8 +297,7 @@ js_math_floor(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = floor(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -320,8 +312,7 @@ math_log(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
#if defined(SOLARIS) && defined(__GNUC__)
if (x < 0) {
@ -346,8 +337,7 @@ js_math_max(JSContext *cx, uintN argc, jsval *vp)
}
argv = vp + 2;
for (i = 0; i < argc; i++) {
x = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
if (!ValueToNumber(cx, argv[i], &x))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(x)) {
*vp = cx->runtime->NaNValue;
@ -376,8 +366,7 @@ js_math_min(JSContext *cx, uintN argc, jsval *vp)
}
argv = vp + 2;
for (i = 0; i < argc; i++) {
x = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
if (!ValueToNumber(cx, argv[i], &x))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(x)) {
*vp = cx->runtime->NaNValue;
@ -402,11 +391,9 @@ math_pow(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
y = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &y))
return JS_FALSE;
/*
* Because C99 and ECMA specify different behavior for pow(),
@ -501,8 +488,7 @@ js_math_round(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = js_copysign(floor(x + 0.5), x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -517,8 +503,7 @@ math_sin(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = sin(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -533,8 +518,7 @@ math_sqrt(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = sqrt(x);
return js_NewNumberInRootedValue(cx, z, vp);
@ -549,8 +533,7 @@ math_tan(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
z = tan(x);
return js_NewNumberInRootedValue(cx, z, vp);

View File

@ -105,15 +105,13 @@ JS_STATIC_ASSERT(uintptr_t(PTRDIFF_MAX) + uintptr_t(1) == uintptr_t(PTRDIFF_MIN)
static JSBool
num_isNaN(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x;
if (argc == 0) {
*vp = JSVAL_TRUE;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
jsdouble x;
if (!ValueToNumber(cx, vp[2], &x))
return false;
*vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
return JS_TRUE;
}
@ -121,14 +119,12 @@ num_isNaN(JSContext *cx, uintN argc, jsval *vp)
static JSBool
num_isFinite(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x;
if (argc == 0) {
*vp = JSVAL_FALSE;
return JS_TRUE;
}
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
jsdouble x;
if (!ValueToNumber(cx, vp[2], &x))
return JS_FALSE;
*vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
return JS_TRUE;
@ -178,7 +174,6 @@ ParseFloat(JSContext* cx, JSString* str)
static JSBool
num_parseInt(JSContext *cx, uintN argc, jsval *vp)
{
jsint radix;
JSString *str;
jsdouble d;
const jschar *bp, *end, *ep;
@ -187,9 +182,9 @@ num_parseInt(JSContext *cx, uintN argc, jsval *vp)
*vp = cx->runtime->NaNValue;
return JS_TRUE;
}
int32_t radix;
if (argc > 1) {
radix = js_ValueToECMAInt32(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToECMAInt32(cx, vp[3], &radix))
return JS_FALSE;
} else {
radix = 0;
@ -283,20 +278,10 @@ static JSBool
Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsval v;
jsdouble d;
if (argc != 0) {
d = js_ValueToNumber(cx, &argv[0]);
v = argv[0];
if (JSVAL_IS_NULL(v))
if (!ValueToNumberValue(cx, &argv[0]))
return JS_FALSE;
if (v != JSVAL_TRUE) {
JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
} else {
if (!js_NewNumberInRootedValue(cx, d, &argv[0]))
return JS_FALSE;
v = argv[0];
}
v = argv[0];
} else {
v = JSVAL_ZERO;
}
@ -391,18 +376,17 @@ num_toString(JSContext *cx, uintN argc, jsval *vp)
{
jsval v;
jsdouble d;
jsint base;
JSString *str;
if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
return JS_FALSE;
JS_ASSERT(JSVAL_IS_NUMBER(v));
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
base = 10;
int32_t base = 10;
if (argc != 0 && !JSVAL_IS_VOID(vp[2])) {
base = js_ValueToECMAInt32(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToECMAInt32(cx, vp[2], &base))
return JS_FALSE;
if (base < 2 || base > 36) {
char numBuf[12];
char *numStr = IntToCString(base, 10, numBuf, sizeof numBuf);
@ -571,8 +555,7 @@ num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
precision = 0.0;
oneArgMode = zeroArgMode;
} else {
precision = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &precision))
return JS_FALSE;
precision = js_DoubleToInteger(precision);
if (precision < precisionMin || precision > precisionMax) {
@ -951,24 +934,27 @@ js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
return JS_TRUE;
}
jsdouble
js_ValueToNumber(JSContext *cx, jsval *vp)
namespace js {
jsval
ValueToNumberSlow(JSContext *cx, jsval v, double *out)
{
jsval v;
JSString *str;
jsdouble d;
JSObject *obj;
v = *vp;
JS_ASSERT(!JSVAL_IS_INT(v) && !JSVAL_IS_DOUBLE(v));
goto skip_int_double;
for (;;) {
if (JSVAL_IS_INT(v))
return (jsdouble) JSVAL_TO_INT(v);
if (JSVAL_IS_DOUBLE(v))
return *JSVAL_TO_DOUBLE(v);
if (JSVAL_IS_INT(v)) {
*out = (double)JSVAL_TO_INT(v);
return v;
}
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
return v;
}
skip_int_double:
if (JSVAL_IS_STRING(v)) {
str = JSVAL_TO_STRING(v);
JSString *str = JSVAL_TO_STRING(v);
d = StringToNumberType<jsdouble>(cx, str);
jsdouble d = StringToNumberType<jsdouble>(cx, str);
if (JSDOUBLE_IS_NaN(d))
break;
@ -976,95 +962,91 @@ js_ValueToNumber(JSContext *cx, jsval *vp)
* JSVAL_TRUE indicates that double jsval was never constructed
* for the result.
*/
*vp = JSVAL_TRUE;
return d;
*out = d;
return JSVAL_TRUE;
}
if (JSVAL_IS_BOOLEAN(v)) {
if (JSVAL_TO_BOOLEAN(v)) {
*vp = JSVAL_ONE;
return 1.0;
*out = 1.0;
return JSVAL_ONE;
}
*vp = JSVAL_ZERO;
return 0.0;
*out = 0.0;
return JSVAL_ZERO;
}
if (JSVAL_IS_NULL(v)) {
*vp = JSVAL_ZERO;
return 0.0;
*out = 0.0;
return JSVAL_ZERO;
}
if (JSVAL_IS_VOID(v))
break;
JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
obj = JSVAL_TO_OBJECT(v);
JSObject *obj = JSVAL_TO_OBJECT(v);
/*
* vp roots obj so we cannot use it as an extra root for
* obj->defaultValue result when calling the hook.
* defaultValue has a special contract whereby the callee may not
* assume vp is rooted. Since obj is rooted elsewhere and no GC may
* occur after calling defaultValue, we can just use v.
*/
AutoValueRooter gcr(cx, v);
if (!obj->defaultValue(cx, JSTYPE_NUMBER, gcr.addr()))
obj = NULL;
else
v = *vp = gcr.value();
if (!obj) {
*vp = JSVAL_NULL;
return 0.0;
}
if (!obj->defaultValue(cx, JSTYPE_NUMBER, &v))
return JSVAL_NULL;
if (!JSVAL_IS_PRIMITIVE(v))
break;
}
*vp = cx->runtime->NaNValue;
return js_NaN;
*out = js_NaN;
return cx->runtime->NaNValue;
}
int32
js_ValueToECMAInt32(JSContext *cx, jsval *vp)
bool
ValueToNumberValueSlow(JSContext *cx, jsval *vp, double *out)
{
jsval v;
jsdouble d;
jsval v = *vp = ValueToNumberSlow(cx, *vp, out);
return !JSVAL_IS_NULL(v) &&
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, *out, vp));
}
v = *vp;
if (JSVAL_IS_INT(v))
return JSVAL_TO_INT(v);
bool
ValueToNumberValueSlow(JSContext *cx, jsval *vp)
{
double d;
jsval v = *vp = ValueToNumberSlow(cx, *vp, &d);
return !JSVAL_IS_NULL(v) &&
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, d, vp));
}
bool
ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
*vp = JSVAL_TRUE;
} else {
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
return 0;
*vp = JSVAL_TRUE;
if (JSVAL_IS_NULL(ValueToNumberSlow(cx, v, &d)))
return false;
}
return js_DoubleToECMAInt32(d);
*out = js_DoubleToECMAInt32(d);
return true;
}
uint32
js_ValueToECMAUint32(JSContext *cx, jsval *vp)
bool
ValueToECMAUint32Slow(JSContext *cx, jsval v, uint32_t *out)
{
jsval v;
jsint i;
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
v = *vp;
if (JSVAL_IS_INT(v)) {
i = JSVAL_TO_INT(v);
if (i < 0)
*vp = JSVAL_TRUE;
return (uint32) i;
}
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
*vp = JSVAL_TRUE;
} else {
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
return 0;
*vp = JSVAL_TRUE;
if (JSVAL_IS_NULL(ValueToNumberSlow(cx, v, &d)))
return false;
}
return js_DoubleToECMAUint32(d);
*out = js_DoubleToECMAUint32(d);
return true;
}
} /* namespace js */
uint32
js_DoubleToECMAUint32(jsdouble d)
{
@ -1094,64 +1076,75 @@ js_DoubleToECMAUint32(jsdouble d)
return (uint32) (d >= 0 ? d : d + two32);
}
int32
js_ValueToInt32(JSContext *cx, jsval *vp)
namespace js {
bool
ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
{
jsval v;
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
} else {
jsval v2 = ValueToNumberSlow(cx, v, &d);
if (JSVAL_IS_NULL(v2))
return false;
if (JSVAL_IS_INT(v2)) {
*out = JSVAL_TO_INT(v2);
return true;
}
}
v = *vp;
if (JSVAL_IS_INT(v))
return JSVAL_TO_INT(v);
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
return 0;
if (JSVAL_IS_INT(*vp))
return JSVAL_TO_INT(*vp);
*vp = JSVAL_TRUE;
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
js_ReportValueError(cx, JSMSG_CANT_CONVERT,
JSDVG_SEARCH_STACK, v, NULL);
*vp = JSVAL_NULL;
return 0;
return false;
}
return (int32) floor(d + 0.5); /* Round to nearest */
*out = (int32) floor(d + 0.5); /* Round to nearest */
return true;
}
uint16
js_ValueToUint16(JSContext *cx, jsval *vp)
bool
ValueToUint16Slow(JSContext *cx, jsval v, uint16_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
uint16 u;
jsuint m;
JSBool neg;
d = js_ValueToNumber(cx, vp);
if (JSVAL_IS_NULL(*vp))
return 0;
if (JSVAL_IS_INT(*vp)) {
u = (uint16) JSVAL_TO_INT(*vp);
} else if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
u = (uint16) 0;
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
} else {
u = (uint16) d;
if ((jsdouble) u != d) {
neg = (d < 0);
d = floor(neg ? -d : d);
d = neg ? -d : d;
m = JS_BIT(16);
d = fmod(d, (double) m);
if (d < 0)
d += m;
u = (uint16) d;
jsval v2 = ValueToNumberSlow(cx, v, &d);
if (JSVAL_IS_NULL(v2))
return false;
if (JSVAL_IS_INT(v2)) {
*out = (uint16_t) JSVAL_TO_INT(v2);
return true;
}
}
*vp = INT_TO_JSVAL(u);
return u;
if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
*out = 0;
return true;
}
uint16 u = (uint16) d;
if ((jsdouble)u == d) {
*out = u;
return true;
}
bool neg = (d < 0);
d = floor(neg ? -d : d);
d = neg ? -d : d;
jsuint m = JS_BIT(16);
d = fmod(d, (double) m);
if (d < 0)
d += m;
*out = (uint16_t) d;
return true;
}
} /* namespace js */
JSBool
js_strtod(JSContext *cx, const jschar *s, const jschar *send,
const jschar **ep, jsdouble *dp)

View File

@ -48,6 +48,7 @@
#include <ieeefp.h>
#endif
#include "jsstdint.h"
#include "jsstr.h"
/*
@ -59,8 +60,6 @@
* and pointed to by 32-bit jsvals on the stack and in object properties.
*/
JS_BEGIN_EXTERN_C
/*
* The ARM architecture supports two floating point models: VFP and FPA. When
* targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
@ -187,7 +186,7 @@ js_FinishRuntimeNumberState(JSContext *cx);
/* Initialize the Number class, returning its prototype object. */
extern JSClass js_NumberClass;
extern JSObject *
extern "C" JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj);
/*
@ -224,29 +223,129 @@ js_NumberToString(JSContext *cx, jsdouble d);
extern JSBool JS_FASTCALL
js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb);
namespace js {
/*
* Convert a value to a number. On exit JSVAL_IS_NULL(*vp) iff there was an
* error. If on exit JSVAL_IS_NUMBER(*vp), then *vp holds the jsval that
* matches the result. Otherwise *vp is JSVAL_TRUE indicating that the jsval
* for result has to be created explicitly using, for example, the
* js_NewNumberInRootedValue function.
* Convert a value to a number, returning the converted value in 'out' if the
* conversion succeeds. v most be a copy of a rooted jsval.
*/
extern jsdouble
js_ValueToNumber(JSContext *cx, jsval* vp);
JS_ALWAYS_INLINE bool
ValueToNumber(JSContext *cx, jsval v, double *out)
{
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
return true;
}
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
return true;
}
extern jsval ValueToNumberSlow(JSContext *, jsval, double *);
return !JSVAL_IS_NULL(ValueToNumberSlow(cx, v, out));
}
/*
* Convert a value to a number, replacing 'vp' with the converted value and
* returning the value as a double in 'out'. vp must point to a rooted jsval.
*
* N.B. this function will allocate a new double if needed; callers needing
* only a double, not a value, should use ValueToNumber instead.
*/
JS_ALWAYS_INLINE bool
ValueToNumberValue(JSContext *cx, jsval *vp, double *out)
{
jsval v = *vp;
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
return true;
}
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
return true;
}
extern bool ValueToNumberValueSlow(JSContext *, jsval *, double *);
return ValueToNumberValueSlow(cx, vp, out);
}
/*
* Convert a value to a number, replacing 'vp' with the converted value. vp
* must point to a rooted jsval.
*
* N.B. this function will allocate a new double if needed; callers needing
* only a double, not a value, should use ValueToNumber instead.
*/
JS_ALWAYS_INLINE bool
ValueToNumberValue(JSContext *cx, jsval *vp)
{
jsval v = *vp;
if (JSVAL_IS_INT(v))
return true;
if (JSVAL_IS_DOUBLE(v))
return true;
extern bool ValueToNumberValueSlow(JSContext *, jsval *);
return ValueToNumberValueSlow(cx, vp);
}
/*
* Convert a value to an int32 or uint32, according to the ECMA rules for
* ToInt32 and ToUint32. On exit JSVAL_IS_NULL(*vp) iff there was an error. If
* on exit JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result.
* Otherwise *vp is JSVAL_TRUE indicating that the jsval for result has to be
* created explicitly using, for example, the js_NewNumberInRootedValue
* function.
* ToInt32 and ToUint32. Return converted value on success, !ok on failure. v
* must be a copy of a rooted jsval.
*/
extern int32
js_ValueToECMAInt32(JSContext *cx, jsval *vp);
JS_ALWAYS_INLINE bool
ValueToECMAInt32(JSContext *cx, jsval v, int32_t *out)
{
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
return true;
}
extern bool ValueToECMAInt32Slow(JSContext *, jsval, int32_t *);
return ValueToECMAInt32Slow(cx, v, out);
}
extern uint32
js_ValueToECMAUint32(JSContext *cx, jsval *vp);
JS_ALWAYS_INLINE bool
ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *out)
{
if (JSVAL_IS_INT(v)) {
*out = (uint32_t)JSVAL_TO_INT(v);
return true;
}
extern bool ValueToECMAUint32Slow(JSContext *, jsval, uint32_t *);
return ValueToECMAUint32Slow(cx, v, out);
}
/*
* Convert a value to a number, then to an int32 if it fits by rounding to
* nearest. Return converted value on success, !ok on failure. v must be a copy
* of a rooted jsval.
*/
JS_ALWAYS_INLINE bool
ValueToInt32(JSContext *cx, jsval v, int32_t *out)
{
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
return true;
}
extern bool ValueToInt32Slow(JSContext *, jsval, int32_t *);
return ValueToInt32Slow(cx, v, out);
}
/*
* Convert a value to a number, then to a uint16 according to the ECMA rules
* for ToUint16. Return converted value on success, !ok on failure. v must be a
* copy of a rooted jsval.
*/
JS_ALWAYS_INLINE bool
ValueToUint16(JSContext *cx, jsval v, uint16_t *out)
{
if (JSVAL_IS_INT(v)) {
*out = (uint16_t)JSVAL_TO_INT(v);
return true;
}
extern bool ValueToUint16Slow(JSContext *, jsval, uint16_t *);
return ValueToUint16Slow(cx, v, out);
}
} /* namespace js */
/*
* Specialized ToInt32 and ToUint32 converters for doubles.
@ -355,28 +454,9 @@ js_DoubleToECMAInt32(jsdouble d)
#endif
}
extern uint32
uint32
js_DoubleToECMAUint32(jsdouble d);
/*
* Convert a value to a number, then to an int32 if it fits by rounding to
* nearest; but failing with an error report if the double is out of range
* or unordered. On exit JSVAL_IS_NULL(*vp) iff there was an error. If on exit
* JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result. Otherwise
* *vp is JSVAL_TRUE indicating that the jsval for result has to be created
* explicitly using, for example, the js_NewNumberInRootedValue function.
*/
extern int32
js_ValueToInt32(JSContext *cx, jsval *vp);
/*
* Convert a value to a number, then to a uint16 according to the ECMA rules
* for ToUint16. On exit JSVAL_IS_NULL(*vp) iff there was an error, otherwise
* vp is jsval matching the result.
*/
extern uint16
js_ValueToUint16(JSContext *cx, jsval *vp);
/*
* Convert a jsdouble to an integral number, stored in a jsdouble.
* If d is NaN, return 0. If d is an infinity, return it without conversion.
@ -426,9 +506,8 @@ extern JSBool
js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
const jschar **ep, jsint radix, jsdouble *dp);
JS_END_EXTERN_C
namespace js {
template<typename T> struct NumberTraits { };
template<> struct NumberTraits<int32> {
static JS_ALWAYS_INLINE int32 NaN() { return 0; }

View File

@ -766,8 +766,8 @@ END_CASE(JSOP_BITAND)
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else { \
VALUE_TO_NUMBER(cx, -2, lval, d); \
VALUE_TO_NUMBER(cx, -1, rval, d2); \
VALUE_TO_NUMBER(cx, lval, d); \
VALUE_TO_NUMBER(cx, rval, d2); \
cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \
} \
} \
@ -851,8 +851,8 @@ END_CASE(JSOP_BITAND)
str2 = JSVAL_TO_STRING(rval); \
cond = js_EqualStrings(str, str2) OP JS_TRUE; \
} else { \
VALUE_TO_NUMBER(cx, -2, lval, d); \
VALUE_TO_NUMBER(cx, -1, rval, d2); \
VALUE_TO_NUMBER(cx, lval, d); \
VALUE_TO_NUMBER(cx, rval, d2); \
cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \
} \
} \
@ -945,7 +945,7 @@ END_CASE(JSOP_RSH)
BEGIN_CASE(JSOP_URSH)
{
uint32 u;
uint32_t u;
FETCH_UINT(cx, -2, u);
FETCH_INT(cx, -1, j);
@ -996,8 +996,8 @@ BEGIN_CASE(JSOP_ADD)
regs.sp--;
STORE_OPND(-1, STRING_TO_JSVAL(str));
} else {
VALUE_TO_NUMBER(cx, -2, lval, d);
VALUE_TO_NUMBER(cx, -1, rval, d2);
VALUE_TO_NUMBER(cx, lval, d);
VALUE_TO_NUMBER(cx, rval, d2);
d += d2;
regs.sp--;
STORE_NUMBER(cx, -1, d);
@ -1111,15 +1111,8 @@ BEGIN_CASE(JSOP_NEG)
JS_ASSERT(INT_FITS_IN_JSVAL(i));
regs.sp[-1] = INT_TO_JSVAL(i);
} else {
if (JSVAL_IS_DOUBLE(rval)) {
d = *JSVAL_TO_DOUBLE(rval);
} else {
d = js_ValueToNumber(cx, &regs.sp[-1]);
if (JSVAL_IS_NULL(regs.sp[-1]))
goto error;
JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||
regs.sp[-1] == JSVAL_TRUE);
}
if (!ValueToNumber(cx, regs.sp[-1], &d))
goto error;
d = -d;
if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
goto error;
@ -1127,19 +1120,12 @@ BEGIN_CASE(JSOP_NEG)
END_CASE(JSOP_NEG)
BEGIN_CASE(JSOP_POS)
{
rval = FETCH_OPND(-1);
if (!JSVAL_IS_NUMBER(rval)) {
d = js_ValueToNumber(cx, &regs.sp[-1]);
rval = regs.sp[-1];
if (JSVAL_IS_NULL(rval))
goto error;
if (rval == JSVAL_TRUE) {
if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
goto error;
} else {
JS_ASSERT(JSVAL_IS_NUMBER(rval));
}
}
if (!ValueToNumberValue(cx, &regs.sp[-1]))
goto error;
rval = regs.sp[-1];
}
END_CASE(JSOP_POS)
BEGIN_CASE(JSOP_DELNAME)

View File

@ -357,8 +357,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
if (argc > 1) {
d = js_ValueToNumber(cx, &argv[1]);
if (JSVAL_IS_NULL(argv[1]))
if (!ValueToNumber(cx, argv[1], &d))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(d) ||
(mask = (jsint)d) != d ||
@ -774,16 +773,14 @@ str_substring(JSContext *cx, uintN argc, jsval *vp)
NORMALIZE_THIS(cx, vp, str);
if (argc != 0) {
d = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &d))
return JS_FALSE;
length = str->length();
begin = js_DoubleToInteger(d);
if (argc == 1) {
end = length;
} else {
d = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &d))
return JS_FALSE;
end = js_DoubleToInteger(d);
}
@ -951,8 +948,7 @@ str_charAt(JSContext *cx, uintN argc, jsval *vp)
if (argc == 0) {
d = 0.0;
} else {
d = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
}
@ -993,8 +989,7 @@ str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
if (argc == 0) {
d = 0.0;
} else {
d = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
}
@ -1250,8 +1245,8 @@ str_indexOf(JSContext *cx, uintN argc, jsval *vp)
textlen -= start;
}
} else {
jsdouble d = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
jsdouble d;
if (!ValueToNumber(cx, vp[3], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d <= 0) {
@ -1310,8 +1305,7 @@ str_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
else if (j < i)
i = j;
} else {
d = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &d))
return JS_FALSE;
if (!JSDOUBLE_IS_NaN(d)) {
d = js_DoubleToInteger(d);
@ -2187,8 +2181,8 @@ str_split(JSContext *cx, uintN argc, jsval *vp)
uint32 limit = 0; /* Avoid warning. */
bool limited = (argc > 1) && !JSVAL_IS_VOID(vp[3]);
if (limited) {
jsdouble d = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
jsdouble d;
if (!ValueToNumber(cx, vp[3], &d))
return false;
/* Clamp limit between 0 and 1 + string length. */
@ -2250,8 +2244,7 @@ str_substr(JSContext *cx, uintN argc, jsval *vp)
NORMALIZE_THIS(cx, vp, str);
if (argc != 0) {
d = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &d))
return JS_FALSE;
length = str->length();
begin = js_DoubleToInteger(d);
@ -2266,8 +2259,7 @@ str_substr(JSContext *cx, uintN argc, jsval *vp)
if (argc == 1) {
end = length;
} else {
d = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &d))
return JS_FALSE;
end = js_DoubleToInteger(d);
if (end < 0)
@ -2353,8 +2345,7 @@ str_slice(JSContext *cx, uintN argc, jsval *vp)
if (argc != 0) {
double begin, end, length;
begin = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
if (!ValueToNumber(cx, vp[2], &begin))
return JS_FALSE;
begin = js_DoubleToInteger(begin);
length = str->length();
@ -2369,8 +2360,7 @@ str_slice(JSContext *cx, uintN argc, jsval *vp)
if (argc == 1) {
end = length;
} else {
end = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
if (!ValueToNumber(cx, vp[3], &end))
return JS_FALSE;
end = js_DoubleToInteger(end);
if (end < 0) {
@ -2988,26 +2978,30 @@ str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
{
jsval *argv;
uintN i;
uint16 code;
jschar *chars;
JSString *str;
argv = vp + 2;
JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
if (argc == 1 &&
(code = js_ValueToUint16(cx, &argv[0])) < UNIT_STRING_LIMIT) {
str = JSString::unitString(code);
if (!str)
if (argc == 1) {
uint16_t code;
if (!ValueToUint16(cx, argv[0], &code))
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
return JS_TRUE;
if (code < UNIT_STRING_LIMIT) {
str = JSString::unitString(code);
if (!str)
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
return JS_TRUE;
}
argv[0] = INT_TO_JSVAL(code);
}
chars = (jschar *) cx->malloc((argc + 1) * sizeof(jschar));
if (!chars)
return JS_FALSE;
for (i = 0; i < argc; i++) {
code = js_ValueToUint16(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i])) {
uint16_t code;
if (!ValueToUint16(cx, argv[i], &code)) {
cx->free(chars);
return JS_FALSE;
}

View File

@ -8860,11 +8860,10 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond)
}
{
AutoValueRooter tvr(cx, JSVAL_NULL);
*tvr.addr() = l;
lnum = js_ValueToNumber(cx, tvr.addr());
ValueToNumber(cx, tvr.value(), &lnum);
*tvr.addr() = r;
rnum = js_ValueToNumber(cx, tvr.addr());
ValueToNumber(cx, tvr.value(), &rnum);
}
cond = EvalCmp(op, lnum, rnum);
fp = true;

View File

@ -119,10 +119,9 @@ ArrayBuffer::class_constructor(JSContext *cx, JSObject *obj,
return false;
}
int32 nbytes = js_ValueToECMAInt32(cx, &argv[0]);
if (JSVAL_IS_NULL(argv[0]))
int32_t nbytes;
if (!ValueToECMAInt32(cx, argv[0], &nbytes))
return false;
if (nbytes < 0 || !INT_FITS_IN_JSVAL(nbytes)) {
/*
* We're just not going to support arrays that are bigger than what will fit
@ -564,10 +563,8 @@ class TypedArrayTemplate
} else if (JSVAL_IS_PRIMITIVE(*vp)) {
JS_ASSERT(JSVAL_IS_STRING(*vp) || JSVAL_IS_SPECIAL(*vp));
if (JSVAL_IS_STRING(*vp)) {
// note that ValueToNumber will always
// succeed with a string arg
d = js_ValueToNumber(cx, vp);
JS_ASSERT(*vp != JSVAL_NULL);
// note that ValueToNumber will always succeed with a string arg
ValueToNumber(cx, *vp, &d);
} else if (*vp == JSVAL_VOID) {
d = js_NaN;
} else {
@ -720,14 +717,12 @@ class TypedArrayTemplate
return false;
}
} else if (JSVAL_IS_OBJECT(argv[0])) {
int32 byteOffset = -1;
int32 length = -1;
int32_t byteOffset = -1;
int32_t length = -1;
if (argc > 1) {
byteOffset = js_ValueToInt32(cx, &argv[1]);
if (JSVAL_IS_NULL(argv[1]))
if (!ValueToInt32(cx, argv[1], &byteOffset))
return false;
if (byteOffset < 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "1");
@ -736,10 +731,8 @@ class TypedArrayTemplate
}
if (argc > 2) {
length = js_ValueToInt32(cx, &argv[2]);
if (JSVAL_IS_NULL(argv[2]))
if (!ValueToInt32(cx, argv[2], &length))
return false;
if (length < 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "2");
@ -789,12 +782,11 @@ class TypedArrayTemplate
return true;
// these are the default values
int32 begin = 0, end = tarray->length;
int32 length = int32(tarray->length);
int32_t begin = 0, end = tarray->length;
int32_t length = int32(tarray->length);
if (argc > 0) {
begin = js_ValueToInt32(cx, &argv[0]);
if (JSVAL_IS_NULL(argv[0]))
if (!ValueToInt32(cx, argv[0], &begin))
return false;
if (begin < 0) {
begin += length;
@ -805,8 +797,7 @@ class TypedArrayTemplate
}
if (argc > 1) {
end = js_ValueToInt32(cx, &argv[1]);
if (JSVAL_IS_NULL(argv[1]))
if (!ValueToInt32(cx, argv[1], &end))
return false;
if (end < 0) {
end += length;
@ -1001,8 +992,8 @@ class TypedArrayTemplate
return NativeType(*JSVAL_TO_DOUBLE(v));
if (JSVAL_IS_PRIMITIVE(v) && v != JSVAL_HOLE) {
jsdouble dval = js_ValueToNumber(cx, &v);
JS_ASSERT(v != JSVAL_NULL);
jsdouble dval;
ValueToNumber(cx, v, &dval);
return NativeType(dval);
}

View File

@ -49,6 +49,7 @@
#include <signal.h>
#include <locale.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsarena.h"
#include "jsutil.h"
#include "jsprf.h"