aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-07 16:03:03 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-12 14:12:39 +0100
commit1390891709236a2889d8afaeb00e1571767f480b (patch)
tree24b310fd9d4b3dd747f751f8ea2d340392e33645 /src/qml/jsapi
parent4c67ae2dd9a49348ed5b2d733a60ed0b06c5d203 (diff)
QJSManagedValue: Allow retrieving and instantiating JS metatypes
... a.k.a InternalClass. This is a faster way of creating multiple similar objects, compared to a sequence of setProperty() calls. Change-Id: Iecc8c581e50b9062895dae9500ffe2482d88028e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r--src/qml/jsapi/qjsmanagedvalue.cpp104
-rw-r--r--src/qml/jsapi/qjsmanagedvalue.h6
2 files changed, 109 insertions, 1 deletions
diff --git a/src/qml/jsapi/qjsmanagedvalue.cpp b/src/qml/jsapi/qjsmanagedvalue.cpp
index cd93366524..c5651f5dbd 100644
--- a/src/qml/jsapi/qjsmanagedvalue.cpp
+++ b/src/qml/jsapi/qjsmanagedvalue.cpp
@@ -533,6 +533,17 @@ bool QJSManagedValue::isError() const
}
/*!
+ * \internal
+ *
+ * Returns \c true if this value represents a JavaScript meta type, or \c false
+ * otherwise.
+ */
+bool QJSManagedValue::isJsMetaType() const
+{
+ return d && d->as<QV4::InternalClass>();
+}
+
+/*!
* Converts the manged value to a string. If the managed value holds a string,
* that one is returned. Otherwise a string coercion by JavaScript rules is
* performed.
@@ -798,7 +809,8 @@ void QJSManagedValue::setProperty(const QString &name, const QJSValue &value)
}
QV4::Scope scope(obj->engine());
QV4::ScopedString str(scope, obj->engine()->newString(name));
- obj->put(str->toPropertyKey(), QJSValuePrivate::convertToReturnedValue(v4, value));
+ obj->put(str->toPropertyKey(),
+ QJSValuePrivate::convertToReturnedValue(scope.engine, value));
}
}
@@ -1054,6 +1066,96 @@ QJSValue QJSManagedValue::callAsConstructor(const QJSValueList &arguments) const
return QJSValuePrivate::fromReturnedValue(f->callAsConstructor(jsCallData));
}
+/*!
+ * \internal
+ *
+ * Retrieves the JavaScript meta type of this value. The JavaScript meta type
+ * represents the layout of members in an object. Instantiating a meta type is
+ * faster than re-constructing the same object using a sequence of setProperty()
+ * calls on a new object.
+ *
+ * \sa members(), instantiate()
+ */
+QJSManagedValue QJSManagedValue::jsMetaType() const
+{
+ if (!d)
+ return QJSManagedValue();
+
+ QJSManagedValue result(v4Engine(d));
+ if (QV4::Managed *m = d->as<QV4::Managed>())
+ *result.d = m->internalClass();
+
+ return result;
+}
+
+/*!
+ * \internal
+ *
+ * If this value is a JavaScript meta type, retrieves the names of its members
+ * The ordering of the names corresponds to the ordering of the values to be
+ * passed to instantiate().
+ *
+ * If the value is not a meta type, an empty list is returned.
+ *
+ * \sa isMetaType(), metaType(), instantiate()
+ */
+QStringList QJSManagedValue::jsMetaMembers() const
+{
+ if (!d)
+ return {};
+
+ if (QV4::InternalClass *c = d->as<QV4::InternalClass>()) {
+ const auto heapClass = c->d();
+ const int size = heapClass->size;
+ QStringList result;
+ result.reserve(size);
+ for (int i = 0; i < size; ++i)
+ result.append(heapClass->keyAt(i));
+ return result;
+ }
+
+ return {};
+}
+
+/*!
+ * \internal
+ *
+ * If this value is a JavaScript meta type, instantiates it using the
+ * \a values, and returns the result. Otherwise returns undefined.
+ *
+ * The values are expected in the same order as the keys in the return value of
+ * members(), and that is the order in which properties were added to the object
+ * this meta type originally belongs to.
+ *
+ * \sa members(), metaType(), isMetaType().
+ */
+QJSManagedValue QJSManagedValue::jsMetaInstantiate(const QJSValueList &values) const
+{
+ if (!d)
+ return {};
+
+ if (QV4::InternalClass *c = d->as<QV4::InternalClass>()) {
+ QV4::ExecutionEngine *engine = c->engine();
+ QJSManagedValue result(engine);
+ *result.d = c->engine()->newObject(c->d());
+ QV4::Object *o = result.d->as<QV4::Object>();
+
+ for (uint i = 0, end = qMin(qsizetype(c->d()->size), values.size()); i < end; ++i) {
+ const QJSValue &arg = values[i];
+ if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
+ qWarning("QJSManagedValue::instantiate() failed: "
+ "Argument was created in different engine.");
+ return QJSManagedValue();
+ }
+ o->setProperty(i, QJSValuePrivate::convertToReturnedValue(engine, arg));
+ }
+
+ return result;
+ }
+
+ return {};
+}
+
QJSManagedValue::QJSManagedValue(QV4::ExecutionEngine *engine) :
d(engine->memoryManager->m_persistentValues->allocate())
{
diff --git a/src/qml/jsapi/qjsmanagedvalue.h b/src/qml/jsapi/qjsmanagedvalue.h
index 702f2507f0..7a63e5ffb3 100644
--- a/src/qml/jsapi/qjsmanagedvalue.h
+++ b/src/qml/jsapi/qjsmanagedvalue.h
@@ -108,6 +108,7 @@ public:
bool isQMetaObject() const;
bool isDate() const;
bool isError() const;
+ bool isJsMetaType() const;
// Native type transformations
QString toString() const;
@@ -146,6 +147,11 @@ public:
QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &arguments = {}) const;
QJSValue callAsConstructor(const QJSValueList &arguments = {}) const;
+ // JavaScript metatypes
+ QJSManagedValue jsMetaType() const;
+ QStringList jsMetaMembers() const;
+ QJSManagedValue jsMetaInstantiate(const QJSValueList &values = {}) const;
+
private:
friend class QJSValue;
friend class QJSEngine;