More exact stack rooting (CallFunction object).
Changes CallFunction and CallFunctionVoid to use a HandleValue as object parameter. Also changes some JS serialization/deserialization functions to only support the JSAPI rooted types (drop support for CScriptVal and CScriptValRooted there). Some other functions got changed too because they were closely related. Refs #2415 Refs #2462 This was SVN commit r15592.
This commit is contained in:
parent
d677a30c39
commit
5c07a25ddc
@ -172,11 +172,15 @@ void CGUIManager::LoadPage(SGUIPage& page)
|
||||
// If we're hotloading then try to grab some data from the previous page
|
||||
shared_ptr<ScriptInterface::StructuredClone> hotloadData;
|
||||
if (page.gui)
|
||||
{
|
||||
CScriptVal hotloadDataVal;
|
||||
shared_ptr<ScriptInterface> scriptInterface = page.gui->GetScriptInterface();
|
||||
scriptInterface->CallFunction(scriptInterface->GetGlobalObject(), "getHotloadData", hotloadDataVal);
|
||||
hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal.get());
|
||||
{
|
||||
shared_ptr<ScriptInterface> scriptInterface = page.gui->GetScriptInterface();
|
||||
JSContext* cx = scriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, scriptInterface->GetGlobalObject());
|
||||
JS::RootedValue hotloadDataVal(cx);
|
||||
scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal);
|
||||
hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal);
|
||||
}
|
||||
|
||||
page.inputs.clear();
|
||||
@ -228,16 +232,20 @@ void CGUIManager::LoadPage(SGUIPage& page)
|
||||
page.gui->SendEventToAll("load");
|
||||
|
||||
shared_ptr<ScriptInterface> scriptInterface = page.gui->GetScriptInterface();
|
||||
CScriptVal initDataVal;
|
||||
CScriptVal hotloadDataVal;
|
||||
JSContext* cx = scriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue initDataVal(cx);
|
||||
JS::RootedValue hotloadDataVal(cx);
|
||||
JS::RootedValue global(cx, scriptInterface->GetGlobalObject());
|
||||
if (page.initData)
|
||||
initDataVal = scriptInterface->ReadStructuredClone(page.initData);
|
||||
initDataVal.set(scriptInterface->ReadStructuredClone(page.initData));
|
||||
if (hotloadData)
|
||||
hotloadDataVal = scriptInterface->ReadStructuredClone(hotloadData);
|
||||
hotloadDataVal.set(scriptInterface->ReadStructuredClone(hotloadData));
|
||||
|
||||
// Call the init() function
|
||||
if (!scriptInterface->CallFunctionVoid(
|
||||
scriptInterface->GetGlobalObject(),
|
||||
global,
|
||||
"init",
|
||||
initDataVal,
|
||||
hotloadDataVal)
|
||||
@ -269,8 +277,9 @@ CScriptVal CGUIManager::GetSavedGameData(ScriptInterface*& pPageScriptInterface)
|
||||
JSContext* cx = top()->GetScriptInterface()->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
JS::RootedValue data(cx);
|
||||
if (!top()->GetScriptInterface()->CallFunction(top()->GetGlobalObject(), "getSavedGameData", &data))
|
||||
if (!top()->GetScriptInterface()->CallFunction(global, "getSavedGameData", &data))
|
||||
LOGERROR(L"Failed to call getSavedGameData() on the current GUI page");
|
||||
pPageScriptInterface = GetScriptInterface().get();
|
||||
return CScriptVal(data);
|
||||
@ -278,15 +287,24 @@ CScriptVal CGUIManager::GetSavedGameData(ScriptInterface*& pPageScriptInterface)
|
||||
|
||||
std::string CGUIManager::GetSavedGameData()
|
||||
{
|
||||
CScriptVal data;
|
||||
top()->GetScriptInterface()->CallFunction(top()->GetGlobalObject(), "getSavedGameData", data);
|
||||
return top()->GetScriptInterface()->StringifyJSON(data.get(), false);
|
||||
shared_ptr<ScriptInterface> scriptInterface = top()->GetScriptInterface();
|
||||
JSContext* cx = scriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue data(cx);
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
scriptInterface->CallFunction(global, "getSavedGameData", &data);
|
||||
return scriptInterface->StringifyJSON(data, false);
|
||||
}
|
||||
|
||||
void CGUIManager::RestoreSavedGameData(std::string jsonData)
|
||||
{
|
||||
top()->GetScriptInterface()->CallFunctionVoid(top()->GetGlobalObject(), "restoreSavedGameData",
|
||||
top()->GetScriptInterface()->ParseJSON(jsonData));
|
||||
shared_ptr<ScriptInterface> scriptInterface = top()->GetScriptInterface();
|
||||
JSContext* cx = scriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
scriptInterface->CallFunctionVoid(global, "restoreSavedGameData", scriptInterface->ParseJSON(jsonData));
|
||||
}
|
||||
|
||||
InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
@ -297,12 +315,17 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
// visible game area), sometimes they'll want to intercepts events before the GUI (e.g.
|
||||
// to capture all mouse events until a mouseup after dragging).
|
||||
// So we call two separate handler functions:
|
||||
|
||||
shared_ptr<ScriptInterface> scriptInterface = top()->GetScriptInterface();
|
||||
JSContext* cx = scriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
bool handled;
|
||||
|
||||
{
|
||||
PROFILE("handleInputBeforeGui");
|
||||
if (top()->GetScriptInterface()->CallFunction(top()->GetGlobalObject(), "handleInputBeforeGui", *ev, top()->FindObjectUnderMouse(), handled))
|
||||
if (scriptInterface->CallFunction(global, "handleInputBeforeGui", *ev, top()->FindObjectUnderMouse(), handled))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
@ -316,7 +339,8 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
|
||||
{
|
||||
PROFILE("handleInputAfterGui");
|
||||
if (top()->GetScriptInterface()->CallFunction(top()->GetGlobalObject(), "handleInputAfterGui", *ev, handled)) if (handled)
|
||||
if (scriptInterface->CallFunction(global, "handleInputAfterGui", *ev, handled))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -124,13 +124,16 @@ u8* CSimulationMessage::Serialize(u8* pBuffer) const
|
||||
{
|
||||
// TODO: ought to handle serialization exceptions
|
||||
// TODO: ought to represent common commands more efficiently
|
||||
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpData(cx, m_Data.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
u8* pos = CNetMessage::Serialize(pBuffer);
|
||||
CBufferBinarySerializer serializer(*m_ScriptInterface, pos);
|
||||
serializer.NumberU32_Unbounded("client", m_Client);
|
||||
serializer.NumberI32_Unbounded("player", m_Player);
|
||||
serializer.NumberU32_Unbounded("turn", m_Turn);
|
||||
serializer.ScriptVal("command", m_Data);
|
||||
serializer.ScriptVal("command", tmpData);
|
||||
return serializer.GetBuffer();
|
||||
}
|
||||
|
||||
@ -138,14 +141,18 @@ const u8* CSimulationMessage::Deserialize(const u8* pStart, const u8* pEnd)
|
||||
{
|
||||
// TODO: ought to handle serialization exceptions
|
||||
// TODO: ought to represent common commands more efficiently
|
||||
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue tmpData(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
const u8* pos = CNetMessage::Deserialize(pStart, pEnd);
|
||||
std::istringstream stream(std::string(pos, pEnd));
|
||||
CStdDeserializer deserializer(*m_ScriptInterface, stream);
|
||||
deserializer.NumberU32_Unbounded("client", m_Client);
|
||||
deserializer.NumberI32_Unbounded("player", m_Player);
|
||||
deserializer.NumberU32_Unbounded("turn", m_Turn);
|
||||
deserializer.ScriptVal("command", m_Data);
|
||||
deserializer.ScriptVal("command", &tmpData);
|
||||
m_Data = CScriptValRooted(cx, tmpData);
|
||||
return pEnd;
|
||||
}
|
||||
|
||||
@ -153,12 +160,15 @@ size_t CSimulationMessage::GetSerializedLength() const
|
||||
{
|
||||
// TODO: serializing twice is stupidly inefficient - we should just
|
||||
// do it once, store the result, and use it here and in Serialize
|
||||
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpData(cx, m_Data.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
CLengthBinarySerializer serializer(*m_ScriptInterface);
|
||||
serializer.NumberU32_Unbounded("client", m_Client);
|
||||
serializer.NumberI32_Unbounded("player", m_Player);
|
||||
serializer.NumberU32_Unbounded("turn", m_Turn);
|
||||
serializer.ScriptVal("command", m_Data);
|
||||
serializer.ScriptVal("command", tmpData);
|
||||
return CNetMessage::GetSerializedLength() + serializer.GetLength();
|
||||
}
|
||||
|
||||
@ -186,28 +196,39 @@ CGameSetupMessage::CGameSetupMessage(ScriptInterface& scriptInterface, jsval dat
|
||||
u8* CGameSetupMessage::Serialize(u8* pBuffer) const
|
||||
{
|
||||
// TODO: ought to handle serialization exceptions
|
||||
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpData(cx, m_Data.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
u8* pos = CNetMessage::Serialize(pBuffer);
|
||||
CBufferBinarySerializer serializer(m_ScriptInterface, pos);
|
||||
serializer.ScriptVal("command", m_Data);
|
||||
serializer.ScriptVal("command", tmpData);
|
||||
return serializer.GetBuffer();
|
||||
}
|
||||
|
||||
const u8* CGameSetupMessage::Deserialize(const u8* pStart, const u8* pEnd)
|
||||
{
|
||||
// TODO: ought to handle serialization exceptions
|
||||
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpData(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
const u8* pos = CNetMessage::Deserialize(pStart, pEnd);
|
||||
std::istringstream stream(std::string(pos, pEnd));
|
||||
CStdDeserializer deserializer(m_ScriptInterface, stream);
|
||||
deserializer.ScriptVal("command", m_Data);
|
||||
deserializer.ScriptVal("command", &tmpData);
|
||||
m_Data = CScriptValRooted(cx, tmpData);
|
||||
return pEnd;
|
||||
}
|
||||
|
||||
size_t CGameSetupMessage::GetSerializedLength() const
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpData(cx, m_Data.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
CLengthBinarySerializer serializer(m_ScriptInterface);
|
||||
serializer.ScriptVal("command", m_Data);
|
||||
serializer.ScriptVal("command", tmpData);
|
||||
return CNetMessage::GetSerializedLength() + serializer.GetLength();
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,12 @@ public:
|
||||
void test_sim()
|
||||
{
|
||||
ScriptInterface script("Test", "Test", g_ScriptRuntime);
|
||||
CScriptValRooted val;
|
||||
script.Eval("[4]", val);
|
||||
CSimulationMessage msg(script, 1, 2, 3, val.get());
|
||||
JSContext* cx = script.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue val(cx);
|
||||
script.Eval("[4]", &val);
|
||||
CSimulationMessage msg(script, 1, 2, 3, val);
|
||||
TS_ASSERT_STR_EQUALS(msg.ToString(), "CSimulationMessage { m_Client: 1, m_Player: 2, m_Turn: 3, m_Data: [4] }");
|
||||
|
||||
size_t len = msg.GetSerializedLength();
|
||||
|
@ -323,8 +323,8 @@ void RunHardwareDetection()
|
||||
g_UserReporter.SubmitReport("hwdetect", 11, scriptInterface.StringifyJSON(settings, false));
|
||||
|
||||
// Run the detection script:
|
||||
|
||||
scriptInterface.CallFunctionVoid(scriptInterface.GetGlobalObject(), "RunHardwareDetection", settings);
|
||||
JS::RootedValue global(cx, scriptInterface.GetGlobalObject());
|
||||
scriptInterface.CallFunctionVoid(global, "RunHardwareDetection", settings);
|
||||
}
|
||||
|
||||
static void ReportGLLimits(ScriptInterface& scriptInterface, JS::HandleValue settings)
|
||||
|
@ -74,7 +74,7 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
// Call the named property on the given object
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) R& ret);
|
||||
bool CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) R& ret);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
@ -83,7 +83,7 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
// (as people would expect it to work based on the SpiderMonkey rooting guide).
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) JS::Rooted<R>* ret);
|
||||
bool CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) JS::Rooted<R>* ret);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
@ -91,7 +91,7 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
// without requiring implicit conversion.
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) JS::MutableHandle<R> ret);
|
||||
bool CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) JS::MutableHandle<R> ret);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
|
@ -129,16 +129,15 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) R& ret) \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) R& ret) \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::RootedValue jsRet(cx); \
|
||||
JS::RootedValue val1(cx, val); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
bool ok = CallFunction_(val1, name, argv.length(), argv.begin(), &jsRet); \
|
||||
bool ok = CallFunction_(val, name, argv.length(), argv.begin(), &jsRet); \
|
||||
if (!ok) \
|
||||
return false; \
|
||||
return FromJSVal(cx, jsRet, ret); \
|
||||
@ -148,16 +147,15 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) JS::Rooted<R>* ret) \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) JS::Rooted<R>* ret) \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::MutableHandle<R> jsRet(ret); \
|
||||
JS::RootedValue val1(cx, val); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
bool ok = CallFunction_(val1, name, argv.length(), argv.begin(), jsRet); \
|
||||
bool ok = CallFunction_(val, name, argv.length(), argv.begin(), jsRet); \
|
||||
if (!ok) \
|
||||
return false; \
|
||||
return true; \
|
||||
@ -167,15 +165,14 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(jsval val, const char* name, T0_A0_CONST_REF(z,i) JS::MutableHandle<R> ret) \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, T0_A0_CONST_REF(z,i) JS::MutableHandle<R> ret) \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::RootedValue val1(cx, val); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
bool ok = CallFunction_(val1, name, argv.length(), argv.begin(), ret); \
|
||||
bool ok = CallFunction_(val, name, argv.length(), argv.begin(), ret); \
|
||||
if (!ok) \
|
||||
return false; \
|
||||
return true; \
|
||||
|
@ -964,12 +964,11 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string & typeName)
|
||||
return JS_NewObject(m->m_cx, (*it).second.m_Class, prototype, NULL);
|
||||
}
|
||||
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name)
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name)
|
||||
{
|
||||
JSAutoRequest rq(m->m_cx);
|
||||
JS::RootedValue jsRet(m->m_cx);
|
||||
JS::RootedValue val1(m->m_cx, val);
|
||||
return CallFunction_(val1, name, 0, NULL, &jsRet);
|
||||
return CallFunction_(val, name, 0, NULL, &jsRet);
|
||||
}
|
||||
|
||||
bool ScriptInterface::CallFunction_(JS::HandleValue val, const char* name, uint argc, jsval* argv, JS::MutableHandleValue ret)
|
||||
@ -1361,7 +1360,8 @@ std::string ScriptInterface::StringifyJSON(jsval obj, bool indent)
|
||||
std::wstring ScriptInterface::ToString(jsval obj, bool pretty)
|
||||
{
|
||||
JSAutoRequest rq(m->m_cx);
|
||||
if (JSVAL_IS_VOID(obj))
|
||||
|
||||
if (obj.isUndefined())
|
||||
return L"(void 0)";
|
||||
|
||||
// Try to stringify as JSON if possible
|
||||
@ -1373,7 +1373,7 @@ std::wstring ScriptInterface::ToString(jsval obj, bool pretty)
|
||||
// Temporary disable the error reporter, so we don't print complaints about cyclic values
|
||||
JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL);
|
||||
|
||||
JSBool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str);
|
||||
JSBool ok = JS_Stringify(m->m_cx, &obj, NULL, JS::NumberValue(2), &StringifierW::callback, &str);
|
||||
|
||||
// Restore error reporter
|
||||
JS_SetErrorReporter(m->m_cx, er);
|
||||
@ -1389,7 +1389,8 @@ std::wstring ScriptInterface::ToString(jsval obj, bool pretty)
|
||||
// so fall back to obj.toSource()
|
||||
|
||||
std::wstring source = L"(error)";
|
||||
CallFunction(obj, "toSource", source);
|
||||
JS::RootedValue tmpObj(m->m_cx, obj); // TODO: pass Handle as argument already
|
||||
CallFunction(tmpObj, "toSource", source);
|
||||
return source;
|
||||
}
|
||||
|
||||
|
@ -150,25 +150,25 @@ public:
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 0 arguments
|
||||
*/
|
||||
bool CallFunctionVoid(jsval val, const char* name);
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 1 argument
|
||||
*/
|
||||
template<typename T0>
|
||||
bool CallFunctionVoid(jsval val, const char* name, const T0& a0);
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 2 arguments
|
||||
*/
|
||||
template<typename T0, typename T1>
|
||||
bool CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1);
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 3 arguments
|
||||
*/
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2);
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1, const T2& a2);
|
||||
|
||||
JSObject* CreateCustomObject(const std::string & typeName);
|
||||
void DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
|
||||
@ -480,45 +480,42 @@ inline void ScriptInterface::AssignOrToJSVal<JS::Value>(JS::MutableHandleValue h
|
||||
}
|
||||
|
||||
template<typename T0>
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0)
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::RootedValue val1(cx, val);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(1);
|
||||
AssignOrToJSVal(argv.handleAt(0), a0);
|
||||
return CallFunction_(val1, name, 1, argv.begin(), &jsRet);
|
||||
return CallFunction_(val, name, 1, argv.begin(), &jsRet);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1)
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::RootedValue val1(cx, val);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(2);
|
||||
AssignOrToJSVal(argv.handleAt(0), a0);
|
||||
AssignOrToJSVal(argv.handleAt(1), a1);
|
||||
return CallFunction_(val1, name, 2, argv.begin(), &jsRet);
|
||||
return CallFunction_(val, name, 2, argv.begin(), &jsRet);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2)
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1, const T2& a2)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::RootedValue val1(cx, val);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(3);
|
||||
AssignOrToJSVal(argv.handleAt(0), a0);
|
||||
AssignOrToJSVal(argv.handleAt(1), a1);
|
||||
AssignOrToJSVal(argv.handleAt(2), a2);
|
||||
return CallFunction_(val1, name, 3, argv.begin(), &jsRet);
|
||||
return CallFunction_(val, name, 3, argv.begin(), &jsRet);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -40,7 +40,8 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
// We want to convert values to strings, but can't just call toSource() on them
|
||||
// since they might not be objects. So just use uneval.
|
||||
std::string source;
|
||||
TS_ASSERT(script.CallFunction(JS::ObjectValue(*JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source));
|
||||
JS::RootedValue global(cx, script.GetGlobalObject());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", v1, source));
|
||||
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
@ -56,7 +57,8 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
ScriptInterface::ToJSVal(cx, &v1, value);
|
||||
|
||||
std::string source;
|
||||
TS_ASSERT(script.CallFunction(JS::ObjectValue(*JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source));
|
||||
JS::RootedValue global(cx, script.GetGlobalObject());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", v1, source));
|
||||
|
||||
if (expected)
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
|
@ -65,14 +65,21 @@ public:
|
||||
ScriptInterface script1("Test", "Test", g_ScriptRuntime);
|
||||
ScriptInterface script2("Test", "Test", g_ScriptRuntime);
|
||||
|
||||
CScriptVal obj1;
|
||||
TS_ASSERT(script1.Eval("({'x': 123, 'y': [1, 1.5, '2', 'test', undefined, null, true, false]})", obj1));
|
||||
JSContext* cx1 = script1.GetContext();
|
||||
JSAutoRequest rq1(cx1);
|
||||
JS::RootedValue obj1(cx1);
|
||||
TS_ASSERT(script1.Eval("({'x': 123, 'y': [1, 1.5, '2', 'test', undefined, null, true, false]})", &obj1));
|
||||
|
||||
CScriptVal obj2 = script2.CloneValueFromOtherContext(script1, obj1.get());
|
||||
{
|
||||
JSContext* cx2 = script2.GetContext();
|
||||
JSAutoRequest rq2(cx2);
|
||||
|
||||
JS::RootedValue obj2(cx2, script2.CloneValueFromOtherContext(script1, obj1));
|
||||
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2.get(), "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:[1, 1.5, \"2\", \"test\", (void 0), null, true, false]})");
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2, "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:[1, 1.5, \"2\", \"test\", (void 0), null, true, false]})");
|
||||
}
|
||||
}
|
||||
|
||||
void test_clone_getters()
|
||||
@ -81,14 +88,22 @@ public:
|
||||
ScriptInterface script1("Test", "Test", g_ScriptRuntime);
|
||||
ScriptInterface script2("Test", "Test", g_ScriptRuntime);
|
||||
|
||||
CScriptVal obj1;
|
||||
TS_ASSERT(script1.Eval("var s = '?'; var v = ({get x() { return 123 }, 'y': {'w':{get z() { delete v.y; delete v.n; v = null; s += s; return 4 }}}, 'n': 100}); v", obj1));
|
||||
JSContext* cx1 = script1.GetContext();
|
||||
JSAutoRequest rq1(cx1);
|
||||
|
||||
JS::RootedValue obj1(cx1);
|
||||
TS_ASSERT(script1.Eval("var s = '?'; var v = ({get x() { return 123 }, 'y': {'w':{get z() { delete v.y; delete v.n; v = null; s += s; return 4 }}}, 'n': 100}); v", &obj1));
|
||||
|
||||
CScriptVal obj2 = script2.CloneValueFromOtherContext(script1, obj1.get());
|
||||
{
|
||||
JSContext* cx2 = script2.GetContext();
|
||||
JSAutoRequest rq2(cx2);
|
||||
|
||||
JS::RootedValue obj2(cx2, script2.CloneValueFromOtherContext(script1, obj1));
|
||||
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2.get(), "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:{w:{z:4}}})");
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2, "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:{w:{z:4}}})");
|
||||
}
|
||||
}
|
||||
|
||||
void test_clone_cyclic()
|
||||
@ -96,24 +111,29 @@ public:
|
||||
ScriptInterface script1("Test", "Test", g_ScriptRuntime);
|
||||
ScriptInterface script2("Test", "Test", g_ScriptRuntime);
|
||||
|
||||
CScriptVal obj1;
|
||||
TS_ASSERT(script1.Eval("var x = []; x[0] = x; ({'a': x, 'b': x})", obj1));
|
||||
JSContext* cx1 = script1.GetContext();
|
||||
JSAutoRequest rq1(cx1);
|
||||
|
||||
JS::RootedValue obj1(cx1);
|
||||
TS_ASSERT(script1.Eval("var x = []; x[0] = x; ({'a': x, 'b': x})", &obj1));
|
||||
|
||||
CScriptVal obj2 = script2.CloneValueFromOtherContext(script1, obj1.get());
|
||||
{
|
||||
JSContext* cx2 = script2.GetContext();
|
||||
JSAutoRequest rq(cx2);
|
||||
JS::RootedValue obj2(cx2, script2.CloneValueFromOtherContext(script1, obj1));
|
||||
|
||||
// Use JSAPI function to check if the values of the properties "a", "b" are equals a.x[0]
|
||||
JSContext* cx2 = script2.GetContext();
|
||||
JSAutoRequest rq(cx2);
|
||||
JS::RootedValue prop_a(cx2);
|
||||
JS::RootedValue prop_b(cx2);
|
||||
JS::RootedValue prop_x1(cx2);
|
||||
TS_ASSERT(JS_GetProperty(cx2, &(obj2.get().toObject()), "a", prop_a.address()));
|
||||
TS_ASSERT(JS_GetProperty(cx2, &(obj2.get().toObject()), "b", prop_b.address()));
|
||||
TS_ASSERT(prop_a.get().isObject());
|
||||
TS_ASSERT(prop_b.get().isObject());
|
||||
TS_ASSERT(JS_GetProperty(cx2, &(prop_a.get().toObject()), "0", prop_x1.address()));
|
||||
TS_ASSERT_EQUALS(prop_x1.get(), prop_a.get());
|
||||
TS_ASSERT_EQUALS(prop_x1.get(), prop_b.get());
|
||||
// Use JSAPI function to check if the values of the properties "a", "b" are equals a.x[0]
|
||||
JS::RootedValue prop_a(cx2);
|
||||
JS::RootedValue prop_b(cx2);
|
||||
JS::RootedValue prop_x1(cx2);
|
||||
TS_ASSERT(script2.GetProperty(obj2, "a", &prop_a));
|
||||
TS_ASSERT(script2.GetProperty(obj2, "b", &prop_b));
|
||||
TS_ASSERT(prop_a.isObject());
|
||||
TS_ASSERT(prop_b.isObject());
|
||||
TS_ASSERT(script2.GetProperty(prop_a, "0", &prop_x1));
|
||||
TS_ASSERT_EQUALS(prop_x1.get(), prop_a.get());
|
||||
TS_ASSERT_EQUALS(prop_x1.get(), prop_b.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -639,12 +639,18 @@ ScriptInterface& CSimulation2::GetScriptInterface() const
|
||||
|
||||
void CSimulation2::ReplaceSkirmishGlobals()
|
||||
{
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "ReplaceSkirmishGlobals");
|
||||
JSContext* cx = GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject());
|
||||
GetScriptInterface().CallFunctionVoid(global, "ReplaceSkirmishGlobals");
|
||||
}
|
||||
|
||||
void CSimulation2::InitGame(const CScriptVal& data)
|
||||
{
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "InitGame", data);
|
||||
JSContext* cx = GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject());
|
||||
GetScriptInterface().CallFunctionVoid(global, "InitGame", data);
|
||||
}
|
||||
|
||||
void CSimulation2::Update(int turnLength)
|
||||
@ -728,7 +734,10 @@ CScriptVal CSimulation2::GetMapSettings()
|
||||
|
||||
void CSimulation2::LoadPlayerSettings(bool newPlayers)
|
||||
{
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadPlayerSettings", m->m_MapSettings, newPlayers);
|
||||
JSContext* cx = GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject());
|
||||
GetScriptInterface().CallFunctionVoid(global, "LoadPlayerSettings", m->m_MapSettings, newPlayers);
|
||||
}
|
||||
|
||||
void CSimulation2::LoadMapSettings()
|
||||
@ -736,10 +745,11 @@ void CSimulation2::LoadMapSettings()
|
||||
JSContext* cx = GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, GetScriptInterface().GetGlobalObject());
|
||||
JS::RootedValue tmpMapSettings(cx, m->m_MapSettings.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
// Initialize here instead of in Update()
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadMapSettings", tmpMapSettings);
|
||||
GetScriptInterface().CallFunctionVoid(global, "LoadMapSettings", tmpMapSettings);
|
||||
|
||||
if (!m->m_StartupScript.empty())
|
||||
GetScriptInterface().LoadScript(L"map startup script", m->m_StartupScript);
|
||||
|
@ -180,20 +180,32 @@ private:
|
||||
|
||||
void Run(JS::HandleValue state, int playerID)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpObj(cx, m_Obj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID);
|
||||
m_ScriptInterface->CallFunctionVoid(tmpObj, "HandleMessage", state, playerID);
|
||||
}
|
||||
// overloaded with a sharedAI part.
|
||||
// javascript can handle both natively on the same function.
|
||||
void Run(JS::HandleValue state, int playerID, CScriptValRooted SharedAI)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpObj(cx, m_Obj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID, SharedAI);
|
||||
m_ScriptInterface->CallFunctionVoid(tmpObj, "HandleMessage", state, playerID, SharedAI);
|
||||
}
|
||||
void InitAI(JS::HandleValue state, CScriptValRooted SharedAI)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpObj(cx, m_Obj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "Init", state, m_Player, SharedAI);
|
||||
m_ScriptInterface->CallFunctionVoid(tmpObj, "Init", state, m_Player, SharedAI);
|
||||
}
|
||||
|
||||
CAIWorker& m_Worker;
|
||||
@ -470,7 +482,9 @@ public:
|
||||
m_ScriptInterface->SetProperty(state, "passabilityMap", m_PassabilityMapVal, true);
|
||||
m_ScriptInterface->SetProperty(state, "territoryMap", m_TerritoryMapVal, true);
|
||||
|
||||
m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "init", state);
|
||||
JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
m_ScriptInterface->CallFunctionVoid(tmpSharedAIObj, "init", state);
|
||||
|
||||
for (size_t i = 0; i < m_Players.size(); ++i)
|
||||
{
|
||||
@ -593,8 +607,9 @@ public:
|
||||
serializer.Bool("useSharedScript", m_HasSharedComponent);
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
CScriptVal sharedData;
|
||||
if (!m_ScriptInterface->CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
|
||||
JS::RootedValue sharedData(cx);
|
||||
JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
if (!m_ScriptInterface->CallFunction(tmpSharedAIObj, "Serialize", &sharedData))
|
||||
LOGERROR(L"AI shared script Serialize call failed");
|
||||
serializer.ScriptVal("sharedData", sharedData);
|
||||
}
|
||||
@ -607,7 +622,7 @@ public:
|
||||
serializer.NumberU32_Unbounded("num commands", (u32)m_Players[i]->m_Commands.size());
|
||||
for (size_t j = 0; j < m_Players[i]->m_Commands.size(); ++j)
|
||||
{
|
||||
CScriptVal val = m_ScriptInterface->ReadStructuredClone(m_Players[i]->m_Commands[j]);
|
||||
JS::RootedValue val(cx, m_ScriptInterface->ReadStructuredClone(m_Players[i]->m_Commands[j]));
|
||||
serializer.ScriptVal("command", val);
|
||||
}
|
||||
|
||||
@ -654,9 +669,10 @@ public:
|
||||
TryLoadSharedComponent(false);
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
CScriptVal sharedData;
|
||||
deserializer.ScriptVal("sharedData", sharedData);
|
||||
if (!m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
|
||||
JS::RootedValue sharedData(cx);
|
||||
JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31
|
||||
deserializer.ScriptVal("sharedData", &sharedData);
|
||||
if (!m_ScriptInterface->CallFunctionVoid(tmpSharedAIObj, "Deserialize", sharedData))
|
||||
LOGERROR(L"AI shared script Deserialize call failed");
|
||||
}
|
||||
|
||||
@ -676,9 +692,9 @@ public:
|
||||
m_Players.back()->m_Commands.reserve(numCommands);
|
||||
for (size_t j = 0; j < numCommands; ++j)
|
||||
{
|
||||
CScriptVal val;
|
||||
deserializer.ScriptVal("command", val);
|
||||
m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val.get()));
|
||||
JS::RootedValue val(cx);
|
||||
deserializer.ScriptVal("command", &val);
|
||||
m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val));
|
||||
}
|
||||
|
||||
// TODO: this is yucky but necessary while the AIs are sharing data between contexts;
|
||||
@ -691,8 +707,8 @@ public:
|
||||
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(tmpPlayerObj, "Deserialize");
|
||||
if (hasCustomDeserialize)
|
||||
{
|
||||
CScriptVal scriptData;
|
||||
deserializer.ScriptVal("data", scriptData);
|
||||
JS::RootedValue scriptData(cx);
|
||||
deserializer.ScriptVal("data", &scriptData);
|
||||
if (m_Players[i]->m_UseSharedComponent)
|
||||
{
|
||||
if (!m_ScriptInterface->CallFunctionVoid(tmpPlayerObj, "Deserialize", scriptData, m_SharedAIObj))
|
||||
@ -705,7 +721,8 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
deserializer.ScriptVal("data", tmpPlayerObj.get());
|
||||
deserializer.ScriptVal("data", &tmpPlayerObj);
|
||||
m_Players.back()->m_Obj = CScriptValRooted(cx, tmpPlayerObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -761,7 +778,8 @@ private:
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
PROFILE3("AI run shared component");
|
||||
m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "onUpdate", state);
|
||||
JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31
|
||||
m_ScriptInterface->CallFunctionVoid(tmpSharedAIObj, "onUpdate", state);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_Players.size(); ++i)
|
||||
|
@ -50,25 +50,33 @@ public:
|
||||
|
||||
virtual void Serialize(ISerializer& serialize)
|
||||
{
|
||||
JSContext* cx = GetSimContext().GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue tmpRoot(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
serialize.NumberU32_Unbounded("num commands", (u32)m_LocalQueue.size());
|
||||
for (size_t i = 0; i < m_LocalQueue.size(); ++i)
|
||||
{
|
||||
tmpRoot.set(m_LocalQueue[i].data.get());
|
||||
serialize.NumberI32_Unbounded("player", m_LocalQueue[i].player);
|
||||
serialize.ScriptVal("data", m_LocalQueue[i].data.get());
|
||||
serialize.ScriptVal("data", tmpRoot);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize)
|
||||
{
|
||||
JSContext* cx = GetSimContext().GetScriptInterface().GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
u32 numCmds;
|
||||
deserialize.NumberU32_Unbounded("num commands", numCmds);
|
||||
for (size_t i = 0; i < numCmds; ++i)
|
||||
{
|
||||
i32 player;
|
||||
CScriptValRooted data;
|
||||
JS::RootedValue data(cx);
|
||||
deserialize.NumberI32_Unbounded("player", player);
|
||||
deserialize.ScriptVal("data", data);
|
||||
SimulationCommand c = { player, data };
|
||||
deserialize.ScriptVal("data", &data);
|
||||
SimulationCommand c = { player, CScriptValRooted(cx, data) };
|
||||
m_LocalQueue.push_back(c);
|
||||
}
|
||||
}
|
||||
@ -96,20 +104,23 @@ public:
|
||||
virtual void FlushTurn(const std::vector<SimulationCommand>& commands)
|
||||
{
|
||||
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
|
||||
|
||||
JSContext* cx = scriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue global(cx, scriptInterface.GetGlobalObject());
|
||||
std::vector<SimulationCommand> localCommands;
|
||||
m_LocalQueue.swap(localCommands);
|
||||
|
||||
for (size_t i = 0; i < localCommands.size(); ++i)
|
||||
{
|
||||
bool ok = scriptInterface.CallFunctionVoid(scriptInterface.GetGlobalObject(), "ProcessCommand", localCommands[i].player, localCommands[i].data);
|
||||
bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", localCommands[i].player, localCommands[i].data);
|
||||
if (!ok)
|
||||
LOGERROR(L"Failed to call ProcessCommand() global script function");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
bool ok = scriptInterface.CallFunctionVoid(scriptInterface.GetGlobalObject(), "ProcessCommand", commands[i].player, commands[i].data);
|
||||
bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", commands[i].player, commands[i].data);
|
||||
if (!ok)
|
||||
LOGERROR(L"Failed to call ProcessCommand() global script function");
|
||||
}
|
||||
|
@ -64,11 +64,15 @@ void CComponentTypeScript::Deinit()
|
||||
|
||||
void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
const char* name = global ? msg.GetScriptGlobalHandlerName() : msg.GetScriptHandlerName();
|
||||
|
||||
CScriptVal msgVal = msg.ToJSValCached(m_ScriptInterface);
|
||||
JS::RootedValue msgVal(cx, msg.ToJSValCached(m_ScriptInterface));
|
||||
|
||||
if (!m_ScriptInterface.CallFunctionVoid(m_Instance.get(), name, msgVal))
|
||||
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
if (!m_ScriptInterface.CallFunctionVoid(tmpInstance, name, msgVal))
|
||||
LOGERROR(L"Script message handler %hs failed", name);
|
||||
}
|
||||
|
||||
@ -77,19 +81,23 @@ void CComponentTypeScript::Serialize(ISerializer& serialize)
|
||||
// If the component set Serialize = null, then do no work here
|
||||
if (m_HasNullSerialize)
|
||||
return;
|
||||
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
|
||||
|
||||
// Support a custom "Serialize" function, which returns a new object that will be
|
||||
// serialized instead of the component itself
|
||||
if (m_HasCustomSerialize)
|
||||
{
|
||||
CScriptVal val;
|
||||
if (!m_ScriptInterface.CallFunction(m_Instance.get(), "Serialize", val))
|
||||
JS::RootedValue val(cx);
|
||||
if (!m_ScriptInterface.CallFunction(tmpInstance, "Serialize", &val))
|
||||
LOGERROR(L"Script Serialize call failed");
|
||||
serialize.ScriptVal("object", val);
|
||||
}
|
||||
else
|
||||
{
|
||||
serialize.ScriptVal("object", m_Instance.get());
|
||||
serialize.ScriptVal("object", tmpInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +115,7 @@ void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserialize
|
||||
|
||||
// If Serialize = null, we'll still call Deserialize but with undefined argument
|
||||
if (!m_HasNullSerialize)
|
||||
deserialize.ScriptVal("object", val.get());
|
||||
deserialize.ScriptVal("object", &val);
|
||||
|
||||
if (!m_ScriptInterface.CallFunctionVoid(tmpInstance, "Deserialize", val))
|
||||
LOGERROR(L"Script Deserialize call failed");
|
||||
@ -118,7 +126,7 @@ void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserialize
|
||||
{
|
||||
// Use ScriptObjectAppend so we don't lose the carefully-constructed
|
||||
// prototype/parent of this object
|
||||
deserialize.ScriptObjectAppend("object", m_Instance.getRef());
|
||||
deserialize.ScriptObjectAppend("object", tmpInstance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,17 @@ public:
|
||||
// void CallVoid(const char* funcname);
|
||||
// template<typename T0> void CallVoid(const char* funcname, const T0& a0);
|
||||
// ...
|
||||
|
||||
// TODO: Check if these temporary roots can be removed after SpiderMonkey 31 upgrade
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(i, typename T)> \
|
||||
R Call(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) \
|
||||
{ \
|
||||
JSContext* cx = m_ScriptInterface.GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::RootedValue tmpInstance(cx, m_Instance.get()); \
|
||||
R ret; \
|
||||
if (m_ScriptInterface.CallFunction(m_Instance.get(), funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
|
||||
if (m_ScriptInterface.CallFunction(tmpInstance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
|
||||
return ret; \
|
||||
LOGERROR(L"Error calling component script function %hs", funcname); \
|
||||
return R(); \
|
||||
@ -65,7 +70,10 @@ public:
|
||||
BOOST_PP_IF(i, template<, ) BOOST_PP_ENUM_PARAMS(i, typename T) BOOST_PP_IF(i, >, ) \
|
||||
void CallVoid(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) \
|
||||
{ \
|
||||
if (m_ScriptInterface.CallFunctionVoid(m_Instance.get(), funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
|
||||
JSContext* cx = m_ScriptInterface.GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::RootedValue tmpInstance(cx, m_Instance.get()); \
|
||||
if (m_ScriptInterface.CallFunctionVoid(tmpInstance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
|
||||
return; \
|
||||
LOGERROR(L"Error calling component script function %hs", funcname); \
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(ScriptInterface& script
|
||||
{
|
||||
}
|
||||
|
||||
void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
|
||||
void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
@ -119,7 +119,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
|
||||
|
||||
// Now handle its array buffer
|
||||
// this may be a backref, since ArrayBuffers can be shared by multiple views
|
||||
HandleScriptVal(JS::ObjectValue(*JS_GetArrayBufferViewBuffer(obj)));
|
||||
JS::RootedValue bufferVal(cx, JS::ObjectValue(*JS_GetArrayBufferViewBuffer(obj)));
|
||||
HandleScriptVal(bufferVal);
|
||||
break;
|
||||
}
|
||||
else if (JS_IsArrayBufferObject(obj))
|
||||
@ -182,10 +183,10 @@ void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
|
||||
// If serialize is null, so don't serialize anything more
|
||||
if (!serialize.isNull())
|
||||
{
|
||||
CScriptValRooted data;
|
||||
if (!m_ScriptInterface.CallFunction(val, "Serialize", data))
|
||||
JS::RootedValue data(cx);
|
||||
if (!m_ScriptInterface.CallFunction(val, "Serialize", &data))
|
||||
throw PSERROR_Serialize_ScriptError("Prototype Serialize function failed");
|
||||
HandleScriptVal(data.get());
|
||||
HandleScriptVal(data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer);
|
||||
|
||||
void ScriptString(const char* name, JSString* string);
|
||||
void HandleScriptVal(jsval val);
|
||||
void HandleScriptVal(JS::HandleValue val);
|
||||
void SetSerializablePrototypes(std::map<JSObject*, std::wstring>& prototypes);
|
||||
private:
|
||||
ScriptInterface& m_ScriptInterface;
|
||||
@ -185,7 +185,7 @@ protected:
|
||||
m_Impl.Put(name, (u8*)value.data(), value.length());
|
||||
}
|
||||
|
||||
virtual void PutScriptVal(const char* UNUSED(name), jsval value)
|
||||
virtual void PutScriptVal(const char* UNUSED(name), JS::HandleValue value)
|
||||
{
|
||||
m_ScriptImpl->HandleScriptVal(value);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ void CDebugSerializer::PutString(const char* name, const std::string& value)
|
||||
m_Stream << INDENT << name << ": " << "\"" << escaped << "\"\n";
|
||||
}
|
||||
|
||||
void CDebugSerializer::PutScriptVal(const char* name, jsval value)
|
||||
void CDebugSerializer::PutScriptVal(const char* name, JS::HandleValue value)
|
||||
{
|
||||
std::wstring source = m_ScriptInterface.ToString(value, true);
|
||||
|
||||
|
@ -54,7 +54,7 @@ protected:
|
||||
virtual void PutNumber(const char* name, fixed value);
|
||||
virtual void PutBool(const char* name, bool value);
|
||||
virtual void PutString(const char* name, const std::string& value);
|
||||
virtual void PutScriptVal(const char* name, jsval value);
|
||||
virtual void PutScriptVal(const char* name, JS::HandleValue value);
|
||||
virtual void PutRaw(const char* name, const u8* data, size_t len);
|
||||
|
||||
private:
|
||||
|
@ -56,12 +56,10 @@ public:
|
||||
virtual void String(const char* name, std::wstring& out, uint32_t minlength, uint32_t maxlength);
|
||||
|
||||
/// Deserialize a jsval, replacing 'out'
|
||||
virtual void ScriptVal(const char* name, jsval& out) = 0;
|
||||
virtual void ScriptVal(const char* name, CScriptVal& out) = 0;
|
||||
virtual void ScriptVal(const char* name, CScriptValRooted& out) = 0;
|
||||
virtual void ScriptVal(const char* name, JS::MutableHandleValue out) = 0;
|
||||
|
||||
/// Deserialize an object jsval, appending properties to object 'obj'
|
||||
virtual void ScriptObjectAppend(const char* name, jsval& obj) = 0;
|
||||
/// Deserialize an object value, appending properties to object 'objVal'
|
||||
virtual void ScriptObjectAppend(const char* name, JS::HandleValue objVal) = 0;
|
||||
|
||||
/// Deserialize a JSString
|
||||
virtual void ScriptString(const char* name, JSString*& out) = 0;
|
||||
|
@ -92,21 +92,11 @@ void ISerializer::String(const char* name, const std::wstring& value, uint32_t m
|
||||
PutString(name, str);
|
||||
}
|
||||
|
||||
void ISerializer::ScriptVal(const char* name, jsval value)
|
||||
void ISerializer::ScriptVal(const char* name, JS::HandleValue value)
|
||||
{
|
||||
PutScriptVal(name, value);
|
||||
}
|
||||
|
||||
void ISerializer::ScriptVal(const char* name, CScriptVal value)
|
||||
{
|
||||
PutScriptVal(name, value.get());
|
||||
}
|
||||
|
||||
void ISerializer::ScriptVal(const char* name, CScriptValRooted value)
|
||||
{
|
||||
PutScriptVal(name, value.get());
|
||||
}
|
||||
|
||||
void ISerializer::RawBytes(const char* name, const u8* data, size_t len)
|
||||
{
|
||||
PutRaw(name, data, len);
|
||||
|
@ -218,22 +218,8 @@ public:
|
||||
/**
|
||||
* Serialize a jsval.
|
||||
* The value must not contain any unserializable values (like functions).
|
||||
* Likely to trigger GC, so value must be rooted.
|
||||
*/
|
||||
void ScriptVal(const char* name, jsval value);
|
||||
|
||||
/**
|
||||
* Serialize a CScriptVal.
|
||||
* The value must not contain any unserializable values (like functions).
|
||||
* Likely to trigger GC, so value must be rooted.
|
||||
*/
|
||||
void ScriptVal(const char* name, CScriptVal value);
|
||||
|
||||
/**
|
||||
* Serialize a CScriptValRooted.
|
||||
* The value must not contain any unserializable values (like functions).
|
||||
*/
|
||||
void ScriptVal(const char* name, CScriptValRooted value);
|
||||
void ScriptVal(const char* name, JS::HandleValue value);
|
||||
|
||||
/**
|
||||
* Serialize a stream of bytes.
|
||||
@ -269,7 +255,7 @@ protected:
|
||||
virtual void PutNumber(const char* name, fixed value) = 0;
|
||||
virtual void PutBool(const char* name, bool value) = 0;
|
||||
virtual void PutString(const char* name, const std::string& value) = 0;
|
||||
virtual void PutScriptVal(const char* name, jsval value) = 0;
|
||||
virtual void PutScriptVal(const char* name, JS::HandleValue value) = 0;
|
||||
virtual void PutRaw(const char* name, const u8* data, size_t len) = 0;
|
||||
};
|
||||
|
||||
|
@ -190,19 +190,6 @@ struct SerializeBool
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeScriptVal
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, CScriptValRooted value)
|
||||
{
|
||||
serialize.ScriptVal(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, CScriptValRooted& value)
|
||||
{
|
||||
deserialize.ScriptVal(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeWaypoint
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), const ICmpPathfinder::Waypoint& value)
|
||||
|
@ -122,10 +122,9 @@ void CStdDeserializer::FreeScriptBackrefs()
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* appendParent)
|
||||
jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleObject appendParent)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
uint8_t type;
|
||||
@ -142,20 +141,20 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* append
|
||||
case SCRIPT_TYPE_OBJECT:
|
||||
case SCRIPT_TYPE_OBJECT_PROTOTYPE:
|
||||
{
|
||||
JSObject* obj;
|
||||
JS::RootedObject obj(cx);
|
||||
if (appendParent)
|
||||
{
|
||||
obj = appendParent;
|
||||
obj.set(appendParent);
|
||||
}
|
||||
else if (type == SCRIPT_TYPE_ARRAY)
|
||||
{
|
||||
u32 length;
|
||||
NumberU32_Unbounded("array length", length);
|
||||
obj = JS_NewArrayObject(cx, length, NULL);
|
||||
obj.set(JS_NewArrayObject(cx, length, NULL));
|
||||
}
|
||||
else if (type == SCRIPT_TYPE_OBJECT)
|
||||
{
|
||||
obj = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
obj.set(JS_NewObject(cx, NULL, NULL, NULL));
|
||||
}
|
||||
else // SCRIPT_TYPE_OBJECT_PROTOTYPE
|
||||
{
|
||||
@ -163,18 +162,17 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* append
|
||||
String("proto name", prototypeName, 0, 256);
|
||||
|
||||
// Get constructor object
|
||||
JSObject* proto = GetSerializablePrototype(prototypeName);
|
||||
JS::RootedObject proto(cx, GetSerializablePrototype(prototypeName));
|
||||
if (!proto)
|
||||
throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object");
|
||||
|
||||
JSObject* parent = JS_GetParent(proto);
|
||||
JS::RootedObject parent(cx, JS_GetParent(proto));
|
||||
if (!proto || !parent)
|
||||
throw PSERROR_Deserialize_ScriptError();
|
||||
|
||||
obj = JS_NewObject(cx, NULL, proto, parent);
|
||||
obj.set(JS_NewObject(cx, NULL, proto, parent));
|
||||
if (!obj)
|
||||
throw PSERROR_Deserialize_ScriptError("JS_NewObject failed");
|
||||
CScriptValRooted objRoot(cx, JS::ObjectValue(*obj));
|
||||
|
||||
// Does it have custom Deserialize function?
|
||||
// if so, we let it handle the deserialized data, rather than adding properties directly
|
||||
@ -190,11 +188,12 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* append
|
||||
bool hasNullSerialize = hasCustomSerialize && JSVAL_IS_NULL(serialize);
|
||||
|
||||
// If Serialize is null, we'll still call Deserialize but with undefined argument
|
||||
CScriptValRooted data;
|
||||
JS::RootedValue data(cx);
|
||||
if (!hasNullSerialize)
|
||||
ScriptVal("data", data);
|
||||
ScriptVal("data", &data);
|
||||
|
||||
m_ScriptInterface.CallFunctionVoid(JS::ObjectValue(*obj), "Deserialize", data);
|
||||
JS::RootedValue objVal(cx, JS::ObjectValue(*obj));
|
||||
m_ScriptInterface.CallFunctionVoid(objVal, "Deserialize", data);
|
||||
|
||||
AddScriptBackref(obj);
|
||||
|
||||
@ -215,9 +214,7 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* append
|
||||
{
|
||||
utf16string propname;
|
||||
ReadStringUTF16("prop name", propname);
|
||||
|
||||
JS::RootedValue propval(cx, ReadScriptVal("prop value", NULL));
|
||||
CScriptValRooted propvalRoot(cx, propval);
|
||||
JS::RootedValue propval(cx, ReadScriptVal("prop value", JS::NullPtr()));
|
||||
|
||||
if (!JS_SetUCProperty(cx, obj, (const jschar*)propname.data(), propname.length(), propval.address()))
|
||||
throw PSERROR_Deserialize_ScriptError();
|
||||
@ -325,7 +322,7 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* append
|
||||
u32 arrayTag = ReserveScriptBackref();
|
||||
|
||||
// Get buffer object
|
||||
jsval bufferVal = ReadScriptVal("buffer", NULL);
|
||||
jsval bufferVal = ReadScriptVal("buffer", JS::NullPtr());
|
||||
|
||||
if (!bufferVal.isObject())
|
||||
throw PSERROR_Deserialize_ScriptError();
|
||||
@ -420,27 +417,21 @@ void CStdDeserializer::ScriptString(const char* name, JSString*& out)
|
||||
throw PSERROR_Deserialize_ScriptError("JS_NewUCStringCopyN failed");
|
||||
}
|
||||
|
||||
void CStdDeserializer::ScriptVal(const char* name, jsval& out)
|
||||
void CStdDeserializer::ScriptVal(const char* name, JS::MutableHandleValue out)
|
||||
{
|
||||
out = ReadScriptVal(name, NULL);
|
||||
out.set(ReadScriptVal(name, JS::NullPtr()));
|
||||
}
|
||||
|
||||
void CStdDeserializer::ScriptVal(const char* name, CScriptVal& out)
|
||||
void CStdDeserializer::ScriptObjectAppend(const char* name, JS::HandleValue objVal)
|
||||
{
|
||||
out = ReadScriptVal(name, NULL);
|
||||
}
|
||||
|
||||
void CStdDeserializer::ScriptVal(const char* name, CScriptValRooted& out)
|
||||
{
|
||||
out = CScriptValRooted(m_ScriptInterface.GetContext(), ReadScriptVal(name, NULL));
|
||||
}
|
||||
|
||||
void CStdDeserializer::ScriptObjectAppend(const char* name, jsval& obj)
|
||||
{
|
||||
if (!obj.isObject())
|
||||
JSContext* cx = m_ScriptInterface.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
if (!objVal.isObject())
|
||||
throw PSERROR_Deserialize_ScriptError();
|
||||
|
||||
ReadScriptVal(name, JSVAL_TO_OBJECT(obj));
|
||||
JS::RootedObject obj(cx, &objVal.toObject());
|
||||
ReadScriptVal(name, obj);
|
||||
}
|
||||
|
||||
void CStdDeserializer::SetSerializablePrototypes(std::map<std::wstring, JSObject*>& prototypes)
|
||||
|
@ -31,10 +31,8 @@ public:
|
||||
CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream);
|
||||
virtual ~CStdDeserializer();
|
||||
|
||||
virtual void ScriptVal(const char* name, jsval& out);
|
||||
virtual void ScriptVal(const char* name, CScriptVal& out);
|
||||
virtual void ScriptVal(const char* name, CScriptValRooted& out);
|
||||
virtual void ScriptObjectAppend(const char* name, jsval& obj);
|
||||
virtual void ScriptVal(const char* name, JS::MutableHandleValue out);
|
||||
virtual void ScriptObjectAppend(const char* name, JS::HandleValue objVal);
|
||||
virtual void ScriptString(const char* name, JSString*& out);
|
||||
|
||||
virtual std::istream& GetStream();
|
||||
@ -46,7 +44,7 @@ protected:
|
||||
virtual void Get(const char* name, u8* data, size_t len);
|
||||
|
||||
private:
|
||||
jsval ReadScriptVal(const char* name, JSObject* appendParent);
|
||||
jsval ReadScriptVal(const char* name, JS::HandleObject appendParent);
|
||||
void ReadStringUTF16(const char* name, utf16string& str);
|
||||
|
||||
virtual void AddScriptBackref(JSObject* obj);
|
||||
|
@ -267,8 +267,11 @@ public:
|
||||
void test_script_basic()
|
||||
{
|
||||
ScriptInterface script("Test", "Test", g_ScriptRuntime);
|
||||
CScriptVal obj;
|
||||
TS_ASSERT(script.Eval("({'x': 123, 'y': [1, 1.5, '2', 'test', undefined, null, true, false]})", obj));
|
||||
JSContext* cx = script.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue obj(cx);
|
||||
TS_ASSERT(script.Eval("({'x': 123, 'y': [1, 1.5, '2', 'test', undefined, null, true, false]})", &obj));
|
||||
|
||||
{
|
||||
std::stringstream stream;
|
||||
@ -326,8 +329,8 @@ public:
|
||||
|
||||
CStdDeserializer deserialize(script, stream);
|
||||
|
||||
jsval newobj;
|
||||
deserialize.ScriptVal("script", newobj);
|
||||
JS::RootedValue newobj(cx);
|
||||
deserialize.ScriptVal("script", &newobj);
|
||||
TS_ASSERT(stream.good());
|
||||
TS_ASSERT_EQUALS(stream.peek(), EOF);
|
||||
|
||||
@ -340,8 +343,11 @@ public:
|
||||
void helper_script_roundtrip(const char* msg, const char* input, const char* expected, size_t expstreamlen = 0, const char* expstream = NULL)
|
||||
{
|
||||
ScriptInterface script("Test", "Test", g_ScriptRuntime);
|
||||
CScriptVal obj;
|
||||
TSM_ASSERT(msg, script.Eval(input, obj));
|
||||
JSContext* cx = script.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue obj(cx);
|
||||
TSM_ASSERT(msg, script.Eval(input, &obj));
|
||||
|
||||
std::stringstream stream;
|
||||
CStdSerializer serialize(script, stream);
|
||||
@ -355,8 +361,8 @@ public:
|
||||
|
||||
CStdDeserializer deserialize(script, stream);
|
||||
|
||||
jsval newobj;
|
||||
deserialize.ScriptVal("script", newobj);
|
||||
JS::RootedValue newobj(cx);
|
||||
deserialize.ScriptVal("script", &newobj);
|
||||
TSM_ASSERT(msg, stream.good());
|
||||
TSM_ASSERT_EQUALS(msg, stream.peek(), EOF);
|
||||
|
||||
@ -567,14 +573,17 @@ public:
|
||||
void test_script_exceptions()
|
||||
{
|
||||
ScriptInterface script("Test", "Test", g_ScriptRuntime);
|
||||
CScriptVal obj;
|
||||
JSContext* cx = script.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue obj(cx);
|
||||
|
||||
std::stringstream stream;
|
||||
CStdSerializer serialize(script, stream);
|
||||
|
||||
TestLogger logger;
|
||||
|
||||
TS_ASSERT(script.Eval("([1, 2, function () { }])", obj));
|
||||
TS_ASSERT(script.Eval("([1, 2, function () { }])", &obj));
|
||||
TS_ASSERT_THROWS(serialize.ScriptVal("script", obj), PSERROR_Serialize_InvalidScriptValue);
|
||||
}
|
||||
|
||||
@ -599,8 +608,11 @@ public:
|
||||
const char* input = "var x = {}; for (var i=0;i<256;++i) x[i]=Math.pow(i, 2); x";
|
||||
|
||||
ScriptInterface script("Test", "Test", g_ScriptRuntime);
|
||||
CScriptVal obj;
|
||||
TS_ASSERT(script.Eval(input, obj));
|
||||
JSContext* cx = script.GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue obj(cx);
|
||||
TS_ASSERT(script.Eval(input, &obj));
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
@ -611,8 +623,8 @@ public:
|
||||
|
||||
CStdDeserializer deserialize(script, stream);
|
||||
|
||||
jsval newobj;
|
||||
deserialize.ScriptVal("script", newobj);
|
||||
JS::RootedValue newobj(cx);
|
||||
deserialize.ScriptVal("script", &newobj);
|
||||
TS_ASSERT(stream.good());
|
||||
TS_ASSERT_EQUALS(stream.peek(), EOF);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user