JSString* js::AsmJSFunctionToString(JSContext* cx, HandleFunction fun) { AsmJSModule& module = FunctionToEnclosingModule(fun); const AsmJSModule::ExportedFunction& f = FunctionToExportedFunction(fun, module); uint32_t begin = module.srcStart() + f.startOffsetInModule(); uint32_t end = module.srcStart() + f.endOffsetInModule(); ScriptSource* source = module.scriptSource(); StringBuffer out(cx); if (!out.append("function ")) return nullptr; bool haveSource = source->hasSourceData(); if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) return nullptr; if (!haveSource) { // asm.js functions can't be anonymous MOZ_ASSERT(fun->atom()); if (!out.append(fun->atom())) return nullptr; if (!out.append("() {\n [sourceless code]\n}")) return nullptr; } else { // asm.js functions cannot have been created with a Function constructor // as they belong within a module. MOZ_ASSERT(!(begin == 0 && end == source->length() && source->argumentsNotIncluded())); if (module.strict()) { // AppendUseStrictSource expects its input to start right after the // function name, so split the source chars from the src into two parts: // the function name and the rest (arguments + body). // asm.js functions can't be anonymous MOZ_ASSERT(fun->atom()); if (!out.append(fun->atom())) return nullptr; size_t nameEnd = begin + fun->atom()->length(); Rooted<JSFlatString*> src(cx, source->substring(cx, nameEnd, end)); if (!AppendUseStrictSource(cx, fun, src, out)) return nullptr; } else { Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end)); if (!src) return nullptr; if (!out.append(src)) return nullptr; } } return out.finishString(); }
JSString * js::AsmJSModuleToString(JSContext *cx, HandleFunction fun, bool addParenToLambda) { AsmJSModule &module = ModuleFunctionToModuleObject(fun).module(); uint32_t begin = module.srcStart(); uint32_t end = module.srcEndAfterCurly(); ScriptSource *source = module.scriptSource(); StringBuffer out(cx); // Whether the function has been created with a Function ctor bool funCtor = begin == 0 && end == source->length() && source->argumentsNotIncluded(); if (addParenToLambda && fun->isLambda() && !out.append("(")) return nullptr; if (!out.append("function ")) return nullptr; if (fun->atom() && !out.append(fun->atom())) return nullptr; if (funCtor) { // Functions created with the function constructor don't have arguments in their source. if (!out.append("(")) return nullptr; if (PropertyName *argName = module.globalArgumentName()) { if (!out.append(argName)) return nullptr; } if (PropertyName *argName = module.importArgumentName()) { if (!out.append(", ") || !out.append(argName)) return nullptr; } if (PropertyName *argName = module.bufferArgumentName()) { if (!out.append(", ") || !out.append(argName)) return nullptr; } if (!out.append(") {\n")) return nullptr; } Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end)); if (!src) return nullptr; if (module.strict()) { if (!AppendUseStrictSource(cx, fun, src, out)) return nullptr; } else { if (!out.append(src)) return nullptr; } if (funCtor && !out.append("\n}")) return nullptr; if (addParenToLambda && fun->isLambda() && !out.append(")")) return nullptr; return out.finishString(); }
JSObject * GlobalObject::initFunctionAndObjectClasses(JSContext *cx) { Rooted<GlobalObject*> self(cx, this); JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment); JS_ASSERT(isNative()); cx->setDefaultCompartmentObjectIfUnset(self); RootedObject objectProto(cx); /* * Create |Object.prototype| first, mirroring CreateBlankProto but for the * prototype of the created object. */ objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self, SingletonObject); if (!objectProto) 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 (!setNewTypeUnknown(cx, &ObjectClass, objectProto)) return NULL; /* Create |Function.prototype| next so we can create other functions. */ RootedFunction functionProto(cx); { RawObject functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self, SingletonObject); if (!functionProto_) return NULL; functionProto = functionProto_->toFunction(); /* * Bizarrely, |Function.prototype| must be an interpreted function, so * give it the guts to be one. */ { RawObject proto = NewFunction(cx, functionProto, NULL, 0, JSFunction::INTERPRETED, self, NullPtr()); if (!proto) return NULL; JS_ASSERT(proto == functionProto); functionProto->setIsFunctionPrototype(); } 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) { js_free(source); return NULL; } ScriptSourceHolder ssh(ss); ss->setSource(source, sourceLen); CompileOptions options(cx); options.setNoScriptRval(true) .setVersion(JSVERSION_DEFAULT); RootedScript 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); types::TypeObject* protoType = functionProto->getType(cx); if (!protoType) return NULL; protoType->interpretedFunction = functionProto; script->setFunction(functionProto); /* * The default 'new' type of Function.prototype is required by type * inference to have unknown properties, to simplify handling of e.g. * CloneFunctionObject. */ if (!setNewTypeUnknown(cx, &FunctionClass, functionProto)) return NULL; } /* Create the Object function now that we have a [[Prototype]] for it. */ RootedFunction objectCtor(cx); { RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self, SingletonObject)); if (!ctor) return NULL; RootedAtom objectAtom(cx, cx->names().Object); objectCtor = NewFunction(cx, ctor, obj_construct, 1, JSFunction::NATIVE_CTOR, self, objectAtom); 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, SingletonObject)); if (!ctor) return NULL; RootedAtom functionAtom(cx, cx->names().Function); functionCtor = NewFunction(cx, ctor, Function, 1, JSFunction::NATIVE_CTOR, self, functionAtom); 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. */ RootedFunction getter(cx, NewFunction(cx, NullPtr(), ProtoGetter, 0, JSFunction::NATIVE_FUN, self, NullPtr())); if (!getter) return NULL; #if JS_HAS_OBJ_PROTO_PROP RootedFunction setter(cx, NewFunction(cx, NullPtr(), ProtoSetter, 0, JSFunction::NATIVE_FUN, self, NullPtr())); if (!setter) return NULL; RootedValue undefinedValue(cx, UndefinedValue()); if (!JSObject::defineProperty(cx, objectProto, cx->names().proto, 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. */ if (!self->addDataProperty(cx, cx->names().Object, JSProto_Object + JSProto_LIMIT * 2, 0)) return NULL; if (!self->addDataProperty(cx, cx->names().Function, JSProto_Function + JSProto_LIMIT * 2, 0)) return NULL; /* Heavy lifting done, but lingering tasks remain. */ /* ES5 15.1.2.1. */ RootedId evalId(cx, NameToId(cx->names().eval)); RawObject evalobj = DefineFunction(cx, self, evalId, 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, NewFunction(cx, NullPtr(), ThrowTypeError, 0, JSFunction::NATIVE_FUN, self, NullPtr())); if (!throwTypeError) return NULL; if (!JSObject::preventExtensions(cx, throwTypeError)) return NULL; self->setThrowTypeError(throwTypeError); RootedObject intrinsicsHolder(cx); if (cx->runtime->isSelfHostingGlobal(self)) { intrinsicsHolder = self; } else { intrinsicsHolder = NewObjectWithClassProto(cx, &ObjectClass, NULL, self, TenuredObject); if (!intrinsicsHolder) return NULL; } self->setIntrinsicsHolder(intrinsicsHolder); /* Define a property 'global' with the current global as its value. */ RootedValue global(cx, ObjectValue(*self)); if (!JSObject::defineProperty(cx, intrinsicsHolder, cx->names().global, global, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { 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. */ Rooted<TaggedProto> tagged(cx, TaggedProto(objectProto)); if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, self->getClass(), tagged)) return NULL; /* * Notify any debuggers about the creation of the script for * |Function.prototype| -- after all initialization, for simplicity. */ RootedScript functionProtoScript(cx, functionProto->nonLazyScript()); CallNewScriptHook(cx, functionProtoScript, 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; }