Exact rooting for CallConstructor.

Refs #2415
Refs #2462

This was SVN commit r15601.
This commit is contained in:
Yves 2014-08-02 16:30:15 +00:00
parent 736d934107
commit c818b8e475
4 changed files with 30 additions and 19 deletions

View File

@ -865,20 +865,21 @@ AutoGCRooter* ScriptInterface::ReplaceAutoGCRooter(AutoGCRooter* rooter)
return ret;
}
jsval ScriptInterface::CallConstructor(jsval ctor, uint argc, jsval argv)
void ScriptInterface::CallConstructor(JS::HandleValue ctor, JS::AutoValueVector& argv, JS::MutableHandleValue out)
{
JSAutoRequest rq(m->m_cx);
if (!ctor.isObject())
{
LOGERROR(L"CallConstructor: ctor is not an object");
return JS::UndefinedValue();
out.setNull();
return;
}
// Passing argc 0 and argv JSVAL_VOID causes a crash in mozjs24
if (argc == 0)
return JS::ObjectValue(*JS_New(m->m_cx, &ctor.toObject(), 0, NULL));
if (argv.length() == 0)
out.setObjectOrNull(JS_New(m->m_cx, &ctor.toObject(), 0, NULL));
else
return JS::ObjectValue(*JS_New(m->m_cx, &ctor.toObject(), argc, &argv));
out.setObjectOrNull(JS_New(m->m_cx, &ctor.toObject(), argv.length(), argv.begin()));
}
void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs)

View File

@ -136,9 +136,11 @@ public:
/**
* Call a constructor function, equivalent to JS "new ctor(arg)".
* @return The new object; or JSVAL_VOID on failure, and logs an error message
* @param ctor An object that can be used as constructor
* @param argv Constructor arguments
* @param out The new object; On error an error message gets logged and out is Null (out.isNull() == true).
*/
jsval CallConstructor(jsval ctor, uint argc, jsval argv);
void CallConstructor(JS::HandleValue ctor, JS::AutoValueVector& argv, JS::MutableHandleValue out);
/**
* Call the named property on the given object, with void return type and 0 arguments

View File

@ -114,7 +114,7 @@ private:
std::string constructor;
JS::RootedValue objectWithConstructor(cx); // object that should contain the constructor function
JS::RootedValue global(cx, m_ScriptInterface->GetGlobalObject());
CScriptVal ctor;
JS::RootedValue ctor(cx);
if (!m_ScriptInterface->HasProperty(metadata, "moduleName"))
{
objectWithConstructor.set(m_ScriptInterface->GetGlobalObject());
@ -135,8 +135,8 @@ private:
}
// Get the constructor function from the loaded scripts
if (!m_ScriptInterface->GetProperty(objectWithConstructor, constructor.c_str(), ctor)
|| ctor.undefined())
if (!m_ScriptInterface->GetProperty(objectWithConstructor, constructor.c_str(), &ctor)
|| ctor.isNull())
{
LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str());
return false;
@ -144,7 +144,7 @@ private:
m_ScriptInterface->GetProperty(metadata, "useShared", m_UseSharedComponent);
CScriptVal obj;
JS::RootedValue obj(cx);
// Set up the data to pass as the constructor argument
JS::RootedValue settings(cx);
@ -156,9 +156,9 @@ private:
JS::AutoValueVector argv(cx);
argv.append(settings.get());
obj = m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0));
m_ScriptInterface->CallConstructor(ctor, argv, &obj);
if (obj.undefined())
if (obj.isNull())
{
LOGERROR(L"Failed to create AI player: %ls: error calling constructor '%hs'", path.string().c_str(), constructor.c_str());
return false;
@ -423,10 +423,12 @@ public:
JS::AutoValueVector argv(cx);
argv.append(settings);
m_SharedAIObj = CScriptValRooted(cx, m_ScriptInterface->CallConstructor(ctor, argv.length(), argv.handleAt(0)));
// TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get());
m_ScriptInterface->CallConstructor(ctor, argv, &tmpSharedAIObj);
m_SharedAIObj = CScriptValRooted(cx, tmpSharedAIObj);
if (m_SharedAIObj.undefined())
if (tmpSharedAIObj.isNull())
{
LOGERROR(L"Failed to create shared AI component: %ls: error calling constructor '%hs'", path.string().c_str(), "SharedScript");
return false;

View File

@ -708,6 +708,9 @@ void CComponentManager::AddSystemComponents(bool skipScriptedComponents, bool sk
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())
{
@ -729,11 +732,14 @@ IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTy
std::map<entity_id_t, IComponent*>& emap2 = m_ComponentsByTypeId[cid];
// If this is a scripted component, construct the appropriate JS object first
jsval obj = JSVAL_NULL;
JS::RootedValue obj(cx);
// TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
JS::RootedValue tmpCtor(cx, ct.ctor.get());
if (ct.type == CT_Script)
{
obj = m_ScriptInterface.CallConstructor(ct.ctor.get(), 0, JSVAL_VOID);
if (JSVAL_IS_VOID(obj))
JS::AutoValueVector argv(cx); // TODO: With SpiderMonkey 31, we can pass JS::HandleValueArray::empty()
m_ScriptInterface.CallConstructor(tmpCtor, argv, &obj);
if (obj.isNull())
{
LOGERROR(L"Script component constructor failed");
return NULL;