aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4qobjectwrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4qobjectwrapper.cpp')
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp243
1 files changed, 61 insertions, 182 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 2cbb152dd0..eaee078a5f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -3,61 +3,53 @@
#include "qv4qobjectwrapper_p.h"
-#include <private/qqmlobjectorgadget_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlvmemetaobject_p.h>
-#include <private/qqmlbinding_p.h>
#include <private/qjsvalue_p.h>
-#include <private/qqmlexpression_p.h>
-#include <private/qqmlglobal_p.h>
+
+#include <private/qqmlbinding_p.h>
+#include <private/qqmlbuiltinfunctions_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmlobjectorgadget_p.h>
+#include <private/qqmlpropertybinding_p.h>
+#include <private/qqmlscriptstring_p.h>
+#include <private/qqmlsignalnames_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qqmllistwrapper_p.h>
-#include <private/qqmlbuiltinfunctions_p.h>
-#if QT_CONFIG(qml_locale)
-#include <private/qqmllocale_p.h>
-#endif
+#include <private/qqmlvmemetaobject_p.h>
#include <private/qv4arraybuffer_p.h>
+#include <private/qv4compileddata_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4functionobject_p.h>
-#include <private/qv4runtime_p.h>
-#include <private/qv4variantobject_p.h>
#include <private/qv4identifiertable_p.h>
-#include <private/qv4lookup_p.h>
-#include <private/qv4qmlcontext_p.h>
-#include <private/qv4sequenceobject_p.h>
-#include <private/qv4objectproto_p.h>
+#include <private/qv4jscall_p.h>
#include <private/qv4jsonobject_p.h>
+#include <private/qv4lookup_p.h>
+#include <private/qv4mm_p.h>
#include <private/qv4regexpobject_p.h>
-#include <private/qv4dateobject_p.h>
+#include <private/qv4runtime_p.h>
#include <private/qv4scopedvalue_p.h>
-#include <private/qv4jscall_p.h>
-#include <private/qv4mm_p.h>
-#include <private/qqmlscriptstring_p.h>
-#include <private/qv4compileddata_p.h>
-#include <private/qqmlpropertybinding_p.h>
-#include <private/qqmlpropertycachemethodarguments_p.h>
-#include <private/qqmlsignalnames_p.h>
+#include <private/qv4sequenceobject_p.h>
+#include <private/qv4variantobject_p.h>
-#include <QtQml/qjsvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qatomic.h>
-#include <QtCore/qmetaobject.h>
-#if QT_CONFIG(qml_itemmodel)
-#include <QtCore/qabstractitemmodel.h>
-#endif
#include <QtCore/qloggingcategory.h>
+#include <QtCore/qmetaobject.h>
#include <QtCore/qqueue.h>
+#include <QtCore/qtimer.h>
#include <QtCore/qtypes.h>
+#include <QtCore/qvarlengtharray.h>
#include <vector>
+
+#if QT_CONFIG(qml_itemmodel)
+#include <QtCore/qabstractitemmodel.h>
+#endif
+
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcBindingRemoval, "qt.qml.binding.removal", QtWarningMsg)
+Q_LOGGING_CATEGORY(lcBuiltinsBindingRemoval, "qt.qml.binding.removal", QtWarningMsg)
Q_LOGGING_CATEGORY(lcObjectConnect, "qt.qml.object.connect", QtWarningMsg)
Q_LOGGING_CATEGORY(lcOverloadResolution, "qt.qml.overloadresolution", QtWarningMsg)
Q_LOGGING_CATEGORY(lcMethodBehavior, "qt.qml.method.behavior")
@@ -246,11 +238,8 @@ static ReturnedValue loadProperty(
property.readProperty(object, &v);
return QV4::JsonObject::fromJsonObject(v4, v);
}
- case QMetaType::QJsonArray: {
- QJsonArray v;
- property.readProperty(object, &v);
- return QV4::JsonObject::fromJsonArray(v4, v);
- }
+ case QMetaType::QJsonArray:
+ return encodeSequence(QMetaSequence::fromContainer<QJsonArray>());
case QMetaType::QStringList:
return encodeSequence(QMetaSequence::fromContainer<QStringList>());
case QMetaType::QVariantList:
@@ -360,20 +349,15 @@ ReturnedValue QObjectWrapper::getProperty(
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex());
} else if (property->isV4Function()) {
- Scope scope(engine);
- ScopedContext global(scope, engine->qmlContext());
- if (!global)
- global = engine->rootContext();
return QObjectMethod::create(
- global, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex());
+ engine, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex());
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
return engine->memoryManager->allocate<QmlSignalHandler>(
object, property->coreIndex())->asReturnedValue();
} else {
- ExecutionContext *global = engine->rootContext();
return QObjectMethod::create(
- global, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex());
+ engine, (flags & AttachMethods) ? wrapper : nullptr, property->coreIndex());
}
}
@@ -405,8 +389,7 @@ static OptionalReturnedValue getDestroyOrToStringMethod(
if (hasProperty)
*hasProperty = true;
- ExecutionContext *global = v4->rootContext();
- return OptionalReturnedValue(QObjectMethod::create(global, qobj, index));
+ return OptionalReturnedValue(QObjectMethod::create(v4, qobj, index));
}
static OptionalReturnedValue getPropertyFromImports(
@@ -608,7 +591,9 @@ void QObjectWrapper::setProperty(
Scope scope(engine);
if (ScopedFunctionObject f(scope, value); f) {
- if (!f->isBinding()) {
+ if (f->as<QQmlTypeWrapper>()) {
+ // Ignore. It's probably a singleton or an attached type.
+ } else if (!f->isBinding()) {
const bool isAliasToAllowed = [&]() {
if (property->isAlias()) {
const QQmlPropertyIndex originalIndex(property->coreIndex(), -1);
@@ -641,7 +626,7 @@ void QObjectWrapper::setProperty(
QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
- ScopedFunctionObject f(scope, bindingFunction->bindingFunction());
+ Scoped<JavaScriptFunctionObject> f(scope, bindingFunction->bindingFunction());
ScopedContext ctx(scope, f->scope());
// binding assignment.
@@ -679,13 +664,13 @@ void QObjectWrapper::setProperty(
}
}
- if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) {
+ if (Q_UNLIKELY(lcBuiltinsBindingRemoval().isInfoEnabled())) {
if (auto binding = QQmlPropertyPrivate::binding(object, QQmlPropertyIndex(property->coreIndex()))) {
const auto stackFrame = engine->currentStackFrame;
switch (binding->kind()) {
case QQmlAbstractBinding::QmlBinding: {
const auto qmlBinding = static_cast<const QQmlBinding*>(binding);
- qCInfo(lcBindingRemoval,
+ qCInfo(lcBuiltinsBindingRemoval,
"Overwriting binding on %s::%s at %s:%d that was initially bound at %s",
object->metaObject()->className(), qPrintable(property->name(object)),
qPrintable(stackFrame->source()), stackFrame->lineNumber(),
@@ -694,7 +679,7 @@ void QObjectWrapper::setProperty(
}
case QQmlAbstractBinding::ValueTypeProxy:
case QQmlAbstractBinding::PropertyToPropertyBinding: {
- qCInfo(lcBindingRemoval,
+ qCInfo(lcBuiltinsBindingRemoval,
"Overwriting binding on %s::%s at %s:%d",
object->metaObject()->className(), qPrintable(property->name(object)),
qPrintable(stackFrame->source()), stackFrame->lineNumber());
@@ -722,7 +707,9 @@ void QObjectWrapper::setProperty(
const QMetaType propType = property->propType();
// functions are already handled, except for the QJSValue case
- Q_ASSERT(!value.as<FunctionObject>() || propType == QMetaType::fromType<QJSValue>());
+ Q_ASSERT(!value.as<FunctionObject>()
+ || value.as<QV4::QQmlTypeWrapper>()
+ || propType == QMetaType::fromType<QJSValue>());
if (value.isNull() && property->isQObject()) {
PROPERTY_STORE(QObject*, nullptr);
@@ -1924,9 +1911,9 @@ static bool requiresStrictArguments(const QQmlObjectOrGadget &object)
&& metaObject->classInfo(indexOfClassInfo).value() == QByteArrayView("true");
}
-static ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQmlPropertyData &data,
- ExecutionEngine *engine, CallData *callArgs,
- QMetaObject::Call callType = QMetaObject::InvokeMetaMethod)
+ReturnedValue QObjectMethod::callPrecise(
+ const QQmlObjectOrGadget &object, const QQmlPropertyData &data, ExecutionEngine *engine,
+ CallData *callArgs, QMetaObject::Call callType)
{
QByteArray unknownTypeError;
@@ -2011,7 +1998,7 @@ Resolve the overloaded method to call. The algorithm works conceptually like th
If two or more overloads have the same match score, return the last one. The match
score is constructed by adding the matchScore() result for each of the parameters.
*/
-static const QQmlPropertyData *ResolveOverloaded(
+const QQmlPropertyData *QObjectMethod::resolveOverloaded(
const QQmlObjectOrGadget &object, const QQmlPropertyData *methods, int methodCount,
ExecutionEngine *engine, CallData *callArgs)
{
@@ -2165,7 +2152,7 @@ static bool ExactMatch(QMetaType passed, QMetaType required, const void *data)
return false;
}
-static const QQmlPropertyData *ResolveOverloaded(
+const QQmlPropertyData *QObjectMethod::resolveOverloaded(
const QQmlPropertyData *methods, int methodCount,
void **argv, int argc, const QMetaType *types)
{
@@ -2559,21 +2546,22 @@ ReturnedValue CallArgument::toValue(ExecutionEngine *engine)
return Encode::undefined();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, Heap::Object *wrapper, int index)
+ReturnedValue QObjectMethod::create(ExecutionEngine *engine, Heap::Object *wrapper, int index)
{
- Scope valueScope(scope);
+ Scope valueScope(engine);
Scoped<QObjectMethod> method(
valueScope,
- valueScope.engine->memoryManager->allocate<QObjectMethod>(scope, wrapper, index));
+ engine->memoryManager->allocate<QObjectMethod>(engine, wrapper, index));
return method.asReturnedValue();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, Heap::QQmlValueTypeWrapper *valueType, int index)
+ReturnedValue QObjectMethod::create(
+ ExecutionEngine *engine, Heap::QQmlValueTypeWrapper *valueType, int index)
{
- Scope valueScope(scope);
+ Scope valueScope(engine);
Scoped<QObjectMethod> method(
valueScope,
- valueScope.engine->memoryManager->allocate<QObjectMethod>(scope, valueType, index));
+ engine->memoryManager->allocate<QObjectMethod>(engine, valueType, index));
return method.asReturnedValue();
}
@@ -2596,11 +2584,10 @@ ReturnedValue QObjectMethod::create(
}
}
- Scoped<ExecutionContext> context(valueScope, cloneFrom->scope.get());
Scoped<QObjectMethod> method(
valueScope,
engine->memoryManager->allocate<QV4::QObjectMethod>(
- context, valueTypeWrapper ? valueTypeWrapper->d() : object, cloneFrom->index));
+ engine, valueTypeWrapper ? valueTypeWrapper->d() : object, cloneFrom->index));
method->d()->methodCount = cloneFrom->methodCount;
@@ -2626,10 +2613,10 @@ ReturnedValue QObjectMethod::create(
return method.asReturnedValue();
}
-void Heap::QObjectMethod::init(QV4::ExecutionContext *scope, Object *object, int methodIndex)
+void Heap::QObjectMethod::init(QV4::ExecutionEngine *engine, Object *object, int methodIndex)
{
- Heap::FunctionObject::init(scope);
- wrapper.set(internalClass->engine, object);
+ Heap::FunctionObject::init(engine);
+ wrapper.set(engine, object);
index = methodIndex;
}
@@ -2944,7 +2931,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
if (d()->methodCount != 1) {
Q_ASSERT(d()->methodCount > 0);
- method = ResolveOverloaded(object, d()->methods, d()->methodCount, v4, callData);
+ method = resolveOverloaded(object, d()->methods, d()->methodCount, v4, callData);
if (method == nullptr)
return Encode::undefined();
}
@@ -2962,7 +2949,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
});
}
- return doCall([&]() { return CallPrecise(object, *method, v4, callData); });
+ return doCall([&]() { return callPrecise(object, *method, v4, callData); });
}
struct ToStringMetaMethod
@@ -3032,7 +3019,7 @@ void QObjectMethod::callInternalWithMetaTypes(
const QQmlPropertyData *method = d()->methods;
if (d()->methodCount != 1) {
Q_ASSERT(d()->methodCount > 0);
- method = ResolveOverloaded(d()->methods, d()->methodCount, argv, argc, types);
+ method = resolveOverloaded(d()->methods, d()->methodCount, argv, argc, types);
}
if (!method || method->isV4Function()) {
@@ -3084,114 +3071,6 @@ void QObjectMethod::callInternalWithMetaTypes(
DEFINE_OBJECT_VTABLE(QObjectMethod);
-
-void Heap::QMetaObjectWrapper::init(const QMetaObject *metaObject)
-{
- FunctionObject::init();
- this->metaObject = metaObject;
- constructors = nullptr;
- constructorCount = 0;
-}
-
-void Heap::QMetaObjectWrapper::destroy()
-{
- delete[] constructors;
-}
-
-void Heap::QMetaObjectWrapper::ensureConstructorsCache() {
-
- const int count = metaObject->constructorCount();
- if (constructorCount != count) {
- delete[] constructors;
- constructorCount = count;
- if (count == 0) {
- constructors = nullptr;
- return;
- }
- constructors = new QQmlPropertyData[count];
-
- for (int i = 0; i < count; ++i) {
- QMetaMethod method = metaObject->constructor(i);
- QQmlPropertyData &d = constructors[i];
- d.load(method);
- d.setCoreIndex(i);
- }
- }
-}
-
-
-ReturnedValue QMetaObjectWrapper::create(ExecutionEngine *engine, const QMetaObject* metaObject) {
-
- Scope scope(engine);
- Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocate<QMetaObjectWrapper>(metaObject)->asReturnedValue());
- mo->init(engine);
- return mo->asReturnedValue();
-}
-
-void QMetaObjectWrapper::init(ExecutionEngine *) {
- const QMetaObject & mo = *d()->metaObject;
-
- for (int i = 0; i < mo.enumeratorCount(); i++) {
- QMetaEnum Enum = mo.enumerator(i);
- for (int k = 0; k < Enum.keyCount(); k++) {
- const char* key = Enum.key(k);
- const int value = Enum.value(k);
- defineReadonlyProperty(QLatin1String(key), Value::fromInt32(value));
- }
- }
-}
-
-ReturnedValue QMetaObjectWrapper::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
-{
- const QMetaObjectWrapper *This = static_cast<const QMetaObjectWrapper*>(f);
- return This->constructInternal(argv, argc);
-}
-
-ReturnedValue QMetaObjectWrapper::constructInternal(const Value *argv, int argc) const
-{
-
- d()->ensureConstructorsCache();
-
- ExecutionEngine *v4 = engine();
- const QMetaObject* mo = d()->metaObject;
- if (d()->constructorCount == 0) {
- return v4->throwTypeError(QLatin1String(mo->className())
- + QLatin1String(" has no invokable constructor"));
- }
-
- Scope scope(v4);
- Scoped<QObjectWrapper> object(scope);
- JSCallData cData(nullptr, argv, argc);
- CallData *callData = cData.callData(scope);
-
- const QQmlObjectOrGadget objectOrGadget(mo);
-
- if (d()->constructorCount == 1) {
- object = CallPrecise(objectOrGadget, d()->constructors[0], v4, callData, QMetaObject::CreateInstance);
- } else if (const QQmlPropertyData *ctor = ResolveOverloaded(
- objectOrGadget, d()->constructors, d()->constructorCount, v4, callData)) {
- object = CallPrecise(objectOrGadget, *ctor, v4, callData, QMetaObject::CreateInstance);
- }
- if (object) {
- Scoped<QMetaObjectWrapper> metaObject(scope, this);
- object->defineDefaultProperty(v4->id_constructor(), metaObject);
- object->setPrototypeOf(const_cast<QMetaObjectWrapper*>(this));
- }
- return object.asReturnedValue();
-
-}
-
-bool QMetaObjectWrapper::virtualIsEqualTo(Managed *a, Managed *b)
-{
- const QMetaObjectWrapper *aMetaObject = a->as<QMetaObjectWrapper>();
- Q_ASSERT(aMetaObject);
- const QMetaObjectWrapper *bMetaObject = b->as<QMetaObjectWrapper>();
- return bMetaObject && aMetaObject->metaObject() == bMetaObject->metaObject();
-}
-
-DEFINE_OBJECT_VTABLE(QMetaObjectWrapper);
-
-
void Heap::QmlSignalHandler::init(QObject *object, int signalIndex)
{
Object::init();
@@ -3214,7 +3093,7 @@ ReturnedValue QmlSignalHandler::call(const Value *thisObject, const Value *argv,
Scope scope(engine());
Scoped<QObjectMethod> method(
scope, QObjectMethod::create(
- scope.engine->rootContext(),
+ scope.engine,
static_cast<Heap::QObjectWrapper *>(nullptr),
signalIndex()));