Bug 670759 - Add GlobalObject::createBlankPrototype to abstract creation of prototype objects other than Object.prototype. r=bhackett

This commit is contained in:
Jeff Walden 2011-06-13 11:52:45 -07:00
parent 312831a434
commit 16572ce292
4 changed files with 52 additions and 49 deletions

View File

@ -814,33 +814,28 @@ static JSFunctionSpec regexp_methods[] = {
};
JSObject *
js_InitRegExpClass(JSContext *cx, JSObject *global)
js_InitRegExpClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(global->isGlobal());
JS_ASSERT(global->isNative());
JS_ASSERT(obj->isNative());
/* Create and initialize RegExp.prototype. */
JSObject *objectProto;
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
return NULL;
JS_ASSERT(objectProto);
GlobalObject *global = obj->asGlobal();
JSObject *proto = NewObject<WithProto::Class>(cx, &js_RegExpClass, objectProto, global);
JSObject *proto = global->createBlankPrototype(cx, &js_RegExpClass);
if (!proto)
return NULL;
AlreadyIncRefed<RegExp> re = RegExp::create(cx, cx->runtime->emptyString, 0, NULL);
if (!re)
return NULL;
#ifdef DEBUG
assertSameCompartment(cx, proto, re->compartment);
#endif
/*
* Associate the empty regular expression with RegExp.prototype, and define
* the initial non-method properties of any regular expression instance.
* These must be added before methods to preserve slot layout.
*/
#ifdef DEBUG
assertSameCompartment(cx, proto, re->compartment);
#endif
if (!proto->initRegExp(cx, re.get()))
return NULL;
@ -882,17 +877,6 @@ js_InitRegExpClass(JSContext *cx, JSObject *global)
return NULL;
}
/*
* Make sure proto's emptyShape is available to be shared by objects of
* this class. JSObject::emptyShape is a one-slot cache. If we omit this,
* some other class could snap it up. (The risk is particularly great for
* Object.prototype.)
*
* All callers of JSObject::initSharingEmptyShape depend on this.
*/
if (!proto->getEmptyShape(cx, &js_RegExpClass, FINALIZE_OBJECT0))
return NULL;
/* Install the fully-constructed RegExp and RegExp.prototype in global. */
if (!DefineConstructorAndPrototype(cx, global, JSProto_RegExp, ctor, proto))
return NULL;

View File

@ -3163,24 +3163,13 @@ StringObject::assignInitialShape(JSContext *cx)
}
JSObject *
js_InitStringClass(JSContext *cx, JSObject *global)
js_InitStringClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(global->isGlobal());
JS_ASSERT(global->isNative());
JS_ASSERT(obj->isNative());
/*
* Define escape/unescape, the URI encode/decode functions, and maybe
* uneval on the global object.
*/
if (!JS_DefineFunctions(cx, global, string_functions))
return NULL;
GlobalObject *global = obj->asGlobal();
/* Create and initialize String.prototype. */
JSObject *objectProto;
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
return NULL;
JSObject *proto = NewObject<WithProto::Class>(cx, &js_StringClass, objectProto, global);
JSObject *proto = global->createBlankPrototype(cx, &js_StringClass);
if (!proto || !proto->asString()->init(cx, cx->runtime->emptyString))
return NULL;
@ -3214,21 +3203,17 @@ js_InitStringClass(JSContext *cx, JSObject *global)
proto->brand(cx);
ctor->brand(cx);
/*
* Make sure proto's emptyShape is available to be shared by String
* objects. JSObject::emptyShape is a one-slot cache. If we omit this, some
* other class could snap it up. (The risk is particularly great for
* Object.prototype.)
*
* All callers of JSObject::initSharingEmptyShape depend on this.
*/
if (!proto->getEmptyShape(cx, &js_StringClass, FINALIZE_OBJECT0))
return NULL;
/* Install the fully-constructed String and String.prototype. */
if (!DefineConstructorAndPrototype(cx, global, JSProto_String, ctor, proto))
return NULL;
/*
* Define escape/unescape, the URI encode/decode functions, and maybe
* uneval on the global object.
*/
if (!JS_DefineFunctions(cx, global, string_functions))
return NULL;
return proto;
}

View File

@ -202,4 +202,28 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
return !v.isFalse();
}
JSObject *
GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
{
JS_ASSERT(clasp != &js_ObjectClass);
JS_ASSERT(clasp != &js_FunctionClass);
JSObject *objectProto;
if (!js_GetClassPrototype(cx, this, JSProto_Object, &objectProto))
return NULL;
JSObject *proto = NewNonFunction<WithProto::Given>(cx, clasp, objectProto, this);
if (!proto)
return NULL;
/*
* Supply the created prototype object with an empty shape for the benefit
* of callers of JSObject::initSharingEmptyShape.
*/
if (!proto->getEmptyShape(cx, clasp, gc::FINALIZE_OBJECT0))
return NULL;
return proto;
}
} // namespace js

View File

@ -111,6 +111,16 @@ class GlobalObject : public ::JSObject {
public:
static GlobalObject *create(JSContext *cx, Class *clasp);
/*
* Create an object to serve as [[Prototype]] for instances of the given
* class, using |Object.prototype| as its [[Prototype]]. Users creating
* prototype objects with particular internal structure (e.g. reserved
* slots guaranteed to contain values of particular types) must immediately
* complete the minimal initialization to make the returned object safe to
* touch.
*/
JSObject *createBlankPrototype(JSContext *cx, js::Class *clasp);
void setThrowTypeError(JSFunction *fun) {
Value &v = getSlotRef(THROWTYPEERROR);
// Our bootstrapping code is currently too convoluted to correctly and