Exact stack rooting for CParamNode

Refs #2415
Refs #2462

This was SVN commit r15944.
This commit is contained in:
Yves 2014-11-09 11:08:53 +00:00
parent 9040f8a3d3
commit 8e2d514228
4 changed files with 48 additions and 25 deletions

View File

@ -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);
}

View File

@ -67,7 +67,7 @@ template<> void ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, JS::Mutable
template<> void ScriptInterface::ToJSVal<CParamNode>(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

View File

@ -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<const jschar*>(text.data()), text.length());
JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast<const jschar*>(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<std::string, CParamNode>::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<const jschar*>(text.data()), text.length());
JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast<const jschar*>(text.data()), text.length()));
if (!str)
return JSVAL_VOID; // TODO: report error
JS::RootedValue childVal(cx, STRING_TO_JSVAL(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);
JS::RootedValue childVal(cx, JS::StringValue(str));
if (!JS_SetProperty(cx, obj, "_string", childVal.address()))
{
ret.setUndefined();
return; // TODO: report error
}
}
ret.setObject(*obj);
}
void CParamNode::ResetScriptVal()

View File

@ -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;