mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 959013 - Add a standardized initialization mechanism based on the ClassSpec. r=luke
This commit is contained in:
parent
857560e4fc
commit
460ab407b5
@ -46,6 +46,12 @@ struct ProtoTableEntry {
|
|||||||
JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT)
|
JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT)
|
||||||
#undef DECLARE_PROTOTYPE_CLASS_INIT
|
#undef DECLARE_PROTOTYPE_CLASS_INIT
|
||||||
|
|
||||||
|
JSObject *
|
||||||
|
js_InitViaClassSpec(JSContext *cx, Handle<JSObject*> obj)
|
||||||
|
{
|
||||||
|
MOZ_ASSUME_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
static const ProtoTableEntry protoTable[JSProto_LIMIT] = {
|
static const ProtoTableEntry protoTable[JSProto_LIMIT] = {
|
||||||
#define INIT_FUNC(name,code,init,clasp) { clasp, init },
|
#define INIT_FUNC(name,code,init,clasp) { clasp, init },
|
||||||
#define INIT_FUNC_DUMMY(name,code,init,clasp) { nullptr, nullptr },
|
#define INIT_FUNC_DUMMY(name,code,init,clasp) { nullptr, nullptr },
|
||||||
@ -441,10 +447,79 @@ GlobalObject::ensureConstructor(JSContext *cx, JSProtoKey key)
|
|||||||
{
|
{
|
||||||
if (getConstructor(key).isObject())
|
if (getConstructor(key).isObject())
|
||||||
return true;
|
return true;
|
||||||
|
return initConstructor(cx, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GlobalObject::initConstructor(JSContext *cx, JSProtoKey key)
|
||||||
|
{
|
||||||
MOZ_ASSERT(getConstructor(key).isUndefined());
|
MOZ_ASSERT(getConstructor(key).isUndefined());
|
||||||
RootedObject self(cx, this);
|
Rooted<GlobalObject*> self(cx, this);
|
||||||
|
|
||||||
|
// There are two different kinds of initialization hooks. One of them is
|
||||||
|
// the class js_InitFoo hook, defined in a JSProtoKey-keyed table at the
|
||||||
|
// top of this file. The other lives in the ClassSpec for classes that
|
||||||
|
// define it. Classes may use one or the other, but not both.
|
||||||
ClassInitializerOp init = protoTable[key].init;
|
ClassInitializerOp init = protoTable[key].init;
|
||||||
return !init || init(cx, self);
|
if (init == js_InitViaClassSpec)
|
||||||
|
init = nullptr;
|
||||||
|
|
||||||
|
const Class *clasp = ProtoKeyToClass(key);
|
||||||
|
|
||||||
|
// Some classes have no init routine, which means that they're disabled at
|
||||||
|
// compile-time. We could try to enforce that callers never pass such keys
|
||||||
|
// to initConstructor, but that would cramp the style of consumers like
|
||||||
|
// GlobalObject::initStandardClasses that want to just carpet-bomb-call
|
||||||
|
// ensureConstructor with every JSProtoKey. So it's easier to just handle
|
||||||
|
// it here.
|
||||||
|
bool haveSpec = clasp && clasp->spec.defined();
|
||||||
|
if (!init && !haveSpec)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// See if there's an old-style initialization hook.
|
||||||
|
if (init) {
|
||||||
|
MOZ_ASSERT(!haveSpec);
|
||||||
|
return init(cx, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ok, we're doing it with a class spec.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Create the constructor.
|
||||||
|
RootedObject ctor(cx, clasp->spec.createConstructor(cx, key));
|
||||||
|
if (!ctor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Define any specified functions.
|
||||||
|
if (const JSFunctionSpec *funs = clasp->spec.constructorFunctions) {
|
||||||
|
if (!JS_DefineFunctions(cx, ctor, funs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't always have a prototype (i.e. Math and JSON). If we don't,
|
||||||
|
// |createPrototype| and |prototypeFunctions| should both be null.
|
||||||
|
RootedObject proto(cx);
|
||||||
|
if (clasp->spec.createPrototype) {
|
||||||
|
proto = clasp->spec.createPrototype(cx, key);
|
||||||
|
if (!proto)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (const JSFunctionSpec *funs = clasp->spec.prototypeFunctions) {
|
||||||
|
if (!JS_DefineFunctions(cx, proto, funs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the prototype exists, link it with the constructor.
|
||||||
|
if (proto && !LinkConstructorAndPrototype(cx, ctor, proto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Call the post-initialization hook, if provided.
|
||||||
|
if (clasp->spec.finishInit && !clasp->spec.finishInit(cx, ctor, proto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Stash things in the right slots and define the constructor on the global.
|
||||||
|
return DefineConstructorAndPrototype(cx, self, key, ctor, proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalObject *
|
GlobalObject *
|
||||||
|
@ -160,6 +160,7 @@ class GlobalObject : public JSObject
|
|||||||
return getSlotForCompilation(APPLICATION_SLOTS + key);
|
return getSlotForCompilation(APPLICATION_SLOTS + key);
|
||||||
}
|
}
|
||||||
bool ensureConstructor(JSContext *cx, JSProtoKey key);
|
bool ensureConstructor(JSContext *cx, JSProtoKey key);
|
||||||
|
bool initConstructor(JSContext *cx, JSProtoKey key);
|
||||||
|
|
||||||
void setConstructor(JSProtoKey key, const Value &v) {
|
void setConstructor(JSProtoKey key, const Value &v) {
|
||||||
JS_ASSERT(key <= JSProto_LIMIT);
|
JS_ASSERT(key <= JSProto_LIMIT);
|
||||||
|
Loading…
Reference in New Issue
Block a user