Implement support for frozen arrays and dictionaries

This commit is contained in:
Gunnar Beutner 2018-01-30 12:19:34 +01:00
parent b88149c455
commit e361b3c427
7 changed files with 98 additions and 2 deletions

View File

@ -1260,6 +1260,14 @@ Signature:
Returns true if the array contains the specified value, false otherwise.
### Array#freeze <a id="array-freeze"></a>
Signature:
function freeze()
Disallows further modifications to this array. Trying to modify the array will result in an exception.
### Array#len <a id="array-len"></a>
Signature:
@ -1395,6 +1403,14 @@ Signature:
Returns true if a dictionary item with the specified `key` exists, false otherwise.
### Dictionary#freeze <a id="dictionary-freeze"></a>
Signature:
function freeze()
Disallows further modifications to this dictionary. Trying to modify the dictionary will result in an exception.
### Dictionary#len <a id="dictionary-len"></a>
Signature:

View File

@ -245,6 +245,13 @@ static Array::Ptr ArrayUnique()
return Array::FromSet(result);
}
static void ArrayFreeze()
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->Freeze();
}
Object::Ptr Array::GetPrototype()
{
static Dictionary::Ptr prototype = new Dictionary({
@ -264,7 +271,8 @@ Object::Ptr Array::GetPrototype()
{ "filter", new Function("Array#filter", ArrayFilter, { "func" }, true) },
{ "any", new Function("Array#any", ArrayAny, { "func" }, true) },
{ "all", new Function("Array#all", ArrayAll, { "func" }, true) },
{ "unique", new Function("Array#unique", ArrayUnique, {}, true) }
{ "unique", new Function("Array#unique", ArrayUnique, {}, true) },
{ "freeze", new Function("Array#freeze", ArrayFreeze, {}) }
});
return prototype;

View File

@ -67,6 +67,9 @@ void Array::Set(SizeType index, const Value& value)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.at(index) = value;
}
@ -80,6 +83,9 @@ void Array::Set(SizeType index, Value&& value)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.at(index).Swap(value);
}
@ -92,6 +98,9 @@ void Array::Add(Value value)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.push_back(std::move(value));
}
@ -160,6 +169,9 @@ void Array::Insert(SizeType index, Value value)
ASSERT(index <= m_Data.size());
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.insert(m_Data.begin() + index, std::move(value));
}
@ -172,6 +184,9 @@ void Array::Remove(SizeType index)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.erase(m_Data.begin() + index);
}
@ -184,6 +199,9 @@ void Array::Remove(Array::Iterator it)
{
ASSERT(OwnsLock());
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.erase(it);
}
@ -191,6 +209,9 @@ void Array::Resize(SizeType newSize)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.resize(newSize);
}
@ -198,6 +219,9 @@ void Array::Clear()
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.clear();
}
@ -205,6 +229,9 @@ void Array::Reserve(SizeType newSize)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.reserve(newSize);
}
@ -213,6 +240,9 @@ void Array::CopyTo(const Array::Ptr& dest) const
ObjectLock olock(this);
ObjectLock xlock(dest);
if (dest->m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
std::copy(m_Data.begin(), m_Data.end(), std::back_inserter(dest->m_Data));
}
@ -261,6 +291,10 @@ Array::Ptr Array::Reverse() const
void Array::Sort()
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
std::sort(m_Data.begin(), m_Data.end());
}
@ -271,6 +305,12 @@ String Array::ToString() const
return msgbuf.str();
}
void Array::Freeze()
{
ObjectLock olock(this);
m_Frozen = true;
}
Value Array::GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const
{
int index;

View File

@ -112,11 +112,14 @@ public:
String ToString() const override;
void Freeze();
Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override;
void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo) override;
private:
std::vector<Value> m_Data; /**< The data for the array. */
bool m_Frozen{false};
};
Array::Iterator begin(const Array::Ptr& x);

View File

@ -91,6 +91,13 @@ static Array::Ptr DictionaryValues()
return new Array(std::move(values));
}
static void DictionaryFreeze()
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
self->Freeze();
}
Object::Ptr Dictionary::GetPrototype()
{
static Dictionary::Ptr prototype = new Dictionary({
@ -101,7 +108,8 @@ Object::Ptr Dictionary::GetPrototype()
{ "contains", new Function("Dictionary#contains", DictionaryContains, { "key" }, true) },
{ "shallow_clone", new Function("Dictionary#shallow_clone", DictionaryShallowClone, {}, true) },
{ "keys", new Function("Dictionary#keys", DictionaryKeys, {}, true) },
{ "values", new Function("Dictionary#values", DictionaryValues, {}, true) }
{ "values", new Function("Dictionary#values", DictionaryValues, {}, true) },
{ "freeze", new Function("Dictionary#freeze", DictionaryFreeze, {}) }
});
return prototype;

View File

@ -94,6 +94,9 @@ void Dictionary::Set(const String& key, Value value)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
m_Data[key] = std::move(value);
}
@ -159,6 +162,9 @@ void Dictionary::Remove(Dictionary::Iterator it)
{
ASSERT(OwnsLock());
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
m_Data.erase(it);
}
@ -171,6 +177,9 @@ void Dictionary::Remove(const String& key)
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
Dictionary::Iterator it;
it = m_Data.find(key);
@ -187,6 +196,9 @@ void Dictionary::Clear()
{
ObjectLock olock(this);
if (m_Frozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
m_Data.clear();
}
@ -260,6 +272,12 @@ String Dictionary::ToString() const
return msgbuf.str();
}
void Dictionary::Freeze()
{
ObjectLock olock(this);
m_Frozen = true;
}
Value Dictionary::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
{
Value value;

View File

@ -83,6 +83,8 @@ public:
String ToString() const override;
void Freeze();
Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override;
void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo) override;
bool HasOwnField(const String& field) const override;
@ -90,6 +92,7 @@ public:
private:
std::map<String, Value> m_Data; /**< The data for the dictionary. */
bool m_Frozen{false};
};
Dictionary::Iterator begin(const Dictionary::Ptr& x);