зеркало из https://github.com/mozilla/gecko-dev.git
BUG 321985: During xdr decoding of atoms avoid creation of JSString for
the already existing atoms. r=brendan
This commit is contained in:
Родитель
ba9071ed84
Коммит
6997c32ab1
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче