Bug 992958 - Switch Function and Object to ClassSpec. r=luke

This commit is contained in:
Bobby Holley
2014-05-23 16:53:04 -07:00
parent 81e5a83b52
commit d24ec1be44
5 changed files with 37 additions and 91 deletions

View File

@@ -618,7 +618,15 @@ const Class JSFunction::class_ = {
nullptr, /* call */ nullptr, /* call */
fun_hasInstance, fun_hasInstance,
nullptr, /* construct */ nullptr, /* construct */
fun_trace fun_trace,
{
CreateFunctionConstructor,
CreateFunctionPrototype,
nullptr,
function_methods,
nullptr,
FinishFunctionClassInit
}
}; };
const Class* const js::FunctionClassPtr = &JSFunction::class_; const Class* const js::FunctionClassPtr = &JSFunction::class_;

View File

@@ -80,7 +80,20 @@ const Class JSObject::class_ = {
JS_StrictPropertyStub, /* setProperty */ JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub, JS_EnumerateStub,
JS_ResolveStub, JS_ResolveStub,
JS_ConvertStub JS_ConvertStub,
nullptr, /* finalize */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
{
CreateObjectConstructor,
CreateObjectPrototype,
object_static_methods,
object_methods,
object_properties,
FinishObjectClassInit
}
}; };
const Class* const js::ObjectClassPtr = &JSObject::class_; const Class* const js::ObjectClassPtr = &JSObject::class_;

View File

@@ -62,8 +62,8 @@
#define JS_FOR_PROTOTYPES(real,imaginary) \ #define JS_FOR_PROTOTYPES(real,imaginary) \
imaginary(Null, 0, js_InitNullClass, dummy) \ imaginary(Null, 0, js_InitNullClass, dummy) \
real(Object, 1, js_InitObjectClass, &JSObject::class_) \ real(Object, 1, js_InitViaClassSpec, &JSObject::class_) \
real(Function, 2, js_InitFunctionClass, &JSFunction::class_) \ real(Function, 2, js_InitViaClassSpec, &JSFunction::class_) \
real(Array, 3, js_InitArrayClass, OCLASP(Array)) \ real(Array, 3, js_InitArrayClass, OCLASP(Array)) \
real(Boolean, 4, js_InitBooleanClass, OCLASP(Boolean)) \ real(Boolean, 4, js_InitBooleanClass, OCLASP(Boolean)) \
real(JSON, 5, js_InitJSONClass, CLASP(JSON)) \ real(JSON, 5, js_InitJSONClass, CLASP(JSON)) \

View File

