diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index 2e52a4b791..369f7d6280 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -563,9 +563,10 @@ public: JS::RootedValue tmpEntityTemplates(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade m_ScriptInterface->Eval("({})", &tmpEntityTemplates); + JS::RootedValue val(cx); for (size_t i = 0; i < templates.size(); ++i) { - JS::RootedValue val(cx, templates[i].second->ToJSVal(cx, false)); + templates[i].second->ToJSVal(cx, false, &val); m_ScriptInterface->SetProperty(tmpEntityTemplates, templates[i].first.c_str(), val, true); } diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index d107977ead..2f907a3e54 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -67,7 +67,7 @@ template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::Mutable template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::MutableHandleValue ret, CParamNode const& val) { JSAutoRequest rq(cx); - ret.set(val.ToJSVal(cx, true)); + val.ToJSVal(cx, true, ret); // Prevent modifications to the object, so that it's safe to share between // components and to reconstruct on deserialization diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp index fcd0c82775..f966004b10 100644 --- a/source/simulation2/system/ParamNode.cpp +++ b/source/simulation2/system/ParamNode.cpp @@ -308,63 +308,85 @@ void CParamNode::ToXML(std::wostream& strm) const } } -jsval CParamNode::ToJSVal(JSContext* cx, bool cacheValue) const +void CParamNode::ToJSVal(JSContext* cx, bool cacheValue, JS::MutableHandleValue ret) const { if (cacheValue && !m_ScriptVal.uninitialised()) - return m_ScriptVal.get(); + { + ret.set(m_ScriptVal.get()); + return; + } - jsval val = ConstructJSVal(cx); + ConstructJSVal(cx, ret); if (cacheValue) - m_ScriptVal = CScriptValRooted(cx, val); - - return val; + m_ScriptVal = CScriptValRooted(cx, ret); } -jsval CParamNode::ConstructJSVal(JSContext* cx) const +void CParamNode::ConstructJSVal(JSContext* cx, JS::MutableHandleValue ret) const { JSAutoRequest rq(cx); if (m_Childs.empty()) { // Empty node - map to undefined if (m_Value.empty()) - return JSVAL_VOID; + { + ret.setUndefined(); + return; + } // Just a string utf16string text(m_Value.begin(), m_Value.end()); - JSString* str = JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length()); + JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length())); if (str) - return STRING_TO_JSVAL(str); + { + ret.setString(str); + return; + } // TODO: report error - return JSVAL_VOID; + ret.setUndefined(); + return; } // Got child nodes - convert this node into a hash-table-style object: - JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); + JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL)); if (!obj) - return JSVAL_VOID; // TODO: report error + { + ret.setUndefined(); + return; // TODO: report error + } + JS::RootedValue childVal(cx); for (std::map::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it) { - JS::RootedValue childVal(cx, it->second.ConstructJSVal(cx)); + it->second.ConstructJSVal(cx, &childVal); if (!JS_SetProperty(cx, obj, it->first.c_str(), childVal.address())) - return JSVAL_VOID; // TODO: report error + { + ret.setUndefined(); + return; // TODO: report error + } } // If the node has a string too, add that as an extra property if (!m_Value.empty()) { utf16string text(m_Value.begin(), m_Value.end()); - JSString* str = JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length()); + JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length())); if (!str) - return JSVAL_VOID; // TODO: report error - JS::RootedValue childVal(cx, STRING_TO_JSVAL(str)); + { + ret.setUndefined(); + return; // TODO: report error + } + + JS::RootedValue childVal(cx, JS::StringValue(str)); if (!JS_SetProperty(cx, obj, "_string", childVal.address())) - return JSVAL_VOID; // TODO: report error + { + ret.setUndefined(); + return; // TODO: report error + } } - return OBJECT_TO_JSVAL(obj); + ret.setObject(*obj); } void CParamNode::ResetScriptVal() diff --git a/source/simulation2/system/ParamNode.h b/source/simulation2/system/ParamNode.h index 8f0d7d56bc..fda6a5ed71 100644 --- a/source/simulation2/system/ParamNode.h +++ b/source/simulation2/system/ParamNode.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2014 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -220,7 +220,7 @@ public: * The cache will be reset if *this* node is modified (e.g. by LoadXML), * but *not* if any child nodes are modified (so don't do that). */ - jsval ToJSVal(JSContext* cx, bool cacheValue) const; + void ToJSVal(JSContext* cx, bool cacheValue, JS::MutableHandleValue ret) const; /** * Returns the names/nodes of the children of this node, ordered by name @@ -247,7 +247,7 @@ private: void ResetScriptVal(); - jsval ConstructJSVal(JSContext* cx) const; + void ConstructJSVal(JSContext* cx, JS::MutableHandleValue ret) const; std::wstring m_Value; ChildrenMap m_Childs;