XDR block objects so that when we try to XDR a let expression or array comprehension, we don't error out. bug 346019, r=brendan

This commit is contained in:
mrbkap%gmail.com 2006-07-31 22:52:27 +00:00
Родитель 1f16e4ba8f
Коммит bde983d761
7 изменённых файлов: 225 добавлений и 29 удалений

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

@ -79,6 +79,10 @@
#include "jsxml.h"
#endif
#if JS_HAS_XDR
#include "jsxdrapi.h"
#endif
#ifdef JS_THREADSAFE
#define NATIVE_DROP_PROPERTY js_DropProperty
@ -1973,14 +1977,159 @@ block_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
}
#if JS_HAS_XDR
#define NO_PARENT_INDEX (jsatomid)-1
jsatomid
FindObjectAtomIndex(JSAtomMap *map, JSObject *obj)
{
size_t i;
JSAtom *atom;
for (i = 0; i < map->length; i++) {
atom = map->vector[i];
if (ATOM_KEY(atom) == OBJECT_TO_JSVAL(obj))
return i;
}
return NO_PARENT_INDEX;
}
static JSBool
block_xdrObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
jsatomid parentId;
JSAtomMap *atomMap;
JSObject *parent;
uint16 depth, count, i;
uint32 tmp;
JSTempValueRooter tvr;
JSScopeProperty *sprop;
jsid propid;
JSAtom *atom;
int16 shortid;
JSBool ok;
cx = xdr->cx;
atomMap = &xdr->script->atomMap;
if (xdr->mode == JSXDR_ENCODE) {
parent = OBJ_GET_PARENT(cx, *objp);
parentId = FindObjectAtomIndex(atomMap, parent);
depth = OBJ_BLOCK_DEPTH(cx, *objp);
count = OBJ_BLOCK_COUNT(cx, *objp);
tmp = (uint32)(depth << 16) | count;
}
/* First, XDR the parent atomid. */
if (!JS_XDRUint32(xdr, &parentId))
return JS_FALSE;
if (xdr->mode == JSXDR_DECODE) {
*objp = js_NewBlockObject(cx);
if (!*objp)
return JS_FALSE;
/*
* If there's a parent id, then get the parent out of our script's
* atomMap. We know that we XDR block object in outer-to-inner order,
* which means that getting the parent now will work.
*/
if (parentId != NO_PARENT_INDEX) {
atom = js_GetAtom(cx, atomMap, parentId);
JS_ASSERT(ATOM_IS_OBJECT(atom));
parent = ATOM_TO_OBJECT(atom);
OBJ_SET_PARENT(cx, *objp, parent);
}
}
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(*objp), &tvr);
if (!JS_XDRUint32(xdr, &tmp)) {
JS_POP_TEMP_ROOT(cx, &tvr);
return JS_FALSE;
}
if (xdr->mode == JSXDR_DECODE) {
depth = (uint16)(tmp >> 16);
count = (uint16)tmp;
OBJ_SET_BLOCK_DEPTH(cx, *objp, depth);
}
/*
* XDR the block object's properties. We know that there are 'count'
* properties to XDR, stored as id/shortid pairs. We do not XDR any
* non-native properties, only those that the compiler created.
*/
sprop = NULL;
ok = JS_TRUE;
for (i = 0; i < count; i++) {
if (xdr->mode == JSXDR_ENCODE) {
/* Find a property to XDR. */
do {
/* If sprop is NULL, this is the first property. */
sprop = sprop ? sprop->parent : OBJ_SCOPE(*objp)->lastProp;
} while (!(sprop->flags & SPROP_HAS_SHORTID));
JS_ASSERT(sprop->getter == js_BlockClass.getProperty);
propid = sprop->id;
JS_ASSERT(JSID_IS_ATOM(propid));
atom = JSID_TO_ATOM(propid);
shortid = sprop->shortid;
JS_ASSERT(shortid >= 0);
}
/* XDR the real id, then the shortid. */
if (!js_XDRStringAtom(xdr, &atom) ||
!JS_XDRUint16(xdr, (uint16 *)&shortid)) {
ok = JS_FALSE;
break;
}
if (xdr->mode == JSXDR_DECODE) {
if (!js_DefineNativeProperty(cx, *objp, ATOM_TO_JSID(atom),
JSVAL_VOID, NULL, NULL,
JSPROP_ENUMERATE | JSPROP_PERMANENT,
SPROP_HAS_SHORTID, shortid, NULL)) {
ok = JS_FALSE;
break;
}
}
}
JS_POP_TEMP_ROOT(cx, &tvr);
return ok;
}
#else
# define block_xdrObject NULL
#endif
JSClass js_BlockClass = {
"Block",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_CACHED_PROTO(JSProto_Block),
JS_PropertyStub, JS_PropertyStub, block_getProperty, block_setProperty,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
NULL, NULL, NULL, NULL, block_xdrObject, NULL, NULL, NULL
};
JSObject*
js_InitBlockClass(JSContext *cx, JSObject* obj)
{
JSObject *proto;
proto = JS_InitClass(cx, obj, NULL, &js_BlockClass, NULL, 0, NULL,
NULL, NULL, NULL);
if (!proto)
return NULL;
OBJ_SET_PROTO(cx, proto, NULL);
return proto;
}
JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj)
{
@ -4383,8 +4532,6 @@ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
#if JS_HAS_XDR
#include "jsxdrapi.h"
JSBool
js_XDRObject(JSXDRState *xdr, JSObject **objp)
{

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

@ -331,6 +331,9 @@ extern JSBool
js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
uintN argc, jsval *argv, jsval *rval);
extern JSObject*
js_InitBlockClass(JSContext *cx, JSObject* obj);
extern JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj);

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