@@ -80,22 +80,6 @@ js::GlobalObject::getTypedObjectModule() const {
return v.toObject().as<TypedObjectModuleObject>(); return v.toObject().as<TypedObjectModuleObject>();
} }
JSObject *
js_InitObjectClass(JSContext *cx, HandleObject obj)
{
JS_ASSERT(obj->isNative());
return obj->as<GlobalObject>().getOrCreateObjectPrototype(cx);
}
JSObject *
js_InitFunctionClass(JSContext *cx, HandleObject obj)
{
JS_ASSERT(obj->isNative());
return obj->as<GlobalObject>().getOrCreateFunctionPrototype(cx);
}
static bool static bool
ThrowTypeError(JSContext *cx, unsigned argc, Value *vp) ThrowTypeError(JSContext *cx, unsigned argc, Value *vp)
{ {
@@ -210,6 +194,8 @@ JSObject *
js::CreateObjectConstructor(JSContext *cx, JSProtoKey key) js::CreateObjectConstructor(JSContext *cx, JSProtoKey key)
{ {
Rooted<GlobalObject*> self(cx, cx->global()); Rooted<GlobalObject*> self(cx, cx->global());
if (!GlobalObject::ensureConstructor(cx, self, JSProto_Function))
return nullptr;
RootedObject functionProto(cx, &self->getPrototype(JSProto_Function).toObject()); RootedObject functionProto(cx, &self->getPrototype(JSProto_Function).toObject());
/* Create the Object function now that we have a [[Prototype]] for it. */ /* Create the Object function now that we have a [[Prototype]] for it. */
@@ -242,65 +228,6 @@ js::CreateFunctionConstructor(JSContext *cx, JSProtoKey key)
return functionCtor; return functionCtor;
} }
JSObject *
GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
{
Rooted<GlobalObject*> self(cx, cx->global());
RootedObject objectProto(cx, CreateObjectPrototype(cx, JSProto_Object));
if (!objectProto)
return nullptr;
self->setPrototype(JSProto_Object, ObjectValue(*objectProto));
RootedObject functionProto(cx, CreateFunctionPrototype(cx, JSProto_Function));
if (!functionProto)
return nullptr;
self->setPrototype(JSProto_Function, ObjectValue(*functionProto));
RootedObject objectCtor(cx, CreateObjectConstructor(cx, JSProto_Object));
if (!objectCtor)
return nullptr;
self->setConstructor(JSProto_Object, ObjectValue(*objectCtor));
self->setConstructorPropertySlot(JSProto_Object, ObjectValue(*objectCtor));
RootedObject functionCtor(cx, CreateFunctionConstructor(cx, JSProto_Function));
if (!functionCtor)
return nullptr;
self->setConstructor(JSProto_Function, ObjectValue(*functionCtor));
self->setConstructorPropertySlot(JSProto_Function, ObjectValue(*functionCtor));
/*
* The hard part's done: now go back and add all the properties these
* primordial values have.
*/
if (!LinkConstructorAndPrototype(cx, objectCtor, objectProto) ||
!DefinePropertiesAndBrand(cx, objectProto, object_properties, object_methods))
{
return nullptr;
}
if (!DefinePropertiesAndBrand(cx, objectCtor, nullptr, object_static_methods) ||
!LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
!DefinePropertiesAndBrand(cx, functionProto, nullptr, function_methods) ||
!DefinePropertiesAndBrand(cx, functionCtor, nullptr, nullptr))
{
return nullptr;
}
/* Add the global Function and Object properties now. */
if (!self->addDataProperty(cx, cx->names().Object, constructorPropertySlot(JSProto_Object), 0))
return nullptr;
if (!self->addDataProperty(cx, cx->names().Function, constructorPropertySlot(JSProto_Function), 0))
return nullptr;
if (!FinishObjectClassInit(cx, objectCtor, objectProto))
return nullptr;
if (!FinishFunctionClassInit(cx, functionCtor, functionProto))
return nullptr;
return functionProto;
}
bool bool
js::FinishObjectClassInit(JSContext *cx, JS::HandleObject ctor, JS::HandleObject proto) js::FinishObjectClassInit(JSContext *cx, JS::HandleObject ctor, JS::HandleObject proto)
{ {
@@ -418,6 +345,14 @@ GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JS
// * Function // * Function
// * Object // * Object
// //
// We get the above when Object is resolved before Function. If Function
// is resolved before Object, we'll end up re-entering resolveConstructor
// for Function, which is a problem. So if Function is being resolved before
// Object.prototype exists, we just resolve Object instead, since we know that
// Function will also be resolved before we return.
if (key == JSProto_Function && global->getPrototype(JSProto_Object).isUndefined())
return resolveConstructor(cx, global, JSProto_Object);
// We don't always have a prototype (i.e. Math and JSON). If we don't, // We don't always have a prototype (i.e. Math and JSON). If we don't,
// |createPrototype|, |prototypeFunctions|, and |prototypeProperties| // |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
// should all be null. // should all be null.

View File

@@ -18,12 +18,6 @@
#include "vm/ArrayBufferObject.h" #include "vm/ArrayBufferObject.h"
#include "vm/ErrorObject.h" #include "vm/ErrorObject.h"
extern JSObject *
js_InitObjectClass(JSContext *cx, js::HandleObject obj);
extern JSObject *
js_InitFunctionClass(JSContext *cx, js::HandleObject obj);
extern JSObject * extern JSObject *
js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj); js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj);
@@ -127,10 +121,6 @@ class GlobalObject : public JSObject
static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS, static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
"global object slot counts are inconsistent"); "global object slot counts are inconsistent");
/* Initialize the Function and Object classes. Must only be called once! */
JSObject *
initFunctionAndObjectClasses(JSContext *cx);
// Emit the specified warning if the given slot in |obj|'s global isn't // Emit the specified warning if the given slot in |obj|'s global isn't
// true, then set the slot to true. Thus calling this method warns once // true, then set the slot to true. Thus calling this method warns once
// for each global object it's called on, and every other call does // for each global object it's called on, and every other call does
@@ -313,7 +303,7 @@ class GlobalObject : public JSObject
if (functionObjectClassesInitialized()) if (functionObjectClassesInitialized())
return &getPrototype(JSProto_Object).toObject(); return &getPrototype(JSProto_Object).toObject();
Rooted<GlobalObject*> self(cx, this); Rooted<GlobalObject*> self(cx, this);
if (!initFunctionAndObjectClasses(cx)) if (!ensureConstructor(cx, self, JSProto_Object))
return nullptr; return nullptr;
return &self->getPrototype(JSProto_Object).toObject(); return &self->getPrototype(JSProto_Object).toObject();
} }
@@ -322,7 +312,7 @@ class GlobalObject : public JSObject
if (functionObjectClassesInitialized()) if (functionObjectClassesInitialized())
return &getPrototype(JSProto_Function).toObject(); return &getPrototype(JSProto_Function).toObject();
Rooted<GlobalObject*> self(cx, this); Rooted<GlobalObject*> self(cx, this);
if (!initFunctionAndObjectClasses(cx)) if (!ensureConstructor(cx, self, JSProto_Object))
return nullptr; return nullptr;
return &self->getPrototype(JSProto_Function).toObject(); return &self->getPrototype(JSProto_Function).toObject();
} }