forked from 0ad/0ad
Exact stack rooting for CParamNode
Refs #2415 Refs #2462 This was SVN commit r15944.
This commit is contained in:
parent
9040f8a3d3
commit
8e2d514228
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
{
|
||||
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()
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user