Bug 686900 - Rewrite js_InitFunctionAndObject. r=jorendorff
authorJeff Walden <jwalden@mit.edu>
Mon, 09 May 2011 13:06:52 -0700
changeset 78468 be380e98f3836622bf18cc98d9a2fa5b4705a154
parent 78467 ae99d33a2290f11263f0750bd030615ccb10f93f
child 78469 ab0a6fdf0144831c16d993df1bd271861b7c353c
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs686900
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 686900 - Rewrite js_InitFunctionAndObject. r=jorendorff
js/src/jsapi.cpp
js/src/jsproto.tbl
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1575,18 +1575,18 @@ StdNameToAtom(JSContext *cx, JSStdName *
     return atom;
 }
 
 /*
  * Table of class initializers and their atom offsets in rt->atomState.
  * If you add a "standard" class, remember to update this table.
  */
 static JSStdName standard_class_atoms[] = {
-    {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Function)},
-    {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Object)},
+    {js_InitFunctionClass,              EAGER_ATOM_AND_CLASP(Function)},
+    {js_InitObjectClass,                EAGER_ATOM_AND_CLASP(Object)},
     {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},
     {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},
     {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},
     {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},
     {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},
     {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},
     {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},
     {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},
--- a/js/src/jsproto.tbl
+++ b/js/src/jsproto.tbl
@@ -51,18 +51,18 @@
 #endif
 
 /*
  * Enumerator codes in the second column must not change -- they are part of
  * the JS XDR API.  Client modules including jsproto.tbl should consider
  * wrapping the inclusion with JS_BEGIN_EXTERN_C and JS_END_EXTERN_C.
  */
 JS_PROTO(Null,                   0,     js_InitNullClass)
-JS_PROTO(Object,                 1,     js_InitFunctionAndObjectClasses)
-JS_PROTO(Function,               2,     js_InitFunctionAndObjectClasses)
+JS_PROTO(Object,                 1,     js_InitObjectClass)
+JS_PROTO(Function,               2,     js_InitFunctionClass)
 JS_PROTO(Array,                  3,     js_InitArrayClass)
 JS_PROTO(Boolean,                4,     js_InitBooleanClass)
 JS_PROTO(JSON,                   5,     js_InitJSONClass)
 JS_PROTO(Date,                   6,     js_InitDateClass)
 JS_PROTO(Math,                   7,     js_InitMathClass)
 JS_PROTO(Number,                 8,     js_InitNumberClass)
 JS_PROTO(String,                 9,     js_InitStringClass)
 JS_PROTO(RegExp,                10,     js_InitRegExpClass)
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -49,143 +49,208 @@
 #include "jsobjinlines.h"
 #include "jsregexpinlines.h"
 
 using namespace js;
 
 JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &ObjectClass, js_Object, 1,
-                                   object_props, object_methods, NULL, object_static_methods);
-    if (!proto)
-        return NULL;
+    JS_ASSERT(obj->isNative());
 
-    /* The default 'new' object for Object.prototype has unknown properties. */
-    proto->getNewType(cx, NULL, /* markUnknown = */ true);
+    GlobalObject *global = obj->asGlobal();
+    if (!global->functionObjectClassesInitialized()) {
+        if (!global->initFunctionAndObjectClasses(cx))
+            return NULL;
+    }
 
-    /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
-    jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
-    JSObject *evalobj = js_DefineFunction(cx, obj, id, eval, 1, JSFUN_STUB_GSOPS);
-    if (!evalobj)
-        return NULL;
-    if (obj->isGlobal())
-        obj->asGlobal()->setOriginalEval(evalobj);
+    return global->getObjectPrototype();
+}
 
-    return proto;
+JSObject *
+js_InitFunctionClass(JSContext *cx, JSObject *obj)
+{
+    JS_ASSERT(obj->isNative());
+
+    GlobalObject *global = obj->asGlobal();
+    return global->functionObjectClassesInitialized()
+           ? global->getFunctionPrototype()
+           : global->initFunctionAndObjectClasses(cx);
 }
 
 static JSBool
 ThrowTypeError(JSContext *cx, uintN argc, Value *vp)
 {
     JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                  JSMSG_THROW_TYPE_ERROR);
     return false;
 }
 
