void WorkerDebuggerGlobalScope::CreateSandbox(JSContext* aCx, const nsAString& aName, JS::Handle<JSObject*> aPrototype, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) { mWorkerPrivate->AssertIsOnWorkerThread(); aResult.set(nullptr); JS::Rooted<JS::Value> protoVal(aCx); protoVal.setObjectOrNull(aPrototype); JS::Rooted<JSObject*> sandbox(aCx, SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox, protoVal)); if (!sandbox) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } if (!JS_WrapObject(aCx, &sandbox)) { aRv.NoteJSContextException(aCx); return; } aResult.set(sandbox); }
bool LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor_, JSObject *proto_) { RootedObject ctor(cx, ctor_), proto(cx, proto_); RootedValue protoVal(cx, ObjectValue(*proto)); RootedValue ctorVal(cx, ObjectValue(*ctor)); return ctor->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom, protoVal, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY) && proto->defineProperty(cx, cx->runtime->atomState.constructorAtom, ctorVal, JS_PropertyStub, JS_StrictPropertyStub, 0); }
void CComponentManager::Script_RegisterComponentType(ScriptInterface::CxPrivate* pCxPrivate, int iid, std::string cname, CScriptVal ctor) { CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData); JSContext* cx = componentManager->m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); // Find the C++ component that wraps the interface int cidWrapper = componentManager->GetScriptWrapper(iid); if (cidWrapper == CID__Invalid) { componentManager->m_ScriptInterface.ReportError("Invalid interface id"); return; } const ComponentType& ctWrapper = componentManager->m_ComponentTypesById[cidWrapper]; bool mustReloadComponents = false; // for hotloading ComponentTypeId cid = componentManager->LookupCID(cname); if (cid == CID__Invalid) { // Allocate a new cid number cid = componentManager->m_NextScriptComponentTypeId++; componentManager->m_ComponentTypeIdsByName[cname] = cid; } else { // Component type is already loaded, so do hotloading: if (!componentManager->m_CurrentlyHotloading) { componentManager->m_ScriptInterface.ReportError("Registering component type with already-registered name"); // TODO: report the actual name return; } const ComponentType& ctPrevious = componentManager->m_ComponentTypesById[cid]; // We can only replace scripted component types, not native ones if (ctPrevious.type != CT_Script) { componentManager->m_ScriptInterface.ReportError("Hotloading script component type with same name as native component"); return; } // We don't support changing the IID of a component type (it would require fiddling // around with m_ComponentsByInterface and being careful to guarantee uniqueness per entity) if (ctPrevious.iid != iid) { // ...though it only matters if any components exist with this type if (!componentManager->m_ComponentsByTypeId[cid].empty()) { componentManager->m_ScriptInterface.ReportError("Hotloading script component type mustn't change interface ID"); return; } } // Remove the old component type's message subscriptions std::map<MessageTypeId, std::vector<ComponentTypeId> >::iterator it; for (it = componentManager->m_LocalMessageSubscriptions.begin(); it != componentManager->m_LocalMessageSubscriptions.end(); ++it) { std::vector<ComponentTypeId>& types = it->second; std::vector<ComponentTypeId>::iterator ctit = find(types.begin(), types.end(), cid); if (ctit != types.end()) types.erase(ctit); } for (it = componentManager->m_GlobalMessageSubscriptions.begin(); it != componentManager->m_GlobalMessageSubscriptions.end(); ++it) { std::vector<ComponentTypeId>& types = it->second; std::vector<ComponentTypeId>::iterator ctit = find(types.begin(), types.end(), cid); if (ctit != types.end()) types.erase(ctit); } mustReloadComponents = true; } std::string schema = "<empty/>"; { CScriptValRooted prototype; if (componentManager->m_ScriptInterface.GetProperty(ctor.get(), "prototype", prototype) && componentManager->m_ScriptInterface.HasProperty(prototype.get(), "Schema")) { componentManager->m_ScriptInterface.GetProperty(prototype.get(), "Schema", schema); } } // Construct a new ComponentType, using the wrapper's alloc functions ComponentType ct = { CT_Script, iid, ctWrapper.alloc, ctWrapper.dealloc, cname, schema, CScriptValRooted(cx, ctor) }; componentManager->m_ComponentTypesById[cid] = ct; componentManager->m_CurrentComponent = cid; // needed by Subscribe // Find all the ctor prototype's On* methods, and subscribe to the appropriate messages: JS::RootedValue protoVal(cx); if (!componentManager->m_ScriptInterface.GetPropertyJS(ctor.get(), "prototype", &protoVal)) return; // error std::vector<std::string> methods; JS::RootedObject proto(cx); if (!protoVal.isObjectOrNull()) return; // error proto = protoVal.toObjectOrNull(); if (!componentManager->m_ScriptInterface.EnumeratePropertyNamesWithPrefix(protoVal, "On", methods)) return; // error for (std::vector<std::string>::const_iterator it = methods.begin(); it != methods.end(); ++it) { std::string name = (*it).substr(2); // strip the "On" prefix // Handle "OnGlobalFoo" functions specially bool isGlobal = false; if (name.substr(0, 6) == "Global") { isGlobal = true; name = name.substr(6); } std::map<std::string, MessageTypeId>::const_iterator mit = componentManager->m_MessageTypeIdsByName.find(name); if (mit == componentManager->m_MessageTypeIdsByName.end()) { std::string msg = "Registered component has unrecognised '" + *it + "' message handler method"; componentManager->m_ScriptInterface.ReportError(msg.c_str()); return; } if (isGlobal) componentManager->SubscribeGloballyToMessageType(mit->second); else componentManager->SubscribeToMessageType(mit->second); } componentManager->m_CurrentComponent = CID__Invalid; if (mustReloadComponents) { // For every script component with this cid, we need to switch its // prototype from the old constructor's prototype property to the new one's const std::map<entity_id_t, IComponent*>& comps = componentManager->m_ComponentsByTypeId[cid]; std::map<entity_id_t, IComponent*>::const_iterator eit = comps.begin(); for (; eit != comps.end(); ++eit) { JS::RootedValue instance(cx, eit->second->GetJSInstance()); if (!instance.isNull()) { componentManager->m_ScriptInterface.SetPrototype(instance, protoVal); } } } }