@ -1443,9 +1443,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return JS_FALSE;
}
for (i = argc, sprop = OBJ_SCOPE(obj)->lastProp; --i >= 0;
for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
sprop = sprop->parent) {
atomv[i] = JSID_TO_ATOM(sprop->id);
if (!(sprop->flags & SPROP_HAS_SHORTID))
continue;
JS_ASSERT(sprop->shortid < argc);
atomv[sprop->shortid] = JSID_TO_ATOM(sprop->id);
}
ok = JS_TRUE;
for (i = 0; i < argc; i++) {

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

@ -38,6 +38,38 @@
#include "jsconfig.h"
#if JS_HAS_SCRIPT_OBJECT
# define SCRIPT_INIT js_InitScriptClass
#else
# define SCRIPT_INIT js_InitNullClass
#endif
#if JS_HAS_XML_SUPPORT
# define XML_INIT js_InitXMLClass
# define NAMESPACE_INIT js_InitNamespaceClass
# define QNAME_INIT js_InitQNameClass
# define ANYNAME_INIT js_InitAnyNameClass
# define ATTRIBUTE_INIT js_InitAttributeNameClass
#else
# define XML_INIT js_InitNullClass
# define NAMESPACE_INIT js_InitNullClass
# define QNAME_INIT js_InitNullClass
# define ANYNAME_INIT js_InitNullClass
# define ATTRIBUTE_INIT js_InitNullClass
#endif
#if JS_HAS_GENERATORS
# define GENERATOR_INIT js_InitIteratorClasses
#else
# define GENERATOR_INIT js_InitNullClass
#endif
#if JS_HAS_FILE_OBJECT
# define FILE_INIT js_InitFileClass
#else
# define FILE_INIT js_InitNullClass
#endif
/*
* Enumerator codes in the second column must not change -- they are part of
* the JS XDR API.
@ -53,16 +85,12 @@ JS_PROTO(Math, 7, js_InitMathClass)
JS_PROTO(Number, 8, js_InitNumberClass)
JS_PROTO(String, 9, js_InitStringClass)
JS_PROTO(RegExp, 10, js_InitRegExpClass)
#if JS_HAS_SCRIPT_OBJECT
JS_PROTO(Script, 11, js_InitScriptClass)
#endif
#if JS_HAS_XML_SUPPORT
JS_PROTO(XML, 12, js_InitXMLClass)
JS_PROTO(Namespace, 13, js_InitNamespaceClass)
JS_PROTO(QName, 14, js_InitQNameClass)
JS_PROTO(AnyName, 15, js_InitAnyNameClass)
JS_PROTO(AttributeName, 16, js_InitAttributeNameClass)
#endif
JS_PROTO(Script, 11, SCRIPT_INIT)
JS_PROTO(XML, 12, XML_INIT)
JS_PROTO(Namespace, 13, NAMESPACE_INIT)
JS_PROTO(QName, 14, QNAME_INIT)
JS_PROTO(AnyName, 15, ANYNAME_INIT)
JS_PROTO(AttributeName, 16, ATTRIBUTE_INIT)
JS_PROTO(Error, 17, js_InitExceptionClasses)
JS_PROTO(InternalError, 18, js_InitExceptionClasses)
JS_PROTO(EvalError, 19, js_InitExceptionClasses)
@ -71,12 +99,18 @@ JS_PROTO(ReferenceError, 21, js_InitExceptionClasses)
JS_PROTO(SyntaxError, 22, js_InitExceptionClasses)
JS_PROTO(TypeError, 23, js_InitExceptionClasses)
JS_PROTO(URIError, 24, js_InitExceptionClasses)
#if JS_HAS_GENERATORS
JS_PROTO(Generator, 25, js_InitIteratorClasses)
#endif
JS_PROTO(Generator, 25, GENERATOR_INIT)
JS_PROTO(Iterator, 26, js_InitIteratorClasses)
JS_PROTO(StopIteration, 27, js_InitIteratorClasses)
JS_PROTO(GeneratorExit, 28, js_InitIteratorClasses)
#if JS_HAS_FILE_OBJECT
JS_PROTO(File, 29, js_InitFileClass)
#endif
JS_PROTO(File, 29, FILE_INIT)
JS_PROTO(Block, 30, js_InitBlockClass)
#undef SCRIPT_INIT
#undef XML_INIT
#undef NAMESPACE_INIT
#undef QNAME_INIT
#undef ANYNAME_INIT
#undef ATTRIBUTE_INIT
#undef GENERATOR_INIT
#undef FILE_INIT

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

@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -359,6 +359,9 @@ XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
memset(atoms, 0, (size_t)natoms * sizeof *atoms);
#endif
}
map->vector = atoms;
map->length = natoms;
}
for (i = 0; i != natoms; ++i) {
@ -377,15 +380,15 @@ XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
goto bad;
}
if (xdr->mode == JSXDR_DECODE) {
map->vector = atoms;
map->length = natoms;
}
return JS_TRUE;
bad:
if (xdr->mode == JSXDR_DECODE)
if (xdr->mode == JSXDR_DECODE) {
JS_free(cx, atoms);
map->vector = NULL;
map->length = 0;
}
return JS_FALSE;
}
@ -393,7 +396,7 @@ JSBool
js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
{
JSContext *cx;
JSScript *script, *newscript;
JSScript *script, *newscript, *oldscript;
uint32 length, lineno, depth, magic, nsrcnotes, ntrynotes;
uint32 prologLength, version;
JSBool filenameWasSaved;
@ -504,6 +507,8 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
* in the (DECODE and magic < _4) case must point at a temporary vector
* allocated just below.
*/
oldscript = xdr->script;
xdr->script = script;
if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)) ||
!XDRAtomMap(xdr, &script->atomMap)) {
goto error;
@ -631,6 +636,8 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
tn->length = (ptrdiff_t) catchLength;
tn->catchStart = (ptrdiff_t) catchStart;
}
xdr->script = oldscript;
return JS_TRUE;
error:

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

@ -233,6 +233,7 @@ JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
xdr->numclasses = xdr->maxclasses = 0;
xdr->reghash = NULL;
xdr->userdata = NULL;
xdr->script = NULL;
}
JS_PUBLIC_API(JSXDRState *)

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

@ -114,6 +114,7 @@ struct JSXDRState {
uintN maxclasses;
void *reghash;
void *userdata;
JSScript *script;
};
extern JS_PUBLIC_API(void)