making sure thta TryMethod deals xml objects properly. bug=352846 r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2006-09-19 06:48:25 +00:00
Родитель 0dde5a1339
Коммит 03e8575213
6 изменённых файлов: 86 добавлений и 55 удалений

Просмотреть файл

@ -706,10 +706,6 @@ Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_FALSE;
}
#ifdef GC_MARK_DEBUG
extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
#endif
static JSBool
GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{

Просмотреть файл

@ -164,24 +164,28 @@ ValueIsLength(JSContext *cx, jsval v, jsuint *lengthp)
JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{
JSTempValueRooter tvr;
jsid id;
JSBool ok;
jsint i;
jsval v;
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
return JS_FALSE;
/* Short-circuit, because js_ValueToECMAUint32 fails when
* called during init time.
*/
if (JSVAL_IS_INT(v)) {
i = JSVAL_TO_INT(v);
/* jsuint cast does ToUint32. */
*lengthp = (jsuint)i;
return JS_TRUE;
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);
}
}
return js_ValueToECMAUint32(cx, v, (uint32 *)lengthp);
JS_POP_TEMP_ROOT(cx, &tvr);
return ok;
}
static JSBool
@ -345,17 +349,19 @@ JSBool
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{
JSErrorReporter older;
JSTempValueRooter tvr;
jsid id;
JSBool ok;
jsval v;
older = JS_SetErrorReporter(cx, NULL);
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
ok = OBJ_GET_PROPERTY(cx, obj, id, &v);
ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
JS_SetErrorReporter(cx, older);
if (!ok)
return JS_FALSE;
return ValueIsLength(cx, v, lengthp);
if (ok)
ok = ValueIsLength(cx, tvr.u.value, lengthp);
JS_POP_TEMP_ROOT(cx, &tvr);
return ok;
}
JSBool
@ -491,7 +497,8 @@ array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
const jschar *sepstr;
JSString *str;
JSHashEntry *he;
JSObject *obj2;
JSTempValueRooter tvr;
JSAtom *atom;
int stackDummy;
if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
@ -592,14 +599,14 @@ array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
str = cx->runtime->emptyString;
} else {
if (op == TO_LOCALE_STRING) {
if (!js_ValueToObject(cx, v, &obj2) ||
!js_TryMethod(cx, obj2,
cx->runtime->atomState.toLocaleStringAtom,
0, NULL, &v)) {
str = NULL;
} else {
str = js_ValueToString(cx, v);
}
atom = cx->runtime->atomState.toLocaleStringAtom;
JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
ok = js_ValueToObject(cx, v, &tvr.u.object) &&
js_TryMethod(cx, tvr.u.object, atom, 0, NULL, &v);
JS_POP_TEMP_ROOT(cx, &tvr);
if (!ok)
goto done;
str = js_ValueToString(cx, v);
} else if (op == TO_STRING) {
str = js_ValueToString(cx, v);
} else {
@ -967,15 +974,15 @@ sort_compare(void *arg, const void *a, const void *b, int *result)
}
} else {
jsdouble cmp;
jsval rval, argv[2];
jsval argv[2];
argv[0] = av;
argv[1] = bv;
ok = js_InternalCall(cx,
OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fval)),
fval, 2, argv, &rval);
fval, 2, argv, ca->localroot);
if (ok) {
ok = js_ValueToNumber(cx, rval, &cmp);
ok = js_ValueToNumber(cx, *ca->localroot, &cmp);
/* Clamp cmp to -1, 0, 1. */
if (ok) {

Просмотреть файл

@ -475,14 +475,27 @@ typedef struct JSTempValueRooter JSTempValueRooter;
typedef void
(* JS_DLL_CALLBACK JSTempValueMarker)(JSContext *cx, JSTempValueRooter *tvr);
typedef union JSTempValueUnion {
jsval value;
JSObject *object;
JSTempValueMarker marker;
jsval *array;
} JSTempValueUnion;
/*
* The following allows to reinterpret JSTempValueUnion.object as jsval using
* the tagging property of a generic jsval described below.
*/
JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval));
JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(JSObject *));
/*
* Context-linked stack of temporary GC roots.
*
* If count is -1, then u.value contains the single value to root. If count is
* -2, then u.marker holds a mark hook that is executed to mark the values.
* Otherwise u.array points to a stack-allocated vector of jsvals. Note that
* the vector may have length 0 or 1 for full generality, so we need -1 to
* discriminate the union.
* If count is -1, then u.value contains the single value to root.
* If count is -2, then u.marker holds a mark hook that is executed to mark
* the values.
* If count >= 0, then u.array points to a stack-allocated vector of jsvals.
*
* To root a single GC-thing pointer, which need not be tagged and stored as a
* jsval, use JS_PUSH_SINGLE_TEMP_ROOT. The (jsval)(val) cast works because a
@ -498,16 +511,11 @@ typedef void
* internal API (see further below) instead.
*/
struct JSTempValueRooter {
JSTempValueRooter *down;
jsint count;
union {
jsval value;
jsval *array;
JSTempValueMarker marker;
} u;
JSTempValueRooter *down;
ptrdiff_t count;
JSTempValueUnion u;
};
#define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \
JS_BEGIN_MACRO \
JS_ASSERT((cx)->tempValueRooters != (tvr)); \
@ -525,7 +533,8 @@ struct JSTempValueRooter {
#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \
JS_BEGIN_MACRO \
JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \
(tvr)->count = (cnt); \
JS_ASSERT((ptrdiff_t)(cnt) >= 0); \
(tvr)->count = (ptrdiff_t)(cnt); \
(tvr)->u.array = (arr); \
JS_END_MACRO
@ -536,6 +545,13 @@ struct JSTempValueRooter {
(tvr)->u.marker = (marker_); \
JS_END_MACRO
#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \
JS_BEGIN_MACRO \
JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \
(tvr)->count = -3; \
(tvr)->u.object = (obj); \
JS_END_MACRO
#define JS_POP_TEMP_ROOT(cx,tvr) \
JS_BEGIN_MACRO \
JS_ASSERT((cx)->tempValueRooters == (tvr)); \

Просмотреть файл

@ -2816,6 +2816,7 @@ restart:
} else if (tvr->count == -2) {
tvr->u.marker(cx, tvr);
} else {
JS_ASSERT(tvr->count >= 0);
GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array");
}
}

