BUG 321985: During xdr decoding of atoms avoid creation of JSString for

the already existing atoms. r=brendan
This commit is contained in:
igor%mir2.org 2006-02-14 09:33:45 +00:00
Родитель ba9071ed84
Коммит 6997c32ab1
8 изменённых файлов: 324 добавлений и 185 удалений

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

@ -904,7 +904,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
return protos[0];
}
const JSErrorFormatString*
const JSErrorFormatString*
js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale, const uintN errorNumber)
{
const JSErrorFormatString *errorString = NULL;
@ -934,6 +934,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
JSErrNum errorNumber;
JSExnType exn;
JSBool ok;
JSAtom *errAtom;
JSObject *errProto, *errObject;
JSString *messageStr, *filenameStr;
uintN lineno;
@ -984,12 +985,23 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
if (!ok)
goto out;
/*
* FIXME: Can runtime->atomState->lazy.nameErrorAtom be used here instead
* of atomizing name?
*/
errAtom = js_Atomize(cx, exceptions[exn].name,
strlen(exceptions[exn].name), 0);
if (!errAtom) {
ok = JS_FALSE;
goto out;
}
/*
* Try to get an appropriate prototype by looking up the corresponding
* exception constructor name in the scope chain of the current context's
* top stack frame, or in the global object if no frame is active.
*/
ok = js_GetClassPrototype(cx, exceptions[exn].name, &errProto);
ok = js_GetClassPrototype(cx, NULL, errAtom, &errProto);
if (!ok)
goto out;

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

@ -1185,13 +1185,12 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
JSFunction *fun;
JSString *atomstr;
uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
uint32 flagsword; /* originally only flags was JS_XDRUint8'd */
uint16 extraUnused; /* variable for no longer used field */
char *propname;
JSAtom *propAtom;
JSScopeProperty *sprop;
uint32 userid; /* NB: holds a signed int-tagged jsval */
JSAtom *atom;
uintN i, n, dupflag;
uint32 type;
#ifdef DEBUG
@ -1214,18 +1213,21 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
JS_GetFunctionName(fun));
return JS_FALSE;
}
atomstr = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
nullAtom = !fun->atom;
flagsword = ((uint32)fun->u.i.nregexps << 16) | fun->flags;
extraUnused = 0;
} else {
fun = js_NewFunction(cx, NULL, NULL, 0, 0, NULL, NULL);
if (!fun)
return JS_FALSE;
atomstr = NULL;
}
if (!JS_XDRStringOrNull(xdr, &atomstr) ||
!JS_XDRUint16(xdr, &fun->nargs) ||
if (!JS_XDRUint32(xdr, &nullAtom))
return JS_FALSE;
if (!nullAtom && !js_XDRStringAtom(xdr, &fun->atom))
return JS_FALSE;
if (!JS_XDRUint16(xdr, &fun->nargs) ||
!JS_XDRUint16(xdr, &extraUnused) ||
!JS_XDRUint16(xdr, &fun->u.i.nvars) ||
!JS_XDRUint32(xdr, &flagsword)) {
@ -1275,12 +1277,10 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
? JSXDR_FUNCONST
: JSXDR_FUNVAR;
userid = INT_TO_JSVAL(sprop->shortid);
/* XXX lossy conversion, need new XDR version for ECMAv3 */
propname = JS_GetStringBytes(ATOM_TO_STRING(JSID_TO_ATOM(sprop->id)));
if (!propname ||
!JS_XDRUint32(xdr, &type) ||
propAtom = JSID_TO_ATOM(sprop->id);
if (!JS_XDRUint32(xdr, &type) ||
!JS_XDRUint32(xdr, &userid) ||
!JS_XDRCString(xdr, &propname)) {
!js_XDRCStringAtom(xdr, &propAtom)) {
if (mark)
JS_ARENA_RELEASE(&cx->tempPool, mark);
return JS_FALSE;
@ -1296,7 +1296,7 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
if (!JS_XDRUint32(xdr, &type) ||
!JS_XDRUint32(xdr, &userid) ||
!JS_XDRCString(xdr, &propname)) {
!js_XDRCStringAtom(xdr, &propAtom)) {
return JS_FALSE;
}
JS_ASSERT(type == JSXDR_FUNARG || type == JSXDR_FUNVAR ||
@ -1315,18 +1315,15 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
getter = NULL;
setter = NULL;
}
atom = js_Atomize(cx, propname, strlen(propname), 0);
JS_free(cx, propname);
if (!atom)
return JS_FALSE;
/* Flag duplicate argument if atom is bound in fun->object. */
dupflag = SCOPE_GET_PROPERTY(OBJ_SCOPE(fun->object),
ATOM_TO_JSID(atom))
ATOM_TO_JSID(propAtom))
? SPROP_IS_DUPLICATE
: 0;
if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(atom),
if (!js_AddHiddenProperty(cx, fun->object,
ATOM_TO_JSID(propAtom),
getter, setter, SPROP_INVALID_SLOT,
attrs | JSPROP_SHARED,
dupflag | SPROP_HAS_SHORTID,
@ -1346,13 +1343,6 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
fun->u.i.nregexps = (uint16) (flagsword >> 16);
*objp = fun->object;
if (atomstr) {
/* XXX only if this was a top-level function! */
fun->atom = js_AtomizeString(cx, atomstr, 0);
if (!fun->atom)
return JS_FALSE;
}
js_CallNewScriptHook(cx, fun->u.i.script, fun);
}

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

@ -1905,10 +1905,6 @@ js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj)
return map;
}
static JSBool
GetClassPrototype(JSContext *cx, JSObject *scope, const char *name,
JSObject **protop);
static jsval *
AllocSlots(JSContext *cx, jsval *slots, uint32 nslots)
{
@ -1976,6 +1972,7 @@ FreeSlots(JSContext *cx, jsval *slots)
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
{
JSAtom *classAtom;
JSObject *obj;
JSObjectOps *ops;
JSObjectMap *map;
@ -1985,10 +1982,17 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
if (!GetClassPrototype(cx, parent, clasp->name, &proto))
classAtom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!classAtom)
return NULL;
if (!proto && !GetClassPrototype(cx, parent, js_Object_str, &proto))
if (!js_GetClassPrototype(cx, parent, classAtom, &proto))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent,
cx->runtime->atomState.ObjectAtom,
&proto)) {
return NULL;
}
}
/* Always call the class's getObjectOps hook if it has one. */
@ -2078,17 +2082,12 @@ bad:
}
JSBool
js_FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp)
js_FindConstructor(JSContext *cx, JSObject *start, JSAtom *ctorName, jsval *vp)
{
JSAtom *atom;
JSObject *obj, *pobj;
JSProperty *prop;
JSScopeProperty *sprop;
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
if (start || (cx->fp && (start = cx->fp->scopeChain) != NULL)) {
/* Find the topmost object in the scope chain. */
do {
@ -2104,7 +2103,7 @@ js_FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp)
}
JS_ASSERT(OBJ_IS_NATIVE(obj));
if (!js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom),
if (!js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(ctorName),
JSRESOLVE_CLASSNAME, &pobj, &prop)) {
return JS_FALSE;
}
@ -2125,13 +2124,17 @@ JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, uintN argc, jsval *argv)
{
JSAtom *ctorName;
jsval cval, rval;
JSTempValueRooter argtvr, tvr;
JSObject *obj, *ctor;
JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr);
if (!js_FindConstructor(cx, parent, clasp->name, &cval)) {
ctorName = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!ctorName)
return NULL;
if (!js_FindConstructor(cx, parent, ctorName, &cval)) {
JS_POP_TEMP_ROOT(cx, &argtvr);
return NULL;
}
@ -3889,19 +3892,13 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
}
JSBool
js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop)
{
return GetClassPrototype(cx, NULL, name, protop);
}
static JSBool
GetClassPrototype(JSContext *cx, JSObject *scope, const char *name,
JSObject **protop)
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSAtom *classAtom,
JSObject **protop)
{
jsval v;
JSObject *ctor;
if (!js_FindConstructor(cx, scope, name, &v))
if (!js_FindConstructor(cx, scope, classAtom, &v))
return JS_FALSE;
if (JSVAL_IS_FUNCTION(cx, v)) {
ctor = JSVAL_TO_OBJECT(v);
@ -4103,45 +4100,45 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
JSClass *clasp;
const char *className;
JSAtom *classAtom;
uint32 classId, classDef;
JSBool ok;
JSObject *proto;
cx = xdr->cx;
if (xdr->mode == JSXDR_ENCODE) {
/*
* XXX: faster way to get already existing classAtom from objp?
*/
clasp = OBJ_GET_CLASS(cx, *objp);
className = clasp->name;
classId = JS_XDRFindClassIdByName(xdr, className);
classAtom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!classAtom)
return JS_FALSE;
classId = JS_XDRFindClassIdByName(xdr, clasp->name);
classDef = !classId;
if (classDef && !JS_XDRRegisterClass(xdr, clasp, &classId))
return JS_FALSE;
} else {
classDef = 0;
className = NULL;
classAtom = NULL;
clasp = NULL; /* quell GCC overwarning */
}
/* XDR a flag word followed (if true) by the class name. */
if (!JS_XDRUint32(xdr, &classDef))
return JS_FALSE;
if (classDef && !JS_XDRCString(xdr, (char **) &className))
if (classDef && !js_XDRCStringAtom(xdr, &classAtom))
return JS_FALSE;
/* From here on, return through out: to free className if it was set. */
ok = JS_XDRUint32(xdr, &classId);
if (!ok)
goto out;
if (!JS_XDRUint32(xdr, &classId))
return JS_FALSE;
if (xdr->mode != JSXDR_ENCODE) {
if (xdr->mode == JSXDR_DECODE) {
if (classDef) {
ok = GetClassPrototype(cx, NULL, className, &proto);
if (!ok)
goto out;
if (!js_GetClassPrototype(cx, NULL, classAtom, &proto))
return JS_FALSE;
clasp = OBJ_GET_CLASS(cx, proto);
ok = JS_XDRRegisterClass(xdr, clasp, &classId);
if (!ok)
goto out;
if (!JS_XDRRegisterClass(xdr, clasp, &classId))
return JS_FALSE;
} else {
clasp = JS_XDRFindClassById(xdr, classId);
if (!clasp) {
@ -4149,8 +4146,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_FIND_CLASS, numBuf);
ok = JS_FALSE;
goto out;
return JS_FALSE;
}
}
}
@ -4158,14 +4154,9 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
if (!clasp->xdrObject) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_XDR_CLASS, clasp->name);
ok = JS_FALSE;
} else {
ok = clasp->xdrObject(xdr, objp);
return JS_FALSE;
}
out:
if (xdr->mode != JSXDR_ENCODE && className)
JS_free(cx, (void *)className);
return ok;
return clasp->xdrObject(xdr, objp);
}
#endif /* JS_HAS_XDR */

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

