bug=415455 r=brendan a1.9=blocking1.9

This commit is contained in:
igor@mir2.org 2008-03-06 13:40:43 -08:00
parent 073f703ffd
commit 4c7eb5780c
9 changed files with 168 additions and 77 deletions

View File

@ -207,11 +207,11 @@ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
return JS_FALSE;
break;
case 'i':
if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
return JS_FALSE;
break;
case 'u':
if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
return JS_FALSE;
break;
case 'j':
@ -548,15 +548,25 @@ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
JS_PUBLIC_API(JSBool)
JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
{
JSTempValueRooter tvr;
CHECK_REQUEST(cx);
return js_ValueToECMAInt32(cx, v, ip);
JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
*ip = js_ValueToECMAInt32(cx, &tvr.u.value);
JS_POP_TEMP_ROOT(cx, &tvr);
return tvr.u.value != JSVAL_NULL;
}
JS_PUBLIC_API(JSBool)
JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
{
JSTempValueRooter tvr;
CHECK_REQUEST(cx);
return js_ValueToECMAUint32(cx, v, ip);
JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
*ip = js_ValueToECMAUint32(cx, &tvr.u.value);
JS_POP_TEMP_ROOT(cx, &tvr);
return tvr.u.value != JSVAL_NULL;
}
JS_PUBLIC_API(JSBool)

View File

@ -234,15 +234,12 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
if (ok) {
/*
* Short-circuit, because js_ValueToECMAUint32 fails when called
* during init time.
*/
if (JSVAL_IS_INT(tvr.u.value)) {
i = JSVAL_TO_INT(tvr.u.value);
*lengthp = (jsuint)i; /* jsuint cast does ToUint32 */
} else {
ok = js_ValueToECMAUint32(cx, tvr.u.value, (uint32 *)lengthp);
*lengthp = js_ValueToECMAUint32(cx, &tvr.u.value);
ok = (tvr.u.value != JSVAL_NULL);
}
}
JS_POP_TEMP_ROOT(cx, &tvr);

View File

@ -793,7 +793,8 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* Set the 'lineNumber' property. */
if (argc > 2) {
if (!js_ValueToECMAUint32(cx, argv[2], &lineno))
lineno = js_ValueToECMAUint32(cx, &argv[2]);
if (argv[2] == JSVAL_NULL)
return JS_FALSE;
} else {
if (!fp)
@ -909,8 +910,11 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
goto out;
localroots[1] = STRING_TO_JSVAL(filename);
ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]) &&
js_ValueToECMAUint32 (cx, localroots[2], &lineno);
ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]);
if (!ok)
goto out;
lineno = js_ValueToECMAUint32 (cx, &localroots[2]);
ok = (localroots[2] != JSVAL_NULL);
if (!ok)
goto out;
@ -1339,7 +1343,8 @@ js_ReportUncaughtException(JSContext *cx)
ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]);
if (!ok)
goto out;
ok = js_ValueToECMAUint32 (cx, roots[4], &lineno);
lineno = js_ValueToECMAUint32 (cx, &roots[4]);
ok = (roots[4] != JSVAL_NULL);
if (!ok)
goto out;

View File

@ -1454,8 +1454,11 @@ fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
}
obj = JSVAL_TO_OBJECT(fval);
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
return JS_FALSE;
if (argc != 0) {
indent = js_ValueToECMAUint32(cx, &vp[2]);
if (vp[2] == JSVAL_NULL)
return JS_FALSE;
}
JS_ASSERT(JS_ObjectIsFunction(cx, obj));
fun = GET_FUNCTION_PRIVATE(cx, obj);

View File

