mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
Initialize classes in reserved slots (bug 561923, r=brendan).
This commit is contained in:
parent
c80c81539f
commit
20213b57cd
@ -1617,13 +1617,11 @@ struct JSExtendedClass {
|
||||
* deleteable, for the most part.
|
||||
*
|
||||
* Implementing this efficiently requires that global objects have classes
|
||||
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS won't break
|
||||
* anything except the ECMA-262 "original prototype value" behavior, which was
|
||||
* broken for years in SpiderMonkey. In other words, without these flags you
|
||||
* get backward compatibility.
|
||||
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
||||
* prevously allowed, but is now an ES5 violation and thus unsupported.
|
||||
*/
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT))
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT * 2))
|
||||
|
||||
/* Fast access to the original value of each standard class's prototype. */
|
||||
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
|
||||
|
@ -3318,6 +3318,55 @@ js_InitObjectClass(JSContext *cx, JSObject *obj)
|
||||
object_props, object_methods, NULL, object_static_methods);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
|
||||
const Value &v, uint32 attrs, bool &named)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(atom);
|
||||
|
||||
if (key != JSProto_Null) {
|
||||
/*
|
||||
* Initializing an actual standard class on a global object. If the
|
||||
* property is not yet present, force it into a new one bound to a
|
||||
* reserved slot. Otherwise, go through the normal property path.
|
||||
*/
|
||||
JS_ASSERT(obj->getClass()->flags & JSCLASS_IS_GLOBAL);
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
||||
JSScope *scope = js_GetMutableScope(cx, obj);
|
||||
if (!scope) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSScopeProperty *sprop = scope->lookup(id);
|
||||
if (!sprop) {
|
||||
uint32 index = JSProto_LIMIT + key;
|
||||
if (!js_SetReservedSlot(cx, obj, index, v)) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 slot = JSSLOT_START(obj->getClass()) + index;
|
||||
sprop = scope->addProperty(cx, id, PropertyStub, PropertyStub,
|
||||
slot, attrs, 0, 0);
|
||||
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
if (!sprop)
|
||||
return false;
|
||||
|
||||
named = true;
|
||||
return true;
|
||||
}
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
}
|
||||
|
||||
named = obj->defineProperty(cx, id, v, PropertyStub, PropertyStub, attrs);
|
||||
return named;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
Class *clasp, Native constructor, uintN nargs,
|
||||
@ -3326,8 +3375,8 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSProtoKey key;
|
||||
JSBool named;
|
||||
JSFunction *fun;
|
||||
bool named = false;
|
||||
|
||||
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
|
||||
if (!atom)
|
||||
@ -3360,7 +3409,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
return NULL;
|
||||
|
||||
/* After this point, control must exit via label bad or out. */
|
||||
AutoObjectRooter tvr(cx, proto);
|
||||
AutoValueRooter tvr(cx, ObjectOrNullTag(proto));
|
||||
|
||||
JSObject *ctor;
|
||||
if (!constructor) {
|
||||
@ -3370,29 +3419,27 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
* of obj (the global object) is has a reserved slot indexed by key;
|
||||
* and (c) key is not the null key.
|
||||
*/
|
||||
if ((clasp->flags & JSCLASS_IS_ANONYMOUS) &&
|
||||
(obj->getClass()->flags & JSCLASS_IS_GLOBAL) &&
|
||||
key != JSProto_Null) {
|
||||
named = JS_FALSE;
|
||||
} else {
|
||||
named = obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectOrNullTag(proto),
|
||||
PropertyStub, PropertyStub,
|
||||
(clasp->flags & JSCLASS_IS_ANONYMOUS)
|
||||
? JSPROP_READONLY | JSPROP_PERMANENT
|
||||
: 0);
|
||||
if (!named)
|
||||
if (!(clasp->flags & JSCLASS_IS_ANONYMOUS) ||
|
||||
!(obj->getClass()->flags & JSCLASS_IS_GLOBAL) ||
|
||||
key == JSProto_Null)
|
||||
{
|
||||
uint32 attrs = (clasp->flags & JSCLASS_IS_ANONYMOUS)
|
||||
? JSPROP_READONLY | JSPROP_PERMANENT
|
||||
: 0;
|
||||
if (!DefineStandardSlot(cx, obj, key, atom, tvr.value(), attrs, named))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ctor = proto;
|
||||
} else {
|
||||
/* Define the constructor function in obj's scope. */
|
||||
fun = js_DefineFunction(cx, obj, atom, constructor, nargs,
|
||||
JSFUN_STUB_GSOPS);
|
||||
named = (fun != NULL);
|
||||
fun = js_NewFunction(cx, NULL, constructor, nargs, 0, obj, atom);
|
||||
if (!fun)
|
||||
goto bad;
|
||||
|
||||
AutoValueRooter tvr2(cx, FunObjTag(*fun));
|
||||
if (!DefineStandardSlot(cx, obj, key, atom, tvr2.value(), 0, named))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Remember the class this function is a constructor for so that
|
||||
* we know to create an object of this class when we call the
|
||||
|
@ -205,7 +205,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
||||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 63)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 64)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
Loading…
Reference in New Issue
Block a user