Bug 679019 - Make initializing the *Error classes non-generic, and combine their initialization with that of Error. r=jorendorff

--HG--
extra : rebase_source : 209d4099359492862de01a2fcb68290755fae86a
This commit is contained in:
Jeff Walden 2011-05-09 13:06:52 -07:00
parent 6b7ecb06cb
commit 8f3d489239
3 changed files with 51 additions and 59 deletions

View File

@ -1009,25 +1009,18 @@ GetExceptionProtoKey(intN exn)
{
JS_ASSERT(JSEXN_ERR <= exn);
JS_ASSERT(exn < JSEXN_LIMIT);
return (JSProtoKey) (JSProto_Error + exn);
return JSProtoKey(JSProto_Error + exn);
}
static JSObject *
InitErrorClass(JSContext *cx, GlobalObject *global)
InitErrorClass(JSContext *cx, GlobalObject *global, intN type, JSObject &proto)
{
/* Create Error.prototype. */
JSObject *errorProto = global->createBlankPrototype(cx, &js_ErrorClass);
JSProtoKey key = GetExceptionProtoKey(type);
JSAtom *name = cx->runtime->atomState.classAtoms[key];
JSObject *errorProto = global->createBlankPrototypeInheriting(cx, &js_ErrorClass, proto);
if (!errorProto)
return NULL;
/* Now create the Error function. */
JSAtom *name = CLASS_ATOM(cx, Error);
JSFunction *ctor = global->createConstructor(cx, Exception, &js_ErrorClass, name, 1);
if (!ctor)
return NULL;
ctor->setReservedSlot(JSSLOT_ERROR_EXNTYPE, Int32Value(int32(JSEXN_ERR)));
/* Add properties to Error.prototype. */
Value empty = StringValue(cx->runtime->emptyString);
jsid nameId = ATOM_TO_JSID(cx->runtime->atomState.nameAtom);
jsid messageId = ATOM_TO_JSID(cx->runtime->atomState.messageAtom);
@ -1045,14 +1038,16 @@ InitErrorClass(JSContext *cx, GlobalObject *global)
return NULL;
}
/* Create the corresponding constructor. */
JSFunction *ctor = global->createConstructor(cx, Exception, &js_ErrorClass, name, 1);
if (!ctor)
return NULL;
ctor->setReservedSlot(JSSLOT_ERROR_EXNTYPE, Int32Value(int32(type)));
if (!LinkConstructorAndPrototype(cx, ctor, errorProto))
return NULL;
if (!DefinePropertiesAndBrand(cx, errorProto, NULL, exception_methods))
return NULL;
/* Install the fully-constructed Error and Error.prototype. */
if (!DefineConstructorAndPrototype(cx, global, JSProto_Error, ctor, errorProto))
if (!DefineConstructorAndPrototype(cx, global, key, ctor, errorProto))
return NULL;
JS_ASSERT(!errorProto->getPrivate());
@ -1060,36 +1055,6 @@ InitErrorClass(JSContext *cx, GlobalObject *global)
return errorProto;
}
static bool
InitSpecialErrorClass(JSContext *cx, GlobalObject *global, intN type, JSObject &errorProto)
{
JSProtoKey key = GetExceptionProtoKey(type);
JSAtom *atom = cx->runtime->atomState.classAtoms[key];
JSObject *ctor;
JSObject *proto =
DefineConstructorAndPrototype(cx, global, key, atom, &errorProto, &js_ErrorClass,
Exception, 1, NULL, NULL, NULL, NULL, &ctor);
if (!proto)
return false;
JS_ASSERT(proto->getPrivate() == NULL);
ctor->setReservedSlot(JSSLOT_ERROR_EXNTYPE, Int32Value(int32(type)));
/* Add properties to the prototype. */
Value empty = StringValue(cx->runtime->emptyString);
jsid nameId = ATOM_TO_JSID(cx->runtime->atomState.nameAtom);
jsid messageId = ATOM_TO_JSID(cx->runtime->atomState.messageAtom);
jsid fileNameId = ATOM_TO_JSID(cx->runtime->atomState.fileNameAtom);
jsid lineNumberId = ATOM_TO_JSID(cx->runtime->atomState.lineNumberAtom);
return DefineNativeProperty(cx, proto, nameId, StringValue(atom),
PropertyStub, StrictPropertyStub, 0, 0, 0) &&
DefineNativeProperty(cx, proto, messageId, empty,
PropertyStub, StrictPropertyStub, 0, 0, 0) &&
DefineNativeProperty(cx, proto, fileNameId, empty,
PropertyStub, StrictPropertyStub, JSPROP_ENUMERATE, 0, 0) &&
DefineNativeProperty(cx, proto, lineNumberId, Int32Value(0),
PropertyStub, StrictPropertyStub, JSPROP_ENUMERATE, 0, 0);
}
JSObject *
js_InitExceptionClasses(JSContext *cx, JSObject *obj)
{
@ -1098,13 +1063,22 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal();
JSObject *errorProto = InitErrorClass(cx, global);
JSObject *objectProto;
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
return NULL;
/* Initialize the base Error class first. */
JSObject *errorProto = InitErrorClass(cx, global, JSEXN_ERR, *objectProto);
if (!errorProto)
return NULL;
/* |Error.prototype| alone has method properties. */
if (!DefinePropertiesAndBrand(cx, errorProto, NULL, exception_methods))
return NULL;
/* Define all remaining *Error constructors. */
for (intN i = JSEXN_ERR + 1; i < JSEXN_LIMIT; i++) {
if (!InitSpecialErrorClass(cx, global, i, *errorProto))
if (!InitErrorClass(cx, global, i, *errorProto))
return NULL;
}

View File

@ -218,28 +218,40 @@ GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom
return fun;
}
JSObject *
GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
static JSObject *
CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
{
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)
JSObject *blankProto = NewNonFunction<WithProto::Given>(cx, clasp, &proto, &global);
if (!blankProto)
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))
if (!blankProto->getEmptyShape(cx, clasp, gc::FINALIZE_OBJECT0))
return NULL;
return proto;
return blankProto;
}
JSObject *
GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
{
JSObject *objectProto;
if (!js_GetClassPrototype(cx, this, JSProto_Object, &objectProto))
return NULL;
return CreateBlankProto(cx, clasp, *objectProto, *this);
}
JSObject *
GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObject &proto)
{
return CreateBlankProto(cx, clasp, proto, *this);
}
bool

View File

@ -132,6 +132,12 @@ class GlobalObject : public ::JSObject {
*/
JSObject *createBlankPrototype(JSContext *cx, js::Class *clasp);
/*
* Identical to createBlankPrototype, but uses proto as the [[Prototype]]
* of the returned blank prototype.
*/
JSObject *createBlankPrototypeInheriting(JSContext *cx, js::Class *clasp, JSObject &proto);
void setThrowTypeError(JSFunction *fun) {
// Our bootstrapping code is currently too convoluted to correctly and
// confidently assert this.