aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/language
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/corelib/language')
-rw-r--r--src/lib/corelib/language/evaluator.cpp2
-rw-r--r--src/lib/corelib/language/language.cpp7
-rw-r--r--src/lib/corelib/language/language.h14
-rw-r--r--src/lib/corelib/language/scriptengine.cpp66
-rw-r--r--src/lib/corelib/language/scriptengine.h8
-rw-r--r--src/lib/corelib/language/value.cpp25
-rw-r--r--src/lib/corelib/language/value.h2
7 files changed, 109 insertions, 15 deletions
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp
index 473e01e5c..824dc8d10 100644
--- a/src/lib/corelib/language/evaluator.cpp
+++ b/src/lib/corelib/language/evaluator.cpp
@@ -782,7 +782,7 @@ private:
void handle(VariantValue *variantValue) override
{
- *result = engine->toScriptValue(variantValue->value());
+ *result = engine->toScriptValue(variantValue->value(), variantValue->id());
engine->takeOwnership(*result);
}
};
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp
index 4701c8585..5ffe87439 100644
--- a/src/lib/corelib/language/language.cpp
+++ b/src/lib/corelib/language/language.cpp
@@ -51,6 +51,7 @@
#include <buildgraph/rulegraph.h> // TODO: Move to language?
#include <buildgraph/transformer.h>
#include <jsextensions/jsextensions.h>
+#include <language/value.h>
#include <loader/loaderutils.h>
#include <logging/categories.h>
#include <logging/translator.h>
@@ -117,6 +118,12 @@ bool Probe::needsReconfigure(const FileTime &referenceTime) const
return Internal::any_of(m_importedFilesUsed, criterion);
}
+void Probe::restoreValues()
+{
+ for (auto it = m_properties.begin(), end = m_properties.end(); it != end; ++it) {
+ m_values[it.key()] = VariantValue::createStored(it.value());
+ }
+}
/*!
* \class SourceArtifact
diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h
index daf88d4fb..86f0f86fe 100644
--- a/src/lib/corelib/language/language.h
+++ b/src/lib/corelib/language/language.h
@@ -116,10 +116,11 @@ public:
const QString &configureScript,
const QVariantMap &properties,
const QVariantMap &initialProperties,
+ const QMap<QString, VariantValuePtr> &values,
const std::vector<QString> &importedFilesUsed)
{
return ProbeConstPtr(new Probe(globalId, location, condition, configureScript, properties,
- initialProperties, importedFilesUsed));
+ initialProperties, values, importedFilesUsed));
}
const QString &globalId() const { return m_globalId; }
@@ -128,6 +129,7 @@ public:
const QString &configureScript() const { return m_configureScript; }
const QVariantMap &properties() const { return m_properties; }
const QVariantMap &initialProperties() const { return m_initialProperties; }
+ const QMap<QString, VariantValuePtr> &values() const { return m_values; }
const std::vector<QString> &importedFilesUsed() const { return m_importedFilesUsed; }
bool needsReconfigure(const FileTime &referenceTime) const;
@@ -135,6 +137,8 @@ public:
{
pool.serializationOp<opType>(m_globalId, m_location, m_condition, m_configureScript,
m_properties, m_initialProperties, m_importedFilesUsed);
+ if constexpr (opType == PersistentPool::OpType::Load)
+ restoreValues();
}
private:
@@ -145,21 +149,27 @@ private:
QString configureScript,
QVariantMap properties,
QVariantMap initialProperties,
+ QMap<QString, VariantValuePtr> values,
std::vector<QString> importedFilesUsed)
: m_globalId(std::move(globalId))
, m_location(location)
, m_configureScript(std::move(configureScript))
, m_properties(std::move(properties))
, m_initialProperties(std::move(initialProperties))
+ , m_values(std::move(values))
, m_importedFilesUsed(std::move(importedFilesUsed))
, m_condition(condition)
- {}
+ {
+ }
+
+ void restoreValues();
QString m_globalId;
CodeLocation m_location;
QString m_configureScript;
QVariantMap m_properties;
QVariantMap m_initialProperties;
+ QMap<QString, VariantValuePtr> m_values;
std::vector<QString> m_importedFilesUsed;
bool m_condition = false;
};
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index 11d41b5c2..a89949bf4 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -58,6 +58,7 @@
#include <tools/stlutils.h>
#include <tools/stringconstants.h>
+#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdiriterator.h>
#include <QtCore/qfile.h>
@@ -196,6 +197,10 @@ void ScriptEngine::reset()
JS_FreeValue(m_context, e.second);
m_jsFileCache.clear();
+ for (const JSValue &s : std::as_const(m_jsValueCache))
+ JS_FreeValue(m_context, s);
+ m_jsValueCache.clear();
+
for (auto it = m_evalResults.cbegin(); it != m_evalResults.cend(); ++it) {
for (int i = 0; i < it.value(); ++i)
JS_FreeValue(m_context, it.key());
@@ -481,6 +486,37 @@ void ScriptEngine::addInternalExtension(const char *name, JSValue ext)
m_internalExtensions.insert(QLatin1String(name), JS_DupValue(m_context, ext));
}
+JSValue ScriptEngine::asJsValue(const QVariant &v, quintptr id, bool frozen)
+{
+ switch (static_cast<QMetaType::Type>(v.userType())) {
+ case QMetaType::QByteArray:
+ return asJsValue(v.toByteArray());
+ case QMetaType::QString:
+ return asJsValue(v.toString());
+ case QMetaType::QStringList:
+ return asJsValue(v.toStringList());
+ case QMetaType::QVariantList:
+ return asJsValue(v.toList(), id, frozen);
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ return JS_NewInt32(m_context, v.toInt());
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ return JS_NewInt64(m_context, v.toInt());
+ case QMetaType::Bool:
+ return JS_NewBool(m_context, v.toBool());
+ case QMetaType::QDateTime:
+ return JS_NewDate(
+ m_context, v.toDateTime().toString(Qt::ISODateWithMs).toUtf8().constData());
+ case QMetaType::QVariantMap:
+ return asJsValue(v.toMap(), id, frozen);
+ default:
+ return JS_UNDEFINED;
+ }
+}
+
JSValue ScriptEngine::asJsValue(const QByteArray &s)
{
return JS_NewArrayBufferCopy(
@@ -506,12 +542,21 @@ JSValue ScriptEngine::asJsValue(const QStringList &l)
return array;
}
-JSValue ScriptEngine::asJsValue(const QVariantMap &m)
+JSValue ScriptEngine::asJsValue(const QVariantMap &m, quintptr id, bool frozen)
{
+ const auto it = id ? m_jsValueCache.constFind(id) : m_jsValueCache.constEnd();
+ if (it != m_jsValueCache.constEnd())
+ return JS_DupValue(m_context, it.value());
+ frozen = id || frozen;
JSValue obj = JS_NewObject(m_context);
for (auto it = m.begin(); it != m.end(); ++it)
- setJsProperty(m_context, obj, it.key(), makeJsVariant(m_context, it.value()));
- return obj;
+ setJsProperty(m_context, obj, it.key(), asJsValue(it.value(), 0, frozen));
+ if (frozen)
+ JS_ObjectSeal(m_context, obj, true);
+ if (!id)
+ return obj;
+ m_jsValueCache[id] = obj;
+ return JS_DupValue(m_context, obj);
}
void ScriptEngine::setPropertyOnGlobalObject(const QString &property, JSValue value)
@@ -520,13 +565,22 @@ void ScriptEngine::setPropertyOnGlobalObject(const QString &property, JSValue va
setJsProperty(m_context, globalObject, property, value);
}
-JSValue ScriptEngine::asJsValue(const QVariantList &l)
+JSValue ScriptEngine::asJsValue(const QVariantList &l, quintptr id, bool frozen)
{
+ const auto it = id ? m_jsValueCache.constFind(id) : m_jsValueCache.constEnd();
+ if (it != m_jsValueCache.constEnd())
+ return JS_DupValue(m_context, it.value());
+ frozen = id || frozen;
JSValue array = JS_NewArray(m_context);
setJsProperty(m_context, array, QLatin1String("length"), JS_NewInt32(m_context, l.size()));
for (int i = 0; i < l.size(); ++i)
- JS_SetPropertyUint32(m_context, array, i, makeJsVariant(m_context, l.at(i)));
- return array;
+ JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i), 0, frozen));
+ if (frozen)
+ JS_ObjectSeal(m_context, array, true);
+ if (!id)
+ return array;
+ m_jsValueCache[id] = array;
+ return JS_DupValue(m_context, array);
}
JSValue ScriptEngine::loadInternalExtension(const QString &uri)
diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h
index 4d797dd43..942b7519c 100644
--- a/src/lib/corelib/language/scriptengine.h
+++ b/src/lib/corelib/language/scriptengine.h
@@ -204,7 +204,7 @@ public:
JSValue newArray(int length, JsValueOwner owner);
void takeOwnership(JSValue v);
JSValue undefinedValue() const { return JS_UNDEFINED; }
- JSValue toScriptValue(const QVariant &v) const { return makeJsVariant(m_context, v); }
+ JSValue toScriptValue(const QVariant &v, quintptr id = 0) { return asJsValue(v, id); }
JSValue evaluate(JsValueOwner resultOwner, const QString &code,
const QString &filePath = QString(), int line = 1,
const JSValueList &scopeChain = {});
@@ -283,11 +283,12 @@ public:
JSValue getInternalExtension(const char *name) const;
void addInternalExtension(const char *name, JSValue ext);
+ JSValue asJsValue(const QVariant &v, quintptr id = 0, bool frozen = false);
JSValue asJsValue(const QByteArray &s);
JSValue asJsValue(const QString &s);
JSValue asJsValue(const QStringList &l);
- JSValue asJsValue(const QVariantList &l);
- JSValue asJsValue(const QVariantMap &m);
+ JSValue asJsValue(const QVariantList &l, quintptr id = 0, bool frozen = false);
+ JSValue asJsValue(const QVariantMap &m, quintptr id = 0, bool frozen = false);
QVariant property(const char *name) const { return m_properties.value(QLatin1String(name)); }
void setProperty(const char *k, const QVariant &v) { m_properties.insert(QLatin1String(k), v); }
@@ -396,6 +397,7 @@ private:
QHash<QString, JSClassID> m_classes;
QHash<QString, JSValue> m_internalExtensions;
QHash<QString, JSValue> m_stringCache;
+ QHash<quintptr, JSValue> m_jsValueCache;
QHash<JSValue, int> m_evalResults;
std::vector<JSValue *> m_externallyCachedValues;
QHash<QPair<Artifact *, QString>, JSValue> m_artifactsScriptValues;
diff --git a/src/lib/corelib/language/value.cpp b/src/lib/corelib/language/value.cpp
index 65e227228..634f54faf 100644
--- a/src/lib/corelib/language/value.cpp
+++ b/src/lib/corelib/language/value.cpp
@@ -240,6 +240,14 @@ ValuePtr ItemValue::clone(ItemPool &pool) const
return create(m_item->clone(pool), createdByPropertiesBlock());
}
+class StoredVariantValue : public VariantValue
+{
+public:
+ explicit StoredVariantValue(QVariant v) : VariantValue(std::move(v)) {}
+
+ quintptr id() const override { return quintptr(this); }
+};
+
VariantValue::VariantValue(QVariant v)
: Value(VariantValueType, false)
, m_value(std::move(v))
@@ -249,13 +257,24 @@ VariantValue::VariantValue(QVariant v)
VariantValue::VariantValue(const VariantValue &other, ItemPool &pool)
: Value(other, pool), m_value(other.m_value) {}
-VariantValuePtr VariantValue::create(const QVariant &v)
+template<typename T>
+VariantValuePtr createImpl(const QVariant &v)
{
if (!v.isValid())
- return invalidValue();
+ return VariantValue::invalidValue();
if (static_cast<QMetaType::Type>(v.userType()) == QMetaType::Bool)
return v.toBool() ? VariantValue::trueValue() : VariantValue::falseValue();
- return std::make_shared<VariantValue>(v);
+ return std::make_shared<T>(v);
+}
+
+VariantValuePtr VariantValue::create(const QVariant &v)
+{
+ return createImpl<VariantValue>(v);
+}
+
+VariantValuePtr VariantValue::createStored(const QVariant &v)
+{
+ return createImpl<StoredVariantValue>(v);
}
ValuePtr VariantValue::clone(ItemPool &pool) const
diff --git a/src/lib/corelib/language/value.h b/src/lib/corelib/language/value.h
index d01ddf8ee..1a6746e24 100644
--- a/src/lib/corelib/language/value.h
+++ b/src/lib/corelib/language/value.h
@@ -236,11 +236,13 @@ public:
explicit VariantValue(QVariant v);
VariantValue(const VariantValue &v, ItemPool &pool);
static VariantValuePtr create(const QVariant &v = QVariant());
+ static VariantValuePtr createStored(const QVariant &v = QVariant());
void apply(ValueHandler *handler) override { handler->handle(this); }
ValuePtr clone(ItemPool &pool) const override;
const QVariant &value() const { return m_value; }
+ virtual quintptr id() const { return 0; }
static const VariantValuePtr &falseValue();
static const VariantValuePtr &trueValue();