JSObject * js_InitExceptionClasses(JSContext *cx, JSObject *obj) { int i; JSObject *protos[JSEXN_LIMIT]; /* Initialize the prototypes first. */ for (i = 0; exceptions[i].name != 0; i++) { JSAtom *atom; JSFunction *fun; JSString *nameString; int protoIndex = exceptions[i].protoIndex; /* Make the prototype for the current constructor name. */ protos[i] = js_NewObject(cx, &ExceptionClass, (protoIndex != JSEXN_NONE) ? protos[protoIndex] : NULL, obj); if (!protos[i]) return NULL; /* So exn_finalize knows whether to destroy private data. */ OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_VOID); atom = js_Atomize(cx, exceptions[i].name, strlen(exceptions[i].name), 0); if (!atom) return NULL; /* Make a constructor function for the current name. */ fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0); if (!fun) return NULL; /* Make this constructor make objects of class Exception. */ fun->clasp = &ExceptionClass; /* Make the prototype and constructor links. */ if (!js_SetClassPrototype(cx, fun->object, protos[i], JSPROP_READONLY | JSPROP_PERMANENT)) { return NULL; } /* proto bootstrap bit from JS_InitClass omitted. */ nameString = JS_NewStringCopyZ(cx, exceptions[i].name); if (!nameString) return NULL; /* Add the name property to the prototype. */ if (!JS_DefineProperty(cx, protos[i], js_name_str, STRING_TO_JSVAL(nameString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } } /* * Add an empty message property. (To Exception.prototype only, * because this property will be the same for all the exception * protos.) */ if (!JS_DefineProperty(cx, protos[0], js_message_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_filename_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_lineno_str, INT_TO_JSVAL(0), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } /* * Add methods only to Exception.prototype, because ostensibly all * exception types delegate to that. */ if (!JS_DefineFunctions(cx, protos[0], exception_methods)) return NULL; return protos[0]; }
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; }
JSObject * GlobalObject::initFunctionAndObjectClasses(JSContext *cx) { Rooted<GlobalObject*> self(cx, this); 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, self); RootedObject objectProto(cx); /* * Create |Object.prototype| first, mirroring CreateBlankProto but for the * prototype of the created object. */ objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self); 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. */ RootedFunction functionProto(cx); { JSObject *functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self); if (!functionProto_) return NULL; functionProto = functionProto_->toFunction(); /* * Bizarrely, |Function.prototype| must be an interpreted function, so * give it the guts to be one. */ JSObject *proto = js_NewFunction(cx, functionProto, NULL, 0, JSFUN_INTERPRETED, self, NULL); if (!proto) return NULL; JS_ASSERT(proto == functionProto); functionProto->flags |= JSFUN_PROTOTYPE; const char *rawSource = "() {\n}"; size_t sourceLen = strlen(rawSource); jschar *source = InflateString(cx, rawSource, &sourceLen); if (!source) return NULL; ScriptSource *ss = cx->new_<ScriptSource>(); if (!ss) { cx->free_(source); return NULL; } ScriptSourceHolder ssh(cx->runtime, ss); ss->setSource(source, sourceLen); CompileOptions options(cx); options.setNoScriptRval(true) .setVersion(JSVERSION_DEFAULT); Rooted<JSScript*> script(cx, JSScript::Create(cx, /* enclosingScope = */ NullPtr(), /* savedCallerFun = */ false, options, /* staticLevel = */ 0, ss, 0, ss->length())); if (!script || !JSScript::fullyInitTrivial(cx, script)) return NULL; functionProto->initScript(script); functionProto->getType(cx)->interpretedFunction = functionProto; script->setFunction(functionProto); if (!functionProto->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 (!functionProto->setNewTypeUnknown(cx)) return NULL; } /* Create the Object function now that we have a [[Prototype]] for it. */ RootedFunction objectCtor(cx); { JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self); if (!ctor) return NULL; objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self, CLASS_NAME(cx, Object)); if (!objectCtor) return NULL; } /* * Install |Object| and |Object.prototype| for the benefit of subsequent * code that looks for them. */ self->setObjectClassDetails(objectCtor, objectProto); /* Create |Function| so it and |Function.prototype| can be installed. */ RootedFunction functionCtor(cx); { // Note that ctor is rooted purely for the JS_ASSERT at the end RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self)); if (!ctor) return NULL; functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self, CLASS_NAME(cx, Function)); if (!functionCtor) return NULL; JS_ASSERT(ctor == functionCtor); } /* * Install |Function| and |Function.prototype| so that we can freely create * functions and objects without special effort. */ self->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, NULL, object_methods)) { return NULL; } /* * Add an Object.prototype.__proto__ accessor property to implement that * extension (if it's actually enabled). Cache the getter for this * function so that cross-compartment [[Prototype]]-getting is implemented * in one place. */ Rooted<JSFunction*> getter(cx, js_NewFunction(cx, NULL, ProtoGetter, 0, 0, self, NULL)); if (!getter) return NULL; #if JS_HAS_OBJ_PROTO_PROP Rooted<JSFunction*> setter(cx, js_NewFunction(cx, NULL, ProtoSetter, 0, 0, self, NULL)); if (!setter) return NULL; RootedValue undefinedValue(cx, UndefinedValue()); if (!objectProto->defineProperty(cx, cx->runtime->atomState.protoAtom, undefinedValue, JS_DATA_TO_FUNC_PTR(PropertyOp, getter.get()), JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setter.get()), JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED)) { return NULL; } #endif /* JS_HAS_OBJ_PROTO_PROP */ self->setProtoGetter(getter); if (!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. */ jsid objectId = NameToId(CLASS_NAME(cx, Object)); if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0)) return NULL; jsid functionId = NameToId(CLASS_NAME(cx, Function)); if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0)) return NULL; /* Heavy lifting done, but lingering tasks remain. */ /* ES5 15.1.2.1. */ RootedId id(cx, NameToId(cx->runtime->atomState.evalAtom)); JSObject *evalobj = js_DefineFunction(cx, self, id, IndirectEval, 1, JSFUN_STUB_GSOPS); if (!evalobj) return NULL; self->setOriginalEval(evalobj); /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */ RootedFunction throwTypeError(cx, js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL)); if (!throwTypeError) return NULL; if (!throwTypeError->preventExtensions(cx)) return NULL; self->setThrowTypeError(throwTypeError); RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self)); if (!intrinsicsHolder) return NULL; self->setIntrinsicsHolder(intrinsicsHolder); if (!JS_DefineFunctions(cx, intrinsicsHolder, intrinsic_functions)) return NULL; /* * 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 (self->shouldSplicePrototype(cx) && !self->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; }
JSObject * js_InitExceptionClasses(JSContext *cx, JSObject *obj) { JSObject *obj_proto, *protos[JSEXN_LIMIT]; int i; /* * If lazy class initialization occurs for any Error subclass, then all * classes are initialized, starting with Error. To avoid reentry and * redundant initialization, we must not pass a null proto parameter to * js_NewObject below, when called for the Error superclass. We need to * ensure that Object.prototype is the proto of Error.prototype. * * See the equivalent code to ensure that parent_proto is non-null when * JS_InitClass calls js_NewObject, in jsapi.c. */ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object), &obj_proto)) { return NULL; } if (!js_EnterLocalRootScope(cx)) return NULL; /* Initialize the prototypes first. */ for (i = 0; exceptions[i].name != 0; i++) { JSAtom *atom; JSFunction *fun; JSString *nameString; int protoIndex = exceptions[i].protoIndex; /* Make the prototype for the current constructor name. */ protos[i] = js_NewObject(cx, &js_ErrorClass, (protoIndex != JSEXN_NONE) ? protos[protoIndex] : obj_proto, obj, 0); if (!protos[i]) break; /* So exn_finalize knows whether to destroy private data. */ STOBJ_SET_SLOT(protos[i], JSSLOT_PRIVATE, JSVAL_VOID); /* Make a constructor function for the current name. */ atom = cx->runtime->atomState.classAtoms[exceptions[i].key]; fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0); if (!fun) break; /* Make this constructor make objects of class Exception. */ fun->u.n.clasp = &js_ErrorClass; /* Make the prototype and constructor links. */ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i], JSPROP_READONLY | JSPROP_PERMANENT)) { break; } /* proto bootstrap bit from JS_InitClass omitted. */ nameString = JS_NewStringCopyZ(cx, exceptions[i].name); if (!nameString) break; /* Add the name property to the prototype. */ if (!JS_DefineProperty(cx, protos[i], js_name_str, STRING_TO_JSVAL(nameString), NULL, NULL, JSPROP_ENUMERATE)) { break; } /* Finally, stash the constructor for later uses. */ if (!js_SetClassObject(cx, obj, exceptions[i].key, FUN_OBJECT(fun))) break; } js_LeaveLocalRootScope(cx); if (exceptions[i].name) return NULL; /* * Add an empty message property. (To Exception.prototype only, * because this property will be the same for all the exception * protos.) */ if (!JS_DefineProperty(cx, protos[0], js_message_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_fileName_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_lineNumber_str, INT_TO_JSVAL(0), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } /* * Add methods only to Exception.prototype, because ostensibly all * exception types delegate to that. */ if (!JS_DefineFunctions(cx, protos[0], exception_methods)) return NULL; return protos[0]; }
JSObject * js_InitExceptionClasses(JSContext *cx, JSObject *obj) { jsval roots[3]; JSObject *obj_proto, *error_proto; jsval empty; /* * If lazy class initialization occurs for any Error subclass, then all * classes are initialized, starting with Error. To avoid reentry and * redundant initialization, we must not pass a null proto parameter to * js_NewObject below, when called for the Error superclass. We need to * ensure that Object.prototype is the proto of Error.prototype. * * See the equivalent code to ensure that parent_proto is non-null when * JS_InitClass calls js_NewObject, in jsapi.c. */ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object), &obj_proto)) { return NULL; } memset(roots, 0, sizeof(roots)); JSAutoTempValueRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots); #ifdef __GNUC__ error_proto = NULL; /* quell GCC overwarning */ #endif /* Initialize the prototypes first. */ for (intN i = JSEXN_ERR; i != JSEXN_LIMIT; i++) { JSObject *proto; JSProtoKey protoKey; JSAtom *atom; JSFunction *fun; /* Make the prototype for the current constructor name. */ proto = js_NewObject(cx, &js_ErrorClass, (i != JSEXN_ERR) ? error_proto : obj_proto, obj); if (!proto) return NULL; if (i == JSEXN_ERR) { error_proto = proto; roots[0] = OBJECT_TO_JSVAL(proto); } else { // We cannot share the root for error_proto and other prototypes // as error_proto must be rooted until the function returns. roots[1] = OBJECT_TO_JSVAL(proto); } /* So exn_finalize knows whether to destroy private data. */ proto->setPrivate(NULL); /* Make a constructor function for the current name. */ protoKey = GetExceptionProtoKey(i); atom = cx->runtime->atomState.classAtoms[protoKey]; fun = js_DefineFunction(cx, obj, atom, Exception, 3, 0); if (!fun) return NULL; roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun)); /* Make this constructor make objects of class Exception. */ FUN_CLASP(fun) = &js_ErrorClass; /* Make the prototype and constructor links. */ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto, JSPROP_READONLY | JSPROP_PERMANENT)) { return NULL; } /* Add the name property to the prototype. */ if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_KEY(atom), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } /* Finally, stash the constructor for later uses. */ if (!js_SetClassObject(cx, obj, protoKey, FUN_OBJECT(fun))) return NULL; } /* * Set default values and add methods. We do it only for Error.prototype * as the rest of exceptions delegate to it. */ empty = STRING_TO_JSVAL(cx->runtime->emptyString); if (!JS_DefineProperty(cx, error_proto, js_message_str, empty, NULL, NULL, JSPROP_ENUMERATE) || !JS_DefineProperty(cx, error_proto, js_fileName_str, empty, NULL, NULL, JSPROP_ENUMERATE) || !JS_DefineProperty(cx, error_proto, js_lineNumber_str, JSVAL_ZERO, NULL, NULL, JSPROP_ENUMERATE) || !JS_DefineFunctions(cx, error_proto, exception_methods)) { return NULL; } return error_proto; }