diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index 4fe96cd2ef..8b35fbabd9 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -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) diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index ec6edb843c..a587e6b190 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -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 diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index c281b76116..e1cf742738 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -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; diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index cb7ade20b4..7c7f267b4d 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -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::const_iterator it = m_ComponentTypesById.find(cid); if (it == m_ComponentTypesById.end()) { @@ -729,11 +732,14 @@ IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTy std::map& 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;