Просмотреть файл

@ -228,6 +228,9 @@ js_MarkGCThing(JSContext *cx, void *thing);
extern void
js_MarkNamedGCThing(JSContext *cx, void *thing, const char *name);
extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
JS_EXTERN_DATA(void *) js_LiveThingToFind;
#else
# define GC_MARK(cx, thing, name) js_MarkGCThing(cx, thing)

Просмотреть файл

@ -2698,6 +2698,9 @@ js_ValueToString(JSContext *cx, jsval v)
JS_FRIEND_API(JSString *)
js_ValueToSource(JSContext *cx, jsval v)
{
JSTempValueRooter tvr;
JSString *str;
if (JSVAL_IS_STRING(v))
return js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
if (JSVAL_IS_PRIMITIVE(v)) {
@ -2708,14 +2711,19 @@ js_ValueToSource(JSContext *cx, jsval v)
return js_NewStringCopyN(cx, js_negzero_ucNstr, 2, 0);
}
} else {
if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v),
cx->runtime->atomState.toSourceAtom,
0, NULL, &v)) {
return NULL;
}
return js_ValueToString(cx, v);
}
return js_ValueToString(cx, v);
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v),
cx->runtime->atomState.toSourceAtom,
0, NULL, &tvr.u.value)) {
str = NULL;
} else {
str = js_ValueToString(cx, tvr.u.value);
}
JS_POP_TEMP_ROOT(cx, &tvr);
return str;
}
JSHashNumber