Пример #1
0
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);
}
Пример #2
0
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);
		}
	}
}
Пример #3
0
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);
	}
}
Пример #4
0
void CSimulation2::InitGame(JS::HandleValue data)
{
	JSContext* cx = GetScriptInterface().GetContext();
	JSAutoRequest rq(cx);
	JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject());
	GetScriptInterface().CallFunctionVoid(global, "InitGame", data);
}
Пример #5
0
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");
	}
}
Пример #6
0
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__);
}
Пример #7
0
	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));
	}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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);
}
Пример #13
0
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);
}
Пример #14
0
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);
}
Пример #15
0
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);
}
Пример #16
0
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);
}
Пример #17
0
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);
}
Пример #18
0
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);
}
Пример #19
0
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
	}
}
Пример #20
0
// 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);
}
Пример #21
0
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);
}
Пример #22
0
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;
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
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);
}
Пример #26
0
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;
}
Пример #27
0
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;
}
Пример #28
0
        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;
            }
        }
Пример #29
0
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;
}
Пример #30
0
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);
}