diff options
Diffstat (limited to 'src/lib/corelib/language')
-rw-r--r-- | src/lib/corelib/language/evaluator.cpp | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/language.cpp | 7 | ||||
-rw-r--r-- | src/lib/corelib/language/language.h | 14 | ||||
-rw-r--r-- | src/lib/corelib/language/scriptengine.cpp | 66 | ||||
-rw-r--r-- | src/lib/corelib/language/scriptengine.h | 8 | ||||
-rw-r--r-- | src/lib/corelib/language/value.cpp | 25 | ||||
-rw-r--r-- | src/lib/corelib/language/value.h | 2 |
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(); |