@ -306,7 +306,7 @@ extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
extern JSBool
js_FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp);
js_FindConstructor(JSContext *cx, JSObject *start, JSAtom *ctorName, jsval *vp);
extern JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
@ -454,7 +454,8 @@ extern JSBool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
extern JSBool
js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop);
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSAtom *atom,
JSObject **protop);
extern JSBool
js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,

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

@ -325,81 +325,62 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
#if JS_HAS_XDR
static JSBool
XDRAtomListElement(JSXDRState *xdr, JSAtomListElement *ale)
{
jsval value;
jsatomid index;
if (xdr->mode == JSXDR_ENCODE)
value = ATOM_KEY(ALE_ATOM(ale));
index = ALE_INDEX(ale);
if (!JS_XDRUint32(xdr, &index))
return JS_FALSE;
ALE_SET_INDEX(ale, index);
if (!JS_XDRValue(xdr, &value))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
if (!ALE_SET_ATOM(ale, js_AtomizeValue(xdr->cx, value, 0)))
return JS_FALSE;
}
return JS_TRUE;
}
static JSBool
XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
{
uint32 length;
uintN i;
JSBool ok;
JSContext *cx;
uint32 natoms, i, index;
JSAtom **atoms;
cx = xdr->cx;
if (xdr->mode == JSXDR_ENCODE)
length = map->length;
natoms = (uint32)map->length;
if (!JS_XDRUint32(xdr, &length))
if (!JS_XDRUint32(xdr, &natoms))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
JSContext *cx;
void *mark;
JSAtomList al;
JSAtomListElement *ale;
cx = xdr->cx;
mark = JS_ARENA_MARK(&cx->tempPool);
ATOM_LIST_INIT(&al);
for (i = 0; i < length; i++) {
JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
if (!ale ||
!XDRAtomListElement(xdr, ale)) {
if (!ale)
JS_ReportOutOfMemory(cx);
JS_ARENA_RELEASE(&cx->tempPool, mark);
if (xdr->mode == JSXDR_ENCODE) {
atoms = map->vector;
} else {
if (natoms == 0) {
atoms = NULL;
} else {
atoms = (JSAtom **) JS_malloc(cx, (size_t)natoms * sizeof *atoms);
if (!atoms)
return JS_FALSE;
}
ALE_SET_NEXT(ale, al.list);
al.count++;
al.list = ale;
#ifdef DEBUG
memset(atoms, 0, (size_t)natoms * sizeof *atoms);
#endif
}
ok = js_InitAtomMap(cx, map, &al);
JS_ARENA_RELEASE(&cx->tempPool, mark);
return ok;
}
if (xdr->mode == JSXDR_ENCODE) {
JSAtomListElement ale;
for (i = 0; i != natoms; ++i) {
if (xdr->mode == JSXDR_ENCODE)
index = i;
if (!JS_XDRUint32(xdr, &index))
goto bad;
for (i = 0; i < map->length; i++) {
ALE_SET_ATOM(&ale, map->vector[i]);
ALE_SET_INDEX(&ale, i);
if (!XDRAtomListElement(xdr, &ale))
return JS_FALSE;
}
/*
* Assert that, when decoding, the read index is valid and points to
* an unoccupied element of atoms array.
*/
JS_ASSERT(index < natoms);
JS_ASSERT(xdr->mode == JSXDR_ENCODE || !atoms[index]);
if (!js_XDRAtom(xdr, &atoms[index]))
goto bad;
}
if (xdr->mode == JSXDR_DECODE) {
map->vector = atoms;
map->length = natoms;
}
return JS_TRUE;
bad:
if (xdr->mode == JSXDR_DECODE)
JS_free(cx, atoms);
return JS_FALSE;
}
JSBool

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

@ -410,46 +410,60 @@ JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
return JS_XDRCString(xdr, sp);
}
/*
* Convert between a JS (Unicode) string and the XDR representation.
*/
JS_PUBLIC_API(JSBool)
JS_XDRString(JSXDRState *xdr, JSString **strp)
static JSBool
XDRChars(JSXDRState *xdr, jschar *chars, uint32 nchars)
{
uint32 i, len, padlen, nbytes;
jschar *chars = NULL, *raw;
if (xdr->mode == JSXDR_ENCODE)
len = JSSTRING_LENGTH(*strp);
if (!JS_XDRUint32(xdr, &len))
return JS_FALSE;
nbytes = len * sizeof(jschar);
if (xdr->mode == JSXDR_DECODE) {
if (!(chars = (jschar *) JS_malloc(xdr->cx, nbytes + sizeof(jschar))))
return JS_FALSE;
} else {
chars = JSSTRING_CHARS(*strp);
}
uint32 i, padlen, nbytes;
jschar *raw;
nbytes = nchars * sizeof(jschar);
padlen = nbytes % JSXDR_ALIGN;
if (padlen) {
padlen = JSXDR_ALIGN - padlen;
nbytes += padlen;
}
if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
goto bad;
return JS_FALSE;
if (xdr->mode == JSXDR_ENCODE) {
for (i = 0; i < len; i++)
for (i = 0; i != nchars; i++)
raw[i] = JSXDR_SWAB16(chars[i]);
if (padlen)
memset((char *)raw + nbytes - padlen, 0, padlen);
} else if (xdr->mode == JSXDR_DECODE) {
for (i = 0; i < len; i++)
for (i = 0; i != nchars; i++)
chars[i] = JSXDR_SWAB16(raw[i]);
chars[len] = 0;
}
return JS_TRUE;
}
if (!(*strp = JS_NewUCString(xdr->cx, chars, len)))
/*
* Convert between a JS (Unicode) string and the XDR representation.
*/
JS_PUBLIC_API(JSBool)
JS_XDRString(JSXDRState *xdr, JSString **strp)
{
uint32 nchars;
jschar *chars;
if (xdr->mode == JSXDR_ENCODE)
nchars = JSSTRING_LENGTH(*strp);
if (!JS_XDRUint32(xdr, &nchars))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
chars = (jschar *) JS_malloc(xdr->cx, (nchars + 1) * sizeof(jschar));
if (!chars)
return JS_FALSE;
} else {
chars = JSSTRING_CHARS(*strp);
}
if (!XDRChars(xdr, chars, nchars))
goto bad;
if (xdr->mode == JSXDR_DECODE) {
chars[nchars] = 0;
*strp = JS_NewUCString(xdr->cx, chars, nchars);
if (!*strp)
goto bad;
}
return JS_TRUE;
@ -473,18 +487,32 @@ JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
return JS_XDRString(xdr, strp);
}
JS_PUBLIC_API(JSBool)
JS_XDRDouble(JSXDRState *xdr, jsdouble **dp)
static JSBool
XDRDoubleValue(JSXDRState *xdr, jsdouble *dp)
{
jsdpun u;
if (xdr->mode == JSXDR_ENCODE)
u.d = **dp;
u.d = *dp;
if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE)
*dp = u.d;
return JS_TRUE;
}
JS_PUBLIC_API(JSBool)
JS_XDRDouble(JSXDRState *xdr, jsdouble **dpp)
{
jsdouble d;
if (xdr->mode == JSXDR_ENCODE)
d = **dpp;
if (!XDRDoubleValue(xdr, &d))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
*dp = JS_NewDouble(xdr->cx, u.d);
if (!*dp)
*dpp = JS_NewDouble(xdr->cx, d);
if (!*dpp)
return JS_FALSE;
}
return JS_TRUE;
@ -494,22 +522,9 @@ JS_XDRDouble(JSXDRState *xdr, jsdouble **dp)
#define JSVAL_XDRNULL 0x8
#define JSVAL_XDRVOID 0xA
JS_PUBLIC_API(JSBool)
JS_XDRValue(JSXDRState *xdr, jsval *vp)
static JSBool
XDRValueBody(JSXDRState *xdr, uint32 type, jsval *vp)
{
uint32 type;
if (xdr->mode == JSXDR_ENCODE) {
if (JSVAL_IS_NULL(*vp))
type = JSVAL_XDRNULL;
else if (JSVAL_IS_VOID(*vp))
type = JSVAL_XDRVOID;
else
type = JSVAL_TAG(*vp);
}
if (!JS_XDRUint32(xdr, &type))
return JS_FALSE;
switch (type) {
case JSVAL_XDRNULL:
*vp = JSVAL_NULL;
@ -573,6 +588,139 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
return JS_TRUE;
}
JS_PUBLIC_API(JSBool)
JS_XDRValue(JSXDRState *xdr, jsval *vp)
{
uint32 type;
if (xdr->mode == JSXDR_ENCODE) {
if (JSVAL_IS_NULL(*vp))
type = JSVAL_XDRNULL;
else if (JSVAL_IS_VOID(*vp))
type = JSVAL_XDRVOID;
else
type = JSVAL_TAG(*vp);
}
return JS_XDRUint32(xdr, &type) && XDRValueBody(xdr, type, vp);
}
JSBool
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
{
jsval v;
uint32 type;
jsdouble d;
JSAtom *atom;
if (xdr->mode == JSXDR_ENCODE) {
v = ATOM_KEY(*atomp);
return JS_XDRValue(xdr, &v);
}
/*
* Inline JS_XDRValue when decoding to avoid ceation of GC things when
* then corresponding atom already exists. See bug 321985.
*/
if (!JS_XDRUint32(xdr, &type))
return JS_FALSE;
if (type == JSVAL_STRING)
return js_XDRStringAtom(xdr, atomp);
if (type == JSVAL_DOUBLE) {
if (!XDRDoubleValue(xdr, &d))
return JS_FALSE;
atom = js_AtomizeDouble(xdr->cx, d, 0);
} else {
if (!XDRValueBody(xdr, type, &v))
return JS_FALSE;
atom = js_AtomizeValue(xdr->cx, v, 0);
}
if (!atom)
return JS_FALSE;
*atomp = atom;
return JS_TRUE;
}
extern JSBool
js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp)
{
JSString *str;
uint32 nchars;
JSAtom *atom;
JSContext *cx;
void *mark;
jschar *chars;
if (xdr->mode == JSXDR_ENCODE) {
JS_ASSERT(ATOM_IS_STRING(*atomp));
str = ATOM_TO_STRING(*atomp);
return JS_XDRString(xdr, &str);
}
/*
* Inline JS_XDRString when decoding to avoid JSString allocation
* for already existing atoms. See bug 321985.
*/
if (!JS_XDRUint32(xdr, &nchars))
return JS_FALSE;
atom = NULL;
cx = xdr->cx;
mark = JS_ARENA_MARK(&cx->tempPool);
JS_ARENA_ALLOCATE_CAST(chars, jschar *, &cx->tempPool,
nchars * sizeof(jschar));
if (!chars)
JS_ReportOutOfMemory(cx);
else if (XDRChars(xdr, chars, nchars))
atom = js_AtomizeChars(cx, chars, nchars, 0);
JS_ARENA_RELEASE(&cx->tempPool, mark);
if (!atom)
return JS_FALSE;
*atomp = atom;
return JS_TRUE;
}
/*
* FIXME: This performs lossy conversion and we need to switch to
* js_XDRStringAtom while allowing to read older XDR files. See bug 325202.
*/
JSBool
js_XDRCStringAtom(JSXDRState *xdr, JSAtom **atomp)
{
char *bytes;
uint32 nbytes;
JSAtom *atom;
JSContext *cx;
void *mark;
if (xdr->mode == JSXDR_ENCODE) {
JS_ASSERT(ATOM_IS_STRING(*atomp));
bytes = JS_GetStringBytes(ATOM_TO_STRING(*atomp));
return JS_XDRCString(xdr, &bytes);
}
/*
* Inline JS_XDRCString when decoding not to malloc temporary buffer
* just to free it after atomization. See bug 321985.
*/
if (!JS_XDRUint32(xdr, &nbytes))
return JS_FALSE;
atom = NULL;
cx = xdr->cx;
mark = JS_ARENA_MARK(&cx->tempPool);
JS_ARENA_ALLOCATE_CAST(bytes, char *, &cx->tempPool,
nbytes * sizeof *bytes);
if (!bytes)
JS_ReportOutOfMemory(cx);
else if (JS_XDRBytes(xdr, bytes, nbytes))
atom = js_Atomize(cx, bytes, nbytes, 0);
JS_ARENA_RELEASE(&cx->tempPool, mark);
if (!atom)
return JS_FALSE;
*atomp = atom;
return JS_TRUE;
}
JS_PUBLIC_API(JSBool)
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
{

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

@ -189,6 +189,22 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
#define JSXDR_MAGIC_SCRIPT_5 0xdead0005
#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_5
/*
* Library-private functions.
*/
extern JSBool
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
extern JSBool
js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp);
/*
* FIXME: This is non-unicode version of js_XDRStringAtom that performs lossy
* conversion. Do not use it in the new code! See bug 325202.
*/
extern JSBool
js_XDRCStringAtom(JSXDRState *xdr, JSAtom **atomp);
JS_END_EXTERN_C
#endif /* ! jsxdrapi_h___ */

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

@ -1825,7 +1825,7 @@ GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
{
jsval v;
if (!js_FindConstructor(cx, NULL, js_XML_str, &v))
if (!js_FindConstructor(cx, NULL, cx->runtime->atomState.XMLAtom, &v))
return JS_FALSE;
if (!JSVAL_IS_FUNCTION(cx, v)) {
*vp = JSVAL_VOID;