From 0683fca535b885b7999bfb246bfed2898f7007ed Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 2 Apr 2014 09:04:17 +0200 Subject: [PATCH] Allow anonymous functions to be garbage-collected. Fixes #5921 --- lib/base/dynamicobject.cpp | 14 ++++++++++---- lib/base/scriptfunction.cpp | 22 +++++++++------------- lib/base/scriptfunction.h | 13 +------------ lib/config/aexpression.cpp | 24 +++++++++++++++--------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/lib/base/dynamicobject.cpp b/lib/base/dynamicobject.cpp index 11be09821..929870b3c 100644 --- a/lib/base/dynamicobject.cpp +++ b/lib/base/dynamicobject.cpp @@ -233,15 +233,21 @@ Value DynamicObject::InvokeMethod(const String& method, if (!methods) BOOST_THROW_EXCEPTION(std::invalid_argument("Method '" + method + "' does not exist.")); - String funcName = methods->Get(method); + Value funcName = methods->Get(method); if (funcName.IsEmpty()) BOOST_THROW_EXCEPTION(std::invalid_argument("Method '" + method + "' does not exist.")); - ScriptFunction::Ptr func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName); + ScriptFunction::Ptr func; - if (!func) - BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + funcName + "' does not exist.")); + if (funcName.IsObjectType()) { + func = funcName; + } else { + func = ScriptFunction::GetByName(funcName); + + if (!func) + BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + String(funcName) + "' does not exist.")); + } return func->Invoke(arguments); } diff --git a/lib/base/scriptfunction.cpp b/lib/base/scriptfunction.cpp index 8b047cc2a..8f392a1f4 100644 --- a/lib/base/scriptfunction.cpp +++ b/lib/base/scriptfunction.cpp @@ -35,31 +35,27 @@ Value ScriptFunction::Invoke(const std::vector& arguments) ScriptFunction::Ptr ScriptFunction::GetByName(const String& name) { - return ScriptFunctionRegistry::GetInstance()->GetItem(name); + ScriptVariable::Ptr sv = ScriptVariable::GetByName(name); + + if (!sv) + return ScriptFunction::Ptr(); + + return sv->GetData(); } -void ScriptFunction::Register(const String& name, const ScriptFunction::Callback& function) +void ScriptFunction::Register(const String& name, const ScriptFunction::Ptr& function) { - ScriptVariable::Ptr sv = ScriptVariable::Set(name, name); + ScriptVariable::Ptr sv = ScriptVariable::Set(name, function); sv->SetConstant(true); - - ScriptFunction::Ptr func = make_shared(function); - ScriptFunctionRegistry::GetInstance()->Register(name, func); } void ScriptFunction::Unregister(const String& name) { ScriptVariable::Unregister(name); - ScriptFunctionRegistry::GetInstance()->Unregister(name); } RegisterFunctionHelper::RegisterFunctionHelper(const String& name, const ScriptFunction::Callback& function) { - ScriptFunction::Register(name, function); -} - -ScriptFunctionRegistry *ScriptFunctionRegistry::GetInstance(void) -{ - return Singleton::GetInstance(); + ScriptFunction::Register(name, make_shared(function)); } diff --git a/lib/base/scriptfunction.h b/lib/base/scriptfunction.h index a5bd6a561..a9188c559 100644 --- a/lib/base/scriptfunction.h +++ b/lib/base/scriptfunction.h @@ -48,24 +48,13 @@ public: Value Invoke(const std::vector& arguments); static ScriptFunction::Ptr GetByName(const String& name); - static void Register(const String& name, const ScriptFunction::Callback& function); + static void Register(const String& name, const ScriptFunction::Ptr& function); static void Unregister(const String& name); private: Callback m_Callback; }; -/** - * A registry for script functions. - * - * @ingroup base - */ -class I2_BASE_API ScriptFunctionRegistry : public Registry -{ -public: - static ScriptFunctionRegistry *GetInstance(void); -}; - /** * Helper class for registering ScriptFunction implementation classes. * diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp index e666027ee..7f1f51b19 100644 --- a/lib/config/aexpression.cpp +++ b/lib/config/aexpression.cpp @@ -248,8 +248,14 @@ Value AExpression::OpLogicalOr(const AExpression *expr, const Dictionary::Ptr& l Value AExpression::OpFunctionCall(const AExpression *expr, const Dictionary::Ptr& locals) { - String funcName = expr->EvaluateOperand1(locals); - ScriptFunction::Ptr func = ScriptFunction::GetByName(funcName); + Value funcName = expr->EvaluateOperand1(locals); + + ScriptFunction::Ptr func; + + if (funcName.IsObjectType()) + func = funcName; + else + func = ScriptFunction::GetByName(funcName); if (!func) BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist.")); @@ -478,13 +484,13 @@ Value AExpression::OpFunction(const AExpression* expr, const Dictionary::Ptr& lo AExpression::Ptr aexpr = left->Get(1); String name = left->Get(0); - if (name.IsEmpty()) - name = "__lambda" + Utility::NewUniqueID(); - Array::Ptr funcargs = expr->m_Operand2; - ScriptFunction::Callback callback = boost::bind(&AExpression::FunctionWrapper, _1, funcargs, aexpr, locals); - ScriptFunction::Register(name, callback); - return name; + ScriptFunction::Ptr func = make_shared(boost::bind(&AExpression::FunctionWrapper, _1, funcargs, aexpr, locals)); + + if (!name.IsEmpty()) + ScriptFunction::Register(name, func); + + return func; } Value AExpression::OpApply(const AExpression* expr, const Dictionary::Ptr& locals) @@ -538,4 +544,4 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca item->Compile()->Register(); return Empty; -} \ No newline at end of file +}