@ -2222,44 +2222,36 @@ js_DumpOpMeters()
#define STORE_NUMBER(cx, n, d) \
JS_BEGIN_MACRO \
jsint i_; \
jsval v_; \
\
if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) { \
v_ = INT_TO_JSVAL(i_); \
sp[n] = INT_TO_JSVAL(i_); \
} else { \
SAVE_SP_AND_PC(fp); \
if (!js_NewDoubleValue(cx, d, &v_)) \
if (!js_NewDoubleValue(cx, d, &sp[n])) \
goto error; \
} \
STORE_OPND(n, v_); \
JS_END_MACRO
#define STORE_INT(cx, n, i) \
JS_BEGIN_MACRO \
jsval v_; \
\
if (INT_FITS_IN_JSVAL(i)) { \
v_ = INT_TO_JSVAL(i); \
sp[n] = INT_TO_JSVAL(i); \
} else { \
SAVE_SP_AND_PC(fp); \
if (!js_NewDoubleValue(cx, (jsdouble)(i), &v_)) \
if (!js_NewDoubleValue(cx, (jsdouble)(i), &sp[n])) \
goto error; \
} \
STORE_OPND(n, v_); \
JS_END_MACRO
#define STORE_UINT(cx, n, u) \
JS_BEGIN_MACRO \
jsval v_; \
\
if ((u) <= JSVAL_INT_MAX) { \
v_ = INT_TO_JSVAL(u); \
sp[n] = INT_TO_JSVAL(u); \
} else { \
SAVE_SP_AND_PC(fp); \
if (!js_NewDoubleValue(cx, (jsdouble)(u), &v_)) \
if (!js_NewDoubleValue(cx, (jsdouble)(u), &sp[n])) \
goto error; \
} \
STORE_OPND(n, v_); \
JS_END_MACRO
#define FETCH_NUMBER(cx, n, d) \
@ -2272,25 +2264,30 @@ js_DumpOpMeters()
#define FETCH_INT(cx, n, i) \
JS_BEGIN_MACRO \
jsval v_ = FETCH_OPND(n); \
jsval v_; \
\
v_= FETCH_OPND(n); \
if (JSVAL_IS_INT(v_)) { \
i = JSVAL_TO_INT(v_); \
} else { \
SAVE_SP_AND_PC(fp); \
if (!js_ValueToECMAInt32(cx, v_, &i)) \
i = js_ValueToECMAInt32(cx, &sp[n]); \
if (sp[n] == JSVAL_NULL) \
goto error; \
} \
JS_END_MACRO
#define FETCH_UINT(cx, n, ui) \
JS_BEGIN_MACRO \
jsval v_ = FETCH_OPND(n); \
jsint i_; \
if (JSVAL_IS_INT(v_) && (i_ = JSVAL_TO_INT(v_)) >= 0) { \
ui = (uint32) i_; \
jsval v_; \
\
v_= FETCH_OPND(n); \
if (JSVAL_IS_INT(v_)) { \
ui = (uint32) JSVAL_TO_INT(v_); \
} else { \
SAVE_SP_AND_PC(fp); \
if (!js_ValueToECMAUint32(cx, v_, &ui)) \
ui = js_ValueToECMAUint32(cx, &sp[n]); \
if (sp[n] == JSVAL_NULL) \
goto error; \
} \
JS_END_MACRO
@ -2449,6 +2446,10 @@ JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
/* Ensure we can share deffun and closure code. */
JS_STATIC_ASSERT(JSOP_DEFFUN_LENGTH == JSOP_CLOSURE_LENGTH);
/* See comments in FETCH_SHIFT macro. */
JS_STATIC_ASSERT((JSVAL_TO_INT(JSVAL_VOID) & 31) == 0);
JSBool
js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
{
@ -3403,19 +3404,15 @@ interrupt:
PUSH_OPND(OBJECT_TO_JSVAL(obj));
END_CASE(JSOP_BINDNAME)
#define INTEGER_OP(OP, EXTRA_CODE) \
#define BITWISE_OP(OP) \
JS_BEGIN_MACRO \
FETCH_INT(cx, -2, i); \
FETCH_INT(cx, -1, j); \
EXTRA_CODE \
i = i OP j; \
sp--; \
STORE_INT(cx, -1, i); \
JS_END_MACRO
#define BITWISE_OP(OP) INTEGER_OP(OP, (void) 0;)
#define SIGNED_SHIFT_OP(OP) INTEGER_OP(OP, j &= 31;)
BEGIN_CASE(JSOP_BITOR)
BITWISE_OP(|);
END_CASE(JSOP_BITOR)
@ -3618,6 +3615,36 @@ interrupt:
#undef EQUALITY_OP
#undef RELATIONAL_OP
/*
* We do not check for JSVAL_VOID here since ToInt32(undefined) == 0
* and (JSVAL_TO_INT(JSVAL_VOID) & 31) == 0. The static assert before
* js_Interpret ensures this.
*/
#define FETCH_SHIFT(shift) \
JS_BEGIN_MACRO \
jsval v_; \
\
v_ = FETCH_OPND(-1); \
if (v_ & JSVAL_INT) { \
shift = JSVAL_TO_INT(v_); \
} else { \
SAVE_SP_AND_PC(fp); \
shift = js_ValueToECMAInt32(cx, &sp[-1]); \
if (sp[-1] == JSVAL_NULL) \
goto error; \
} \
shift &= 31; \
JS_END_MACRO
#define SIGNED_SHIFT_OP(OP) \
JS_BEGIN_MACRO \
FETCH_INT(cx, -2, i); \
FETCH_SHIFT(j); \
i = i OP j; \
sp--; \
STORE_INT(cx, -1, i); \
JS_END_MACRO
BEGIN_CASE(JSOP_LSH)
SIGNED_SHIFT_OP(<<);
END_CASE(JSOP_LSH)
@ -3631,14 +3658,13 @@ interrupt:
uint32 u;
FETCH_UINT(cx, -2, u);
FETCH_INT(cx, -1, j);
u >>= j & 31;
FETCH_SHIFT(j);
u >>= j;
sp--;
STORE_UINT(cx, -1, u);
}
END_CASE(JSOP_URSH)
#undef INTEGER_OP
#undef BITWISE_OP
#undef SIGNED_SHIFT_OP

View File

@ -118,7 +118,8 @@ num_parseInt(JSContext *cx, uintN argc, jsval *vp)
const jschar *bp, *end, *ep;
if (argc > 1) {
if (!js_ValueToECMAInt32(cx, vp[3], &radix))
radix = js_ValueToECMAInt32(cx, &vp[3]);
if (vp[3] == JSVAL_NULL)
return JS_FALSE;
} else {
radix = 0;
@ -262,7 +263,8 @@ num_toString(JSContext *cx, uintN argc, jsval *vp)
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
base = 10;
if (argc != 0 && !JSVAL_IS_VOID(vp[2])) {
if (!js_ValueToECMAInt32(cx, vp[2], &base))
base = js_ValueToECMAInt32(cx, &vp[2]);
if (vp[2] == JSVAL_NULL)
return JS_FALSE;
if (base < 2 || base > 36) {
char numBuf[12];
@ -771,55 +773,92 @@ badstr:
return JS_TRUE;
}
JSBool
js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
int32
js_ValueToECMAInt32(JSContext *cx, jsval *vp)
{
jsval v;
jsdouble d;
if (!js_ValueToNumber(cx, v, &d))
return JS_FALSE;
*ip = js_DoubleToECMAInt32(d);
return JS_TRUE;
v = *vp;
if (JSVAL_IS_INT(v))
return JSVAL_TO_INT(v);
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
} else {
if (!js_ValueToNumber(cx, v, &d)) {
*vp = JSVAL_NULL;
return 0;
}
*vp = JSVAL_ZERO;
}
return js_DoubleToECMAInt32(d);
}
int32
js_DoubleToECMAInt32(jsdouble d)
{
jsdouble two32 = 4294967296.0;
jsdouble two31 = 2147483648.0;
int32 i;
jsdouble two32, two31;
if (!JSDOUBLE_IS_FINITE(d) || d == 0)
if (!JSDOUBLE_IS_FINITE(d))
return 0;
i = (int32) d;
if ((jsdouble) i == d)
return i;
two32 = 4294967296.0;
two31 = 2147483648.0;
d = fmod(d, two32);
d = (d >= 0) ? floor(d) : ceil(d) + two32;
return (int32) (d >= two31 ? d - two32 : d);
}
JSBool
js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
uint32
js_ValueToECMAUint32(JSContext *cx, jsval *vp)
{
jsval v;
jsdouble d;
if (!js_ValueToNumber(cx, v, &d))
return JS_FALSE;
*ip = js_DoubleToECMAUint32(d);
return JS_TRUE;
v = *vp;
if (JSVAL_IS_INT(v))
return (uint32) JSVAL_TO_INT(v);
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
} else {
if (!js_ValueToNumber(cx, v, &d)) {
*vp = JSVAL_NULL;
return 0;
}
*vp = JSVAL_ZERO;
}
return js_DoubleToECMAUint32(d);
}
uint32
js_DoubleToECMAUint32(jsdouble d)
{
int32 i;
JSBool neg;
jsdouble two32 = 4294967296.0;
jsdouble two32;
if (!JSDOUBLE_IS_FINITE(d) || d == 0)
if (!JSDOUBLE_IS_FINITE(d))
return 0;
/*
* We check whether d fits int32, not uint32, as all but the ">>>" bit
* manipulation bytecode stores the result as int, not uint. When the
* result does not fit int jsval, it will be stored as a negative double.
*/
i = (int32) d;
if ((jsdouble) i == d)
return (int32)i;
neg = (d < 0);
d = floor(neg ? -d : d);
d = neg ? -d : d;
two32 = 4294967296.0;
d = fmod(d, two32);
return (uint32) (d >= 0 ? d : d + two32);

View File

@ -204,24 +204,29 @@ extern JSBool
js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
/*
* Convert a value or a double to an int32, according to the ECMA rules
* for ToInt32.
* Convert a value to an int32 or uint32, according to the ECMA rules for
* ToInt32 and ToUint32. On failure the functions sets *vp to JSVAL_NULL. Any
* other value in *vp on exit indicates a success.
*/
extern JSBool
js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
extern int32
js_ValueToECMAInt32(JSContext *cx, jsval *vp);
extern uint32
js_ValueToECMAUint32(JSContext *cx, jsval *vp);
/*
* Specialized ToInt32 and ToUint32 converters for doubles.
*/
extern int32
js_DoubleToECMAInt32(jsdouble d);
extern uint32
js_DoubleToECMAUint32(jsdouble d);
/*
* Convert a value or a double to a uint32, according to the ECMA rules
* for ToUint32.
*/
extern JSBool
js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
extern uint32
js_DoubleToECMAUint32(jsdouble d);
/*
* Convert a value to a number, then to an int32 if it fits by rounding to

View File

@ -110,8 +110,11 @@ script_toSource(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
indent = 0;
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
return JS_FALSE;
if (argc != 0) {
indent = js_ValueToECMAUint32(cx, &vp[2]);
if (vp[2] == JSVAL_NULL)
return JS_FALSE;
}
script = (JSScript *) JS_GetPrivate(cx, obj);
@ -166,8 +169,11 @@ script_toString(JSContext *cx, uintN argc, jsval *vp)
JSString *str;
indent = 0;
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
return JS_FALSE;
if (argc != 0) {
indent = js_ValueToECMAUint32(cx, &vp[2]);
if (vp[2] == JSVAL_NULL)
return JS_FALSE;
}
obj = JS_THIS_OBJECT(cx, vp);
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))

View File

@ -1932,7 +1932,7 @@ GetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip)
{
jsval v;
return GetXMLSetting(cx, name, &v) && js_ValueToECMAUint32(cx, v, uip);
return GetXMLSetting(cx, name, &v) && JS_ValueToECMAUint32(cx, v, uip);
}
static JSBool