Change scoping mechanism for the __using keyword

refs #12408
This commit is contained in:
Gunnar Beutner 2016-08-12 13:13:01 +02:00
parent 3980cf04a0
commit 2a40a71ffa
5 changed files with 47 additions and 34 deletions

View File

@ -24,6 +24,7 @@
using namespace icinga;
boost::thread_specific_ptr<std::stack<ScriptFrame *> > 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;
}

View File

@ -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<std::stack<ScriptFrame *> > m_ScriptFrames;
static Array::Ptr m_Imports;
inline static void PushFrame(ScriptFrame *frame);
inline static ScriptFrame *PopFrame(void);

View File

@ -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<Dictionary>())
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<Array>(frame.Imports->ShallowClone());
frame.Imports->Add(import);
ScriptFrame::AddImport(import);
return Empty;
}

View File

@ -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;

View File

@ -215,7 +215,7 @@ static void AddSuggestion(std::vector<String>& matches, const String& word, cons
matches.push_back(suggestion);
}
static void AddSuggestions(std::vector<String>& matches, const String& word, const String& pword, const Value& value)
static void AddSuggestions(std::vector<String>& matches, const String& word, const String& pword, bool withPrototype, const Value& value)
{
String prefix;
@ -239,6 +239,7 @@ static void AddSuggestions(std::vector<String>& matches, const String& word, con
AddSuggestion(matches, word, prefix + field.Name);
}
if (withPrototype) {
while (type) {
Object::Ptr prototype = type->GetPrototype();
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(prototype);
@ -253,6 +254,7 @@ static void AddSuggestions(std::vector<String>& matches, const String& word, con
type = type->GetBaseType();
}
}
}
std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& word, ScriptFrame& frame)
{
@ -276,10 +278,11 @@ std::vector<String> 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<String> 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 */ }
}