JSObject * GlobalObject::initFunctionAndObjectClasses(JSContext *cx) { 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 = NewObjectWithGivenProto(cx, &ObjectClass, NULL, this); if (!objectProto || !objectProto->setSingletonType(cx)) return NULL; /* * The default 'new' type of Object.prototype is required by type inference * to have unknown properties, to simplify handling of e.g. heterogenous * objects in JSON and script literals. */ if (!objectProto->setNewTypeUnknown(cx)) return NULL; /* Create |Function.prototype| next so we can create other functions. */ JSFunction *functionProto; { JSObject *proto = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, this); if (!proto) 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->initScript(script); functionProto->getType(cx)->interpretedFunction = functionProto; script->setFunction(functionProto); if (!proto->setSingletonType(cx)) return NULL; /* * The default 'new' type of Function.prototype is required by type * inference to have unknown properties, to simplify handling of e.g. * CloneFunctionObject. */ if (!proto->setNewTypeUnknown(cx)) return NULL; } /* 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 = NewObjectWithGivenProto(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 = NewObjectWithGivenProto(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 NULL; if (!addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0)) return NULL; /* 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; AutoIdVector ids(cx); if (!throwTypeError->preventExtensions(cx, &ids)) 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; /* * Notify any debuggers about the creation of the script for * |Function.prototype| -- after all initialization, for simplicity. */ js_CallNewScriptHook(cx, functionProto->script(), functionProto); return functionProto; }