void CSimulation2::LoadPlayerSettings(bool newPlayers) { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject()); GetScriptInterface().CallFunctionVoid(global, "LoadPlayerSettings", m->m_MapSettings, newPlayers); }
void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent) { JSContext* cx = m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); m_ScriptInterface.SetProperty(m_Instance, "entity", (int)ent, true, false); m_ScriptInterface.SetProperty(m_Instance, "template", paramNode, true, false); // Support a custom "Deserialize" function, to which we pass the deserialized data // instead of automatically adding the deserialized properties onto the object if (m_HasCustomDeserialize) { JS::RootedValue val(cx); // If Serialize = null, we'll still call Deserialize but with undefined argument if (!m_HasNullSerialize) deserialize.ScriptVal("object", &val); if (!m_ScriptInterface.CallFunctionVoid(m_Instance, "Deserialize", val)) LOGERROR("Script Deserialize call failed"); } else { if (!m_HasNullSerialize) { // Use ScriptObjectAppend so we don't lose the carefully-constructed // prototype/parent of this object deserialize.ScriptObjectAppend("object", m_Instance); } } }
void CBinarySerializerScriptImpl::ScriptString(const char* name, JS::HandleString string) { JSContext* cx = m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); #if BYTE_ORDER != LITTLE_ENDIAN #error TODO: probably need to convert JS strings to little-endian #endif size_t length; JS::AutoCheckCannotGC nogc; // Serialize strings directly as UTF-16 or Latin1, to avoid expensive encoding conversions bool isLatin1 = JS_StringHasLatin1Chars(string); m_Serializer.Bool("isLatin1", isLatin1); if (isLatin1) { const JS::Latin1Char* chars = JS_GetLatin1StringCharsAndLength(cx, nogc, string, &length); if (!chars) throw PSERROR_Serialize_ScriptError("JS_GetLatin1StringCharsAndLength failed"); m_Serializer.NumberU32_Unbounded("string length", (u32)length); m_Serializer.RawBytes(name, (const u8*)chars, length); } else { const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, string, &length); if (!chars) throw PSERROR_Serialize_ScriptError("JS_GetTwoByteStringCharsAndLength failed"); m_Serializer.NumberU32_Unbounded("string length", (u32)length); m_Serializer.RawBytes(name, (const u8*)chars, length*2); } }
void CSimulation2::InitGame(JS::HandleValue data) { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject()); GetScriptInterface().CallFunctionVoid(global, "InitGame", data); }
void CStdDeserializer::ScriptString(const char* name, JS::MutableHandleString out) { #if BYTE_ORDER != LITTLE_ENDIAN #error TODO: probably need to convert JS strings from little-endian #endif JSContext* cx = m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); bool isLatin1; Bool("isLatin1", isLatin1); if (isLatin1) { std::vector<JS::Latin1Char> str; ReadStringLatin1(name, str); out.set(JS_NewStringCopyN(cx, (const char*)str.data(), str.size())); if (!out) throw PSERROR_Deserialize_ScriptError("JS_NewStringCopyN failed"); } else { utf16string str; ReadStringUTF16(name, str); out.set(JS_NewUCStringCopyN(cx, (const char16_t*)str.data(), str.length())); if (!out) throw PSERROR_Deserialize_ScriptError("JS_NewUCStringCopyN failed"); } }
void CBackupDeleter::run() { if (! _ctx._options->_removeNonExistingFiles ) return; LOGD("{} START", __PRETTY_FUNCTION__); const CAsset * pRoot( _parser.getRoot() ); assert( pRoot ); CRequest rq(_ctx._options->_curlVerbose); for (const auto & p : _remote.paths()) { const CAsset * pLocal = pRoot->find(p); if (pLocal == nullptr) { rq.addHeader("X-Auth-Token", _ctx._cr.token()); const std::string url= fmt::format("{}/{}/{}", _ctx._cr.endpoint(), _ctx._options->_dstContainer, (_ctx._options->_dstFolder / rq.escapePath(p)).string() ); LOGI("deleting backup '{}'", url); //p.string()); rq.del(url); if ( rq.getHttpResponseCode() != 204 ) { LOGE("Failed to delete '{}' [http response : {}]", url, rq.getHttpResponseCode()); _ctx.abort(); } } if (_ctx.aborted()) break; } LOGD("{} DONE", __PRETTY_FUNCTION__); }
virtual void PushLocalCommand(player_id_t player, JS::HandleValue cmd) { JSContext* cx = GetSimContext().GetScriptInterface().GetContext(); JSAutoRequest rq(cx); m_LocalQueue.emplace_back(SimulationCommand(player, cx, cmd)); }
bool CNetClient::OnGameStart(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_GAME_START); CNetClient* client = (CNetClient*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); // Find the player assigned to our GUID int player = -1; if (client->m_PlayerAssignments.find(client->m_GUID) != client->m_PlayerAssignments.end()) player = client->m_PlayerAssignments[client->m_GUID].m_PlayerID; client->m_ClientTurnManager = new CNetClientTurnManager( *client->m_Game->GetSimulation2(), *client, client->m_HostID, client->m_Game->GetReplayLogger()); client->m_Game->SetPlayerID(player); client->m_Game->StartGame(&client->m_GameAttributes, ""); JS::RootedValue msg(cx); client->GetScriptInterface().Eval("({'type':'start'})", &msg); client->PushGuiMessage(msg); return true; }
template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, JS::HandleValue v, bool& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isBoolean(), v); out = JS::ToBoolean(v); return true; }
bool Sched_context::deblock(unsigned cpu, Sched_context *crs, bool lazy_q = false) { assert_kdb(cpu_lock.test()); Sched_context *cs = rq(cpu).current_sched(); bool res = true; if (this == cs) { if (crs->dominates(this)) res = false; } else { deblock_refill(cpu); if ((EXPECT_TRUE(cs != 0) && cs->dominates(this)) || crs->dominates(this)) res = false; } if (res && lazy_q) return true; ready_enqueue(cpu); return res; }
bool ScriptInterface::ParseJSON(const std::string& string_utf8, JS::MutableHandleValue out) { JSAutoRequest rq(m->m_cx); std::wstring attrsW = wstring_from_utf8(string_utf8); utf16string string(attrsW.begin(), attrsW.end()); if (JS_ParseJSON(m->m_cx, reinterpret_cast<const jschar*>(string.c_str()), (u32)string.size(), out)) return true; LOGERROR("JS_ParseJSON failed!"); if (!JS_IsExceptionPending(m->m_cx)) return false; JS::RootedValue exc(m->m_cx); if (!JS_GetPendingException(m->m_cx, &exc)) return false; JS_ClearPendingException(m->m_cx); // We expect an object of type SyntaxError if (!exc.isObject()) return false; JS::RootedValue rval(m->m_cx); JS::RootedObject excObj(m->m_cx, &exc.toObject()); if (!JS_CallFunctionName(m->m_cx, excObj, "toString", JS::HandleValueArray::empty(), &rval)) return false; std::wstring error; ScriptInterface::FromJSVal(m->m_cx, rval, error); LOGERROR("%s", utf8_from_wstring(error)); return false; }
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); if (!VfsFileExists(path)) { LOGERROR("File '%s' does not exist", path.string8()); return false; } CVFSFile file; PSRETURN ret = file.Load(g_VFS, path); if (ret != PSRETURN_OK) { LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret)); return false; } std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 utf16string codeUtf16(code.begin(), code.end()); uint lineNo = 1; JS::RootedValue rval(m->m_cx); return JS_EvaluateUCScript(m->m_cx, global, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), utf8_from_wstring(path.string()).c_str(), lineNo, &rval); }
template<> void ScriptInterface::ToJSVal<CFixedVector3D>(JSContext* cx, JS::MutableHandleValue ret, const CFixedVector3D& val) { JSAutoRequest rq(cx); // apply the Vector3D prototype to the return value; ScriptInterface::CxPrivate* pCxPrivate = ScriptInterface::GetScriptInterfaceAndCBData(cx); JS::RootedObject proto(cx, &pCxPrivate->pScriptInterface->GetCachedValue(ScriptInterface::CACHE_VECTOR3DPROTO).toObject()); JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, proto, JS::NullPtr())); if (!obj) { ret.setUndefined(); return; } JS::RootedValue x(cx); JS::RootedValue y(cx); JS::RootedValue z(cx); ToJSVal(cx, &x, val.X); ToJSVal(cx, &y, val.Y); ToJSVal(cx, &z, val.Z); JS_SetProperty(cx, obj, "x", x); JS_SetProperty(cx, obj, "y", y); JS_SetProperty(cx, obj, "z", z); ret.setObject(*obj); }
void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs) { JSAutoRequest rq(m->m_cx); std::string typeName = clasp->name; if (m_CustomObjectTypes.find(typeName) != m_CustomObjectTypes.end()) { // This type already exists throw PSERROR_Scripting_DefineType_AlreadyExists(); } JS::RootedObject global(m->m_cx, m->m_glob); JS::RootedObject obj(m->m_cx, JS_InitClass(m->m_cx, global, JS::NullPtr(), clasp, constructor, minArgs, // Constructor, min args ps, fs, // Properties, methods static_ps, static_fs)); // Constructor properties, methods if (obj == NULL) throw PSERROR_Scripting_DefineType_CreationFailed(); CustomType type; type.m_Prototype = DefPersistentRooted<JSObject*>(m->m_cx, obj); type.m_Class = clasp; type.m_Constructor = constructor; m_CustomObjectTypes[typeName] = std::move(type); }
bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& code) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); utf16string codeUtf16(code.begin(), code.end()); uint lineNo = 1; // CompileOptions does not copy the contents of the filename string pointer. // Passing a temporary string there will cause undefined behaviour, so we create a separate string to avoid the temporary. std::string filenameStr(utf8_from_wstring(filename.string())); JS::CompileOptions options(m->m_cx); options.setFileAndLine(filenameStr.c_str(), lineNo); options.setCompileAndGo(true); JS::RootedFunction func(m->m_cx, JS_CompileUCFunction(m->m_cx, global, NULL, 0, NULL, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), options) ); if (!func) return false; JS::RootedValue rval(m->m_cx); return JS_CallFunction(m->m_cx, JS::NullPtr(), func, JS::HandleValueArray::empty(), &rval); }
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : m_runtime(runtime), m_glob(runtime->m_rt), m_nativeScope(runtime->m_rt) { bool ok; m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE); ENSURE(m_cx); JS_SetParallelIonCompilationEnabled(m_runtime->m_rt, true); // For GC debugging: // JS_SetGCZeal(m_cx, 2); JS_SetContextPrivate(m_cx, NULL); JS_SetErrorReporter(m_cx, ErrorReporter); JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_ION_ENABLE, 1); JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_BASELINE_ENABLE, 1); JS::ContextOptionsRef(m_cx).setExtraWarnings(1) .setWerror(0) .setVarObjFix(1) .setStrictMode(1); JS::CompartmentOptions opt; opt.setVersion(JSVERSION_LATEST); JSAutoRequest rq(m_cx); JS::RootedObject globalRootedVal(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt)); m_comp = JS_EnterCompartment(m_cx, globalRootedVal); ok = JS_InitStandardClasses(m_cx, globalRootedVal); ENSURE(ok); m_glob = globalRootedVal.get(); // Use the testing functions to globally enable gcPreserveCode. This brings quite a // big performance improvement. In future SpiderMonkey versions, we should probably // use the functions implemented here: https://bugzilla.mozilla.org/show_bug.cgi?id=1068697 JS::RootedObject testingFunctionsObj(m_cx, js::GetTestingFunctions(m_cx)); ENSURE(testingFunctionsObj); JS::RootedValue ret(m_cx); JS_CallFunctionName(m_cx, testingFunctionsObj, "gcPreserveCode", JS::HandleValueArray::empty(), &ret); JS_DefineProperty(m_cx, m_glob, "global", globalRootedVal, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(m_cx, globalRootedVal, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(m_cx, globalRootedVal, "log", ::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(m_cx, globalRootedVal, "warn", ::warn, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(m_cx, globalRootedVal, "error", ::error, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(m_cx, globalRootedVal, "deepcopy", ::deepcopy, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); Register("ProfileStart", ::ProfileStart, 1); Register("ProfileStop", ::ProfileStop, 0); runtime->RegisterContext(m_cx); }
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); if (!VfsFileExists(path)) { LOGERROR("File '%s' does not exist", path.string8()); return false; } CVFSFile file; PSRETURN ret = file.Load(g_VFS, path); if (ret != PSRETURN_OK) { LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret)); return false; } std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 utf16string codeUtf16(code.begin(), code.end()); uint lineNo = 1; // CompileOptions does not copy the contents of the filename string pointer. // Passing a temporary string there will cause undefined behaviour, so we create a separate string to avoid the temporary. std::string filenameStr = path.string8(); JS::RootedValue rval(m->m_cx); JS::CompileOptions opts(m->m_cx); opts.setFileAndLine(filenameStr.c_str(), lineNo); return JS::Evaluate(m->m_cx, global, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval); }
void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI* pGUI) { if(!GetGUI()) throw PSERROR_GUI_OperationNeedsGUIObject(); JSContext* cx = pGUI->GetScriptInterface()->GetContext(); JSAutoRequest rq(cx); JS::RootedValue globalVal(cx, pGUI->GetGlobalObject()); JS::RootedObject globalObj(cx, &globalVal.toObject()); const int paramCount = 1; const char* paramNames[paramCount] = { "mouse" }; // Location to report errors from CStr CodeName = GetName()+" "+Action; // Generate a unique name static int x = 0; char buf[64]; sprintf_s(buf, ARRAY_SIZE(buf), "__eventhandler%d (%s)", x++, Action.c_str()); JS::CompileOptions options(cx); options.setFileAndLine(CodeName.c_str(), 0); options.setCompileAndGo(true); JS::RootedFunction func(cx, JS_CompileFunction(cx, globalObj, buf, paramCount, paramNames, Code.c_str(), Code.length(), options)); if (!func) return; // JS will report an error message JS::RootedObject funcObj(cx, JS_GetFunctionObject(func)); SetScriptHandler(Action, funcObj); }
void IGUIObject::ScriptEvent(const CStr& Action) { auto it = m_ScriptHandlers.find(Action); if (it == m_ScriptHandlers.end()) return; JSContext* cx = m_pGUI->GetScriptInterface()->GetContext(); JSAutoRequest rq(cx); // Set up the 'mouse' parameter JS::RootedValue mouse(cx); m_pGUI->GetScriptInterface()->Eval("({})", &mouse); m_pGUI->GetScriptInterface()->SetProperty(mouse, "x", m_pGUI->m_MousePos.x, false); m_pGUI->GetScriptInterface()->SetProperty(mouse, "y", m_pGUI->m_MousePos.y, false); m_pGUI->GetScriptInterface()->SetProperty(mouse, "buttons", m_pGUI->m_MouseButtons, false); JS::AutoValueVector paramData(cx); paramData.append(mouse); JS::RootedObject obj(cx, GetJSObject()); JS::RootedValue handlerVal(cx, JS::ObjectValue(*it->second)); JS::RootedValue result(cx); bool ok = JS_CallFunctionValue(cx, obj, handlerVal, paramData, &result); if (!ok) { // We have no way to propagate the script exception, so just ignore it // and hope the caller checks JS_IsExceptionPending } }
// Return file contents as an array of lines. Assume file is UTF-8 encoded text. // // lines = readFileLines(filename); // filename: VFS filename (may include path) JS::Value JSI_VFS::ReadFileLines(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename) { JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); JSAutoRequest rq(cx); // // read file // CVFSFile file; if (file.Load(g_VFS, filename) != PSRETURN_OK) return JSVAL_NULL; CStr contents = file.DecodeUTF8(); // assume it's UTF-8 // Fix CRLF line endings. (This function will only ever be used on text files.) contents.Replace("\r\n", "\n"); // // split into array of strings (one per line) // std::stringstream ss(contents); JS::RootedObject line_array(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty())); std::string line; int cur_line = 0; while (std::getline(ss, line)) { // Decode each line as UTF-8 JS::RootedValue val(cx); ScriptInterface::ToJSVal(cx, &val, CStr(line).FromUTF8()); JS_SetElement(cx, line_array, cur_line++, val); } return JS::ObjectValue(*line_array); }
template<> void ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, JS::MutableHandleValue ret, IComponent* const& val) { JSAutoRequest rq(cx); if (val == NULL) { ret.setNull(); return; } // If this is a scripted component, just return the JS object directly JS::RootedValue instance(cx, val->GetJSInstance()); if (!instance.isNull()) { ret.set(instance); return; } // Otherwise we need to construct a wrapper object // (TODO: cache wrapper objects?) JS::RootedObject obj(cx); if (!val->NewJSObject(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface, &obj)) { // Report as an error, since scripts really shouldn't try to use unscriptable interfaces LOGERROR("IComponent does not have a scriptable interface"); ret.setUndefined(); return; } JS_SetPrivate(obj, static_cast<void*>(val)); ret.setObject(*obj); }
template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector<T>& out) { JSAutoRequest rq(cx); JS::RootedObject obj(cx); if (!v.isObject()) FAIL("Argument must be an array"); obj = &v.toObject(); if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj))) FAIL("Argument must be an array"); u32 length; if (!JS_GetArrayLength(cx, obj, &length)) FAIL("Failed to get array length"); out.reserve(length); for (u32 i = 0; i < length; ++i) { JS::RootedValue el(cx); if (!JS_GetElement(cx, obj, i, &el)) FAIL("Failed to read array element"); T el2; if (!ScriptInterface::FromJSVal<T>(cx, el, el2)) return false; out.push_back(el2); } return true; }
template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, JS::HandleValue v, Entity& out) { JSAutoRequest rq(cx); if (!v.isObject()) FAIL("Argument must be an object"); JS::RootedObject obj(cx, &v.toObject()); JS::RootedValue templateName(cx); JS::RootedValue id(cx); JS::RootedValue player(cx); JS::RootedValue position(cx); JS::RootedValue rotation(cx); // TODO: Report type errors if (!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID)) FAIL("Failed to read Entity.player property"); if (!JS_GetProperty(cx, obj, "templateName", &templateName) || !FromJSVal(cx, templateName, out.templateName)) FAIL("Failed to read Entity.templateName property"); if (!JS_GetProperty(cx, obj, "id", &id) || !FromJSVal(cx, id, out.entityID)) FAIL("Failed to read Entity.id property"); if (!JS_GetProperty(cx, obj, "position", &position) || !FromJSVal(cx, position, out.position)) FAIL("Failed to read Entity.position property"); if (!JS_GetProperty(cx, obj, "rotation", &rotation) || !FromJSVal(cx, rotation, out.rotation)) FAIL("Failed to read Entity.rotation property"); return true; }
template<> bool ScriptInterface::FromJSVal<std::wstring>(JSContext* cx, JS::HandleValue v, std::wstring& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isString() || v.isNumber(), v); // allow implicit number conversions JS::RootedString str(cx, JS::ToString(cx, v)); if (!str) FAIL("Argument must be convertible to a string"); if (JS_StringHasLatin1Chars(str)) { size_t length; JS::AutoCheckCannotGC nogc; const JS::Latin1Char* ch = JS_GetLatin1StringCharsAndLength(cx, nogc, str, &length); if (!ch) FAIL("JS_GetLatin1StringCharsAndLength failed"); out.assign(ch, ch + length); } else { size_t length; JS::AutoCheckCannotGC nogc; const char16_t* ch = JS_GetTwoByteStringCharsAndLength(cx, nogc, str, &length); if (!ch) FAIL("JS_GetTwoByteStringsCharsAndLength failed"); // out of memory out.assign(ch, ch + length); } return true; }
template<> void ScriptInterface::ToJSVal<CColor>(JSContext* cx, JS::MutableHandleValue ret, CColor const& val) { JSAutoRequest rq(cx); JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr())); if (!obj) { ret.setUndefined(); return; } JS::RootedValue r(cx); JS::RootedValue g(cx); JS::RootedValue b(cx); JS::RootedValue a(cx); ToJSVal(cx, &r, val.r); ToJSVal(cx, &g, val.g); ToJSVal(cx, &b, val.b); ToJSVal(cx, &a, val.a); JS_SetProperty(cx, obj, "r", r); JS_SetProperty(cx, obj, "g", g); JS_SetProperty(cx, obj, "b", b); JS_SetProperty(cx, obj, "a", a); ret.setObject(*obj); }
bool ScriptInterface::LoadGlobalScripts() { // Ignore this failure in tests if (!g_VFS) return false; // Load and execute *.js in the global scripts directory VfsPaths pathnames; vfs::GetPathnames(g_VFS, L"globalscripts/", L"*.js", pathnames); for (const VfsPath& path : pathnames) if (!LoadGlobalScriptFile(path)) { LOGERROR("LoadGlobalScripts: Failed to load script %s", path.string8()); return false; } JSAutoRequest rq(m->m_cx); JS::RootedValue proto(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); if (JS_GetProperty(m->m_cx, global, "Vector2Dprototype", &proto)) m->m_ScriptValCache[CACHE_VECTOR2DPROTO] = DefPersistentRooted<JS::Value>(GetJSRuntime(), proto); if (JS_GetProperty(m->m_cx, global, "Vector3Dprototype", &proto)) m->m_ScriptValCache[CACHE_VECTOR3DPROTO] = DefPersistentRooted<JS::Value>(GetJSRuntime(), proto); return true; }
IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTypeId cid) { JSContext* cx = m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); std::map<ComponentTypeId, ComponentType>::const_iterator it = m_ComponentTypesById.find(cid); if (it == m_ComponentTypesById.end()) { LOGERROR("Invalid component id %d", cid); return NULL; } const ComponentType& ct = it->second; ENSURE((size_t)ct.iid < m_ComponentsByInterface.size()); boost::unordered_map<entity_id_t, IComponent*>& emap1 = m_ComponentsByInterface[ct.iid]; if (emap1.find(ent.GetId()) != emap1.end()) { LOGERROR("Multiple components for interface %d", ct.iid); return NULL; } std::map<entity_id_t, IComponent*>& emap2 = m_ComponentsByTypeId[cid]; // If this is a scripted component, construct the appropriate JS object first JS::RootedValue obj(cx); if (ct.type == CT_Script) { m_ScriptInterface.CallConstructor(ct.ctor.get(), JS::HandleValueArray::empty(), &obj); if (obj.isNull()) { LOGERROR("Script component constructor failed"); return NULL; } } // Construct the new component IComponent* component = ct.alloc(m_ScriptInterface, obj); ENSURE(component); component->SetEntityHandle(ent); component->SetSimContext(m_SimContext); // Store a reference to the new component emap1.insert(std::make_pair(ent.GetId(), component)); emap2.insert(std::make_pair(ent.GetId(), component)); // TODO: We need to more careful about this - if an entity is constructed by a component // while we're iterating over all components, this will invalidate the iterators and everything // will break. // We probably need some kind of delayed addition, so they get pushed onto a queue and then // inserted into the world later on. (Be careful about immediation deletion in that case, too.) SEntityComponentCache* cache = ent.GetComponentCache(); ENSURE(cache != NULL && ct.iid < (int)cache->numInterfaces && cache->interfaces[ct.iid] == NULL); cache->interfaces[ct.iid] = component; return component; }
virtual void handle(boost::shared_ptr<Transceiver> &tr, boost::shared_ptr<Message> &message) { RecordType type = static_cast<RecordType>(message->type()); uint32_t fd = message->getFd(); uint16_t id = message->getId(); typename RequestsType::iterator cIt=_reqs.find(fd), cEnd=_reqs.end(); typename RequestsMap::iterator rIt,rEnd; bool isReqs=false; // cIt - connection (fd) iterator // rIt - request (req id) iterator if (cIt!=cEnd) { rIt=(*cIt).second.find(id); rEnd=(*cIt).second.end(); isReqs=true; } #ifdef FCGI_DEBUG std::cout<<"FCGI ["<<fd<<"] handle message type="<<type<<", id="<< id <<((isReqs && rIt!=rEnd) ? " FOUND" : " NOT FOUND")<<std::endl; #endif switch (type) { case BEGIN_REQUEST : if (isReqs && rIt==rEnd) { boost::shared_ptr<HandlerType> rq(new HandlerType(tr,message)); cIt->second.insert(make_pair(id, rq)); } else throw Exceptions::FcgiException("BEGIN_REQUEST on the same connection with id already exists.",0); break; case PARAMS: if (isReqs && rIt!=rEnd) { rIt->second->handleParams(message); } break; case IN: if (isReqs && rIt!=rEnd) { rIt->second->handleIN(message); } break; case DATA: if (isReqs && rIt!=rEnd) { rIt->second->handleData(message); } break; case ABORT_REQUEST: if (isReqs && rIt!=rEnd) { rIt->second->handleAbort(message); // cIt->second.erase(rIt); } break; case GET_VALUES: processGetValues(tr, message); break; default: break; } }
template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, JS::HandleValue v, u16& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); if (!JS::ToUint16(cx, v, &out)) return false; return true; }
bool ScriptInterface::Eval_(const wchar_t* code, JS::MutableHandleValue rval) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); utf16string codeUtf16(code, code+wcslen(code)); return JS_EvaluateUCScript(m->m_cx, global, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, rval); }