+namespace js {
+
 JSObject *
-js_InitFunctionClass(JSContext *cx, JSObject *obj)
+GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &FunctionClass, Function, 1,
-                                   NULL, function_methods, NULL, NULL);
-    if (!proto)
+    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_ASSERT(isNative());
+
+    /*
+     * Calling a function from a cleared global triggers this (yeah, I know).
+     * Uncomment this once bug 470510 is fixed (if that bug doesn't remove
+     * isCleared entirely).
+     */
+    // JS_ASSERT(!isCleared());
+
+    /* If cx has no global object, make this the global object. */
+    if (!cx->globalObject)
+        JS_SetGlobalObject(cx, this);
+
+    /*
+     * Create |Object.prototype| first, mirroring CreateBlankProto but for the
+     * prototype of the created object.
+     */
+    JSObject *objectProto = NewNonFunction<WithProto::Given>(cx, &ObjectClass, NULL, this);
+    if (!objectProto || !objectProto->setSingletonType(cx))
+        return NULL;
+    types::TypeObject *objectType = objectProto->getNewType(cx, NULL, /* markUnknown = */ true);
+    if (!objectType || !objectType->getEmptyShape(cx, &ObjectClass, gc::FINALIZE_OBJECT0))
+        return NULL;
+
+    /* Create |Function.prototype| next so we can create other functions. */
+    JSFunction *functionProto;
+    {
+        JSObject *proto = NewObject<WithProto::Given>(cx, &FunctionClass, objectProto, this);
+        if (!proto || !proto->setSingletonType(cx))
+            return NULL;
+        types::TypeObject *functionType = proto->getNewType(cx, NULL, /* markUnknown = */ true);
+        if (!functionType || !functionType->getEmptyShape(cx, &FunctionClass, gc::FINALIZE_OBJECT0))
+            return NULL;
+
+        /*
+         * Bizarrely, |Function.prototype| must be an interpreted function, so
+         * give it the guts to be one.
+         */
+        functionProto = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, this, NULL);
+        if (!functionProto)
+            return NULL;
+        JS_ASSERT(proto == functionProto);
+        functionProto->flags |= JSFUN_PROTOTYPE;
+
+        JSScript *script =
+            JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
+        if (!script)
+            return NULL;
+        script->noScriptRval = true;
+        script->code[0] = JSOP_STOP;
+        script->code[1] = SRC_NULL;
+        functionProto->u.i.script = script;
+        functionProto->getType(cx)->interpretedFunction = functionProto;
+        script->hasFunction = true;
+        script->setOwnerObject(functionProto);
+    }
+
+    /* Create the Object function now that we have a [[Prototype]] for it. */
+    jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
+    JSFunction *objectCtor;
+    {
+        JSObject *ctor = NewObject<WithProto::Given>(cx, &FunctionClass, functionProto, this);
+        if (!ctor)
+            return NULL;
+        objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, this,
+                                    JSID_TO_ATOM(objectId));
+        if (!objectCtor)
+            return NULL;
+        JS_ASSERT(ctor == objectCtor);
+
+        objectCtor->setConstructorClass(&ObjectClass);
+    }
+
+    /*
+     * Install |Object| and |Object.prototype| for the benefit of subsequent
+     * code that looks for them.
+     */
+    setObjectClassDetails(objectCtor, objectProto);
+
+    /* Create |Function| so it and |Function.prototype| can be installed. */
+    jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
+    JSFunction *functionCtor;
+    {
+        JSObject *ctor =
+            NewObject<WithProto::Given>(cx, &FunctionClass, functionProto, this);
+        if (!ctor)
+            return NULL;
+        functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, this,
+                                      JSID_TO_ATOM(functionId));
+        if (!functionCtor)
+            return NULL;
+        JS_ASSERT(ctor == functionCtor);
+
+        functionCtor->setConstructorClass(&FunctionClass);
+    }
+
+    /*
+     * Install |Function| and |Function.prototype| so that we can freely create
+     * functions and objects without special effort.
+     */
+    setFunctionClassDetails(functionCtor, functionProto);
+
+    /*
+     * 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_props, object_methods) ||
+        !DefinePropertiesAndBrand(cx, objectCtor, NULL, object_static_methods) ||
+        !LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
+        !DefinePropertiesAndBrand(cx, functionProto, NULL, function_methods) ||
+        !DefinePropertiesAndBrand(cx, functionCtor, NULL, NULL))
+    {
+        return NULL;
+    }
+
+    /* Add the global Function and Object properties now. */
+    if (!addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
+        return false;
+    if (!addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
+        return false;
+
+    /* Heavy lifting done, but lingering tasks remain. */
+
+    /* ES5 15.1.2.1. */
+    jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
+    JSObject *evalobj = js_DefineFunction(cx, this, id, eval, 1, JSFUN_STUB_GSOPS);
+    if (!evalobj)
+        return NULL;
+    setOriginalEval(evalobj);
+
+    /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
+    JSFunction *throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, this, NULL);
+    if (!throwTypeError)
+        return NULL;
+    setThrowTypeError(throwTypeError);
+
+    /*
+     * The global object should have |Object.prototype| as its [[Prototype]].
+     * Eventually we'd like to have standard classes be there from the start,
+     * and thus we would know we were always setting what had previously been a
+     * null [[Prototype]], but right now some code assumes it can set the
+     * [[Prototype]] before standard classes have been initialized.  For now,
+     * only set the [[Prototype]] if it hasn't already been set.
+     */
+    if (shouldSplicePrototype(cx) && !splicePrototype(cx, objectProto))
         return NULL;
 
     /*
-     * The default 'new' object for Function.prototype has unknown properties.
-     * This will be used for generic scripted functions, e.g. from
-     * non-compileAndGo code.
+     * Notify any debuggers about the creation of the script for
+     * |Function.prototype| -- after all initialization, for simplicity.
      */
-    proto->getNewType(cx, NULL, /* markUnknown = */ true);
-
-    JSFunction *fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
-    if (!fun)
-        return NULL;
-    fun->flags |= JSFUN_PROTOTYPE;
-
-    JSScript *script = JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
-    if (!script)
-        return NULL;
-    script->noScriptRval = true;
-    script->code[0] = JSOP_STOP;
-    script->code[1] = SRC_NULL;
-    fun->u.i.script = script;
-    fun->getType(cx)->interpretedFunction = fun;
-    script->hasFunction = true;
-    script->setOwnerObject(fun);
-    js_CallNewScriptHook(cx, script, fun);
-
-    if (obj->isGlobal()) {
-        /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
-        JSFunction *throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, obj, NULL);
-        if (!throwTypeError)
-            return NULL;
-
-        obj->asGlobal()->setThrowTypeError(throwTypeError);
-    }
-
-    return proto;
+    js_CallNewScriptHook(cx, functionProto->script(), functionProto);
+    return functionProto;
 }
 
