From 2a40a71ffaa9dae15b7f007e52b527efdedfc666 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 12 Aug 2016 13:13:01 +0200 Subject: [PATCH] Change scoping mechanism for the __using keyword refs #12408 --- lib/base/scriptframe.cpp | 25 +++++++++++++++++++------ lib/base/scriptframe.hpp | 5 ++++- lib/config/expression.cpp | 11 +++-------- lib/config/vmops.hpp | 7 +++---- lib/remote/consolehandler.cpp | 33 ++++++++++++++++++--------------- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/lib/base/scriptframe.cpp b/lib/base/scriptframe.cpp index 6ea697c77..cd2ec8e23 100644 --- a/lib/base/scriptframe.cpp +++ b/lib/base/scriptframe.cpp @@ -24,6 +24,7 @@ using namespace icinga; boost::thread_specific_ptr > ScriptFrame::m_ScriptFrames; +Array::Ptr ScriptFrame::m_Imports; ScriptFrame::ScriptFrame(void) : Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0) @@ -45,12 +46,6 @@ void ScriptFrame::InitializeFrame(void) ScriptFrame *frame = frames->top(); Sandboxed = frame->Sandboxed; - Imports = frame->Imports; - } - - if (!Imports) { - Imports = new Array(); - Imports->Add(ScriptGlobal::Get("System")); } PushFrame(this); @@ -111,3 +106,21 @@ void ScriptFrame::PushFrame(ScriptFrame *frame) frames->push(frame); } + +Array::Ptr ScriptFrame::GetImports(void) +{ + if (!m_Imports) { + m_Imports = new Array(); + m_Imports->Add(ScriptGlobal::Get("System")); + } + + return m_Imports; +} + +void ScriptFrame::AddImport(const Object::Ptr& import) +{ + Array::Ptr imports = m_Imports->ShallowClone(); + imports->Add(import); + m_Imports = imports; +} + diff --git a/lib/base/scriptframe.hpp b/lib/base/scriptframe.hpp index 9827011a8..e60b40022 100644 --- a/lib/base/scriptframe.hpp +++ b/lib/base/scriptframe.hpp @@ -32,7 +32,6 @@ namespace icinga struct I2_BASE_API ScriptFrame { Dictionary::Ptr Locals; - Array::Ptr Imports; Value Self; bool Sandboxed; int Depth; @@ -46,8 +45,12 @@ struct I2_BASE_API ScriptFrame static ScriptFrame *GetCurrentFrame(void); + static Array::Ptr GetImports(void); + static void AddImport(const Object::Ptr& import); + private: static boost::thread_specific_ptr > m_ScriptFrames; + static Array::Ptr m_Imports; inline static void PushFrame(ScriptFrame *frame); inline static ScriptFrame *PopFrame(void); diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index bd24225a1..7c1807164 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -904,15 +904,10 @@ ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin CHECK_RESULT(importres); Value import = importres.GetValue(); - if (!import.IsObject()) - BOOST_THROW_EXCEPTION(ScriptError("The parameter does not resolve to an object", m_DebugInfo)); + if (!import.IsObjectType()) + BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo)); - if (!frame.Imports) - frame.Imports = new Array(); - else - frame.Imports = static_pointer_cast(frame.Imports->ShallowClone()); - - frame.Imports->Add(import); + ScriptFrame::AddImport(import); return Empty; } diff --git a/lib/config/vmops.hpp b/lib/config/vmops.hpp index 40d56170d..8a11b5259 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -46,11 +46,10 @@ class VMOps public: static inline bool FindVarImportRef(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo()) { - if (!frame.Imports) - return false; + Array::Ptr imports = ScriptFrame::GetImports(); - ObjectLock olock(frame.Imports); - BOOST_FOREACH(const Value& import, frame.Imports) { + ObjectLock olock(imports); + BOOST_FOREACH(const Value& import, imports) { Object::Ptr obj = import; if (obj->HasOwnField(name)) { *result = import; diff --git a/lib/remote/consolehandler.cpp b/lib/remote/consolehandler.cpp index 3fb41edfc..ac99b038d 100644 --- a/lib/remote/consolehandler.cpp +++ b/lib/remote/consolehandler.cpp @@ -215,7 +215,7 @@ static void AddSuggestion(std::vector& matches, const String& word, cons matches.push_back(suggestion); } -static void AddSuggestions(std::vector& matches, const String& word, const String& pword, const Value& value) +static void AddSuggestions(std::vector& matches, const String& word, const String& pword, bool withPrototype, const Value& value) { String prefix; @@ -239,18 +239,20 @@ static void AddSuggestions(std::vector& matches, const String& word, con AddSuggestion(matches, word, prefix + field.Name); } - while (type) { - Object::Ptr prototype = type->GetPrototype(); - Dictionary::Ptr dict = dynamic_pointer_cast(prototype); + if (withPrototype) { + while (type) { + Object::Ptr prototype = type->GetPrototype(); + Dictionary::Ptr dict = dynamic_pointer_cast(prototype); - if (dict) { - ObjectLock olock(dict); - BOOST_FOREACH(const Dictionary::Pair& kv, dict) { - AddSuggestion(matches, word, prefix + kv.first); + if (dict) { + ObjectLock olock(dict); + BOOST_FOREACH(const Dictionary::Pair& kv, dict) { + AddSuggestion(matches, word, prefix + kv.first); + } } - } - type = type->GetBaseType(); + type = type->GetBaseType(); + } } } @@ -276,10 +278,11 @@ std::vector ConsoleHandler::GetAutocompletionSuggestions(const String& w } } - if (frame.Imports) { - ObjectLock olock(frame.Imports); - BOOST_FOREACH(const Value& import, frame.Imports) { - AddSuggestions(matches, word, "", import); + { + Array::Ptr imports = ScriptFrame::GetImports(); + ObjectLock olock(imports); + BOOST_FOREACH(const Value& import, imports) { + AddSuggestions(matches, word, "", false, import); } } @@ -296,7 +299,7 @@ std::vector ConsoleHandler::GetAutocompletionSuggestions(const String& w if (expr) value = expr->Evaluate(frame); - AddSuggestions(matches, word, pword, value); + AddSuggestions(matches, word, pword, true, value); } catch (...) { /* Ignore the exception */ } } -- 2.40.0