From 6fc69ec6aa33f55ee7b01ba0a6dcac4c1d78dda4 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 9 May 2011 13:06:52 -0700 Subject: [PATCH] Bug 679019 - Make initializing the *Error classes non-generic, and combine their initialization with that of Error. r=jorendorff --HG-- extra : rebase_source : 209d4099359492862de01a2fcb68290755fae86a --- js/src/jsexn.cpp | 72 ++++++++++++-------------------------- js/src/vm/GlobalObject.cpp | 32 +++++++++++------ js/src/vm/GlobalObject.h | 6 ++++ 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 8c1f6fb90e6..ff528302f29 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -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; } diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index ca9d4565453..07902c147d4 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -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(cx, clasp, objectProto, this); - if (!proto) + JSObject *blankProto = NewNonFunction(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 diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 8e34cd35879..73a12219a82 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -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.