-JSObject *
-js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
-{
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
-
-    /* If cx has no global object, use obj so prototypes can be found. */
-    if (!cx->globalObject)
-        JS_SetGlobalObject(cx, obj);
-
-    /* Record Function and Object in cx->resolvingList. */
-    JSAtom **classAtoms = cx->runtime->atomState.classAtoms;
-    AutoResolving resolving1(cx, obj, ATOM_TO_JSID(classAtoms[JSProto_Function]));
-    AutoResolving resolving2(cx, obj, ATOM_TO_JSID(classAtoms[JSProto_Object]));
-
-    /* Initialize the function class first so constructors can be made. */
-    JSObject *fun_proto;
-    if (!js_GetClassPrototype(cx, obj, JSProto_Function, &fun_proto))
-        return NULL;
-    if (!fun_proto) {
-        fun_proto = js_InitFunctionClass(cx, obj);
-        if (!fun_proto)
-            return NULL;
-    } else {
-        JSObject *ctor = JS_GetConstructor(cx, fun_proto);
-        if (!ctor)
-            return NULL;
-        if (!obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
-                                 ObjectValue(*ctor), 0, 0, 0)) {
-            return NULL;
-        }
-    }
-
-    /* Initialize the object class next so Object.prototype works. */
-    JSObject *obj_proto;
-    if (!js_GetClassPrototype(cx, obj, JSProto_Object, &obj_proto))
-        return NULL;
-    if (!obj_proto)
-        obj_proto = js_InitObjectClass(cx, obj);
-    if (!obj_proto)
-        return NULL;
-
-    /*
-     * Function.prototype and the global object delegate to Object.prototype.
-     * Don't update the prototype if the __proto__ of either object was cleared
-     * after the objects started getting used.
-     */
-    if (fun_proto->shouldSplicePrototype(cx) && !fun_proto->splicePrototype(cx, obj_proto))
-        return NULL;
-    if (obj->shouldSplicePrototype(cx) && !obj->splicePrototype(cx, obj_proto))
-        return NULL;
-
-    return fun_proto;
-}
-
-namespace js {
-
 GlobalObject *
 GlobalObject::create(JSContext *cx, Class *clasp)
 {
     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
     JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, NULL, NULL);
     if (!obj || !obj->setSingletonType(cx))
         return NULL;
@@ -214,17 +279,17 @@ GlobalObject::initStandardClasses(JSCont
 
     /* Define a top-level property 'undefined' with the undefined value. */
     if (!defineProperty(cx, ATOM_TO_JSID(state.typeAtoms[JSTYPE_VOID]), UndefinedValue(),
                         PropertyStub, StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
-    if (!js_InitFunctionAndObjectClasses(cx, this))
+    if (!initFunctionAndObjectClasses(cx))
         return false;
 
     /* Initialize the rest of the standard objects and functions. */
     return js_InitArrayClass(cx, this) &&
            js_InitBooleanClass(cx, this) &&
            js_InitExceptionClasses(cx, this) &&
            js_InitMathClass(cx, this) &&
            js_InitNumberClass(cx, this) &&
@@ -253,16 +318,24 @@ GlobalObject::clear(JSContext *cx)
 
     /* Clear regexp statics. */
     RegExpStatics::extractFrom(this)->clear();
 
     /* Clear the runtime-codegen-enabled cache. */
     setSlot(RUNTIME_CODEGEN_ENABLED, UndefinedValue());
 
     /*
+     * Clear the original-eval and [[ThrowTypeError]] slots, in case throwing
+     * trying to execute a script for this global must reinitialize standard
+     * classes.  See bug 470150.
+     */
+    setSlot(EVAL, UndefinedValue());
+    setSlot(THROWTYPEERROR, UndefinedValue());
+
+    /*
      * Mark global as cleared. If we try to execute any compile-and-go
      * scripts from here on, we will throw.
      */
     int32 flags = getSlot(FLAGS).toInt32();
     flags |= FLAGS_CLEARED;
     setSlot(FLAGS, Int32Value(flags));
 }
 
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -46,19 +46,16 @@
 #include "jsvector.h"
 
 extern JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj);
 
 extern JSObject *
 js_InitFunctionClass(JSContext *cx, JSObject *obj);
 
-extern JSObject *
-js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj);
-
 namespace js {
 
 class Debugger;
 
 /*
  * Global object slots are reserved as follows:
  *
  * [0, JSProto_LIMIT)
@@ -115,16 +112,57 @@ class GlobalObject : public ::JSObject {
     }
 
     static const int32 FLAGS_CLEARED = 0x1;
 
     void setFlags(int32 flags) {
         setSlot(FLAGS, Int32Value(flags));
     }
 
+    friend JSObject *
+    ::js_InitObjectClass(JSContext *cx, JSObject *obj);
+    friend JSObject *
+    ::js_InitFunctionClass(JSContext *cx, JSObject *obj);
+
+    /* Initialize the Function and Object classes.  Must only be called once! */
+    JSObject *
+    initFunctionAndObjectClasses(JSContext *cx);
+
+    void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) {
+        Value &ctorVal = getSlotRef(key);
+        Value &protoVal = getSlotRef(JSProto_LIMIT + key);
+        Value &visibleVal = getSlotRef(2 * JSProto_LIMIT + key);
+        JS_ASSERT(ctorVal.isUndefined());
+        JS_ASSERT(protoVal.isUndefined());
+        JS_ASSERT(visibleVal.isUndefined());
+        ctorVal = ObjectValue(*ctor);
+        protoVal = ObjectValue(*proto);
+        visibleVal = ctorVal;
+    }
+
+    void setObjectClassDetails(JSFunction *ctor, JSObject *proto) {
+        setDetailsForKey(JSProto_Object, ctor, proto);
+    }
+
+    void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) {
+        setDetailsForKey(JSProto_Function, ctor, proto);
+    }
+
+    void setThrowTypeError(JSFunction *fun) {
+        Value &v = getSlotRef(THROWTYPEERROR);
+        JS_ASSERT(v.isUndefined());
+        v.setObject(*fun);
+    }
+
+    void setOriginalEval(JSObject *evalobj) {
+        Value &v = getSlotRef(EVAL);
+        JS_ASSERT(v.isUndefined());
+        v.setObject(*evalobj);
+    }
+
   public:
     static GlobalObject *create(JSContext *cx, Class *clasp);
 
     /*
      * Create a constructor function with the specified name and length using
      * ctor, a method which creates objects with the given class.
      */
     JSFunction *
@@ -141,25 +179,36 @@ 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.
-        // JS_ASSERT(v.isUndefined());
-        // JS_ASSERT(getSlot(THROWTYPEERROR).isUndefined());
-        setSlot(THROWTYPEERROR, ObjectValue(*fun));
+    bool functionObjectClassesInitialized() const {
+        bool inited = !getSlot(JSProto_Function).isUndefined();
+        JS_ASSERT(inited == !getSlot(JSProto_LIMIT + JSProto_Function).isUndefined());
+        JS_ASSERT(inited == !getSlot(JSProto_Object).isUndefined());
+        JS_ASSERT(inited == !getSlot(JSProto_LIMIT + JSProto_Object).isUndefined());
+        return inited;
+    }
+
+    JSObject *getFunctionPrototype() const {
+        JS_ASSERT(functionObjectClassesInitialized());
+        return &getSlot(JSProto_LIMIT + JSProto_Function).toObject();
+    }
+
+    JSObject *getObjectPrototype() const {
+        JS_ASSERT(functionObjectClassesInitialized());
+        return &getSlot(JSProto_LIMIT + JSProto_Object).toObject();
     }
 
     JSObject *getThrowTypeError() const {
+        JS_ASSERT(functionObjectClassesInitialized());
         return &getSlot(THROWTYPEERROR).toObject();
     }
 
     JSObject *getOrCreateGeneratorPrototype(JSContext *cx) {
         Value &v = getSlotRef(GENERATOR_PROTO);
         if (!v.isObject() && !js_InitIteratorClasses(cx, this))
             return NULL;
         JS_ASSERT(v.toObject().isGenerator());
@@ -174,27 +223,20 @@ class GlobalObject : public ::JSObject {
 
     bool isCleared() const {
         return getSlot(FLAGS).toInt32() & FLAGS_CLEARED;
     }
 
     bool isRuntimeCodeGenEnabled(JSContext *cx);
 
     const Value &getOriginalEval() const {
+        JS_ASSERT(getSlot(EVAL).isObject());
         return getSlot(EVAL);
     }
 
-    void setOriginalEval(JSObject *evalobj) {
-        // Our bootstrapping code is currently too convoluted to correctly and
-        // confidently assert this.
-        // JS_ASSERT(v.isUndefined());
-        // JS_ASSERT(getSlot(EVAL).isUndefined());
-        setSlot(EVAL, ObjectValue(*evalobj));
-    }
-
     bool getFunctionNamespace(JSContext *cx, Value *vp);
 
     bool initGeneratorClass(JSContext *cx);
     bool initStandardClasses(JSContext *cx);
 
     typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector;
 
     /*