зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
1f16e4ba8f
Коммит
bde983d761
155
js/src/jsobj.c
155
js/src/jsobj.c
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче