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.cpp618
1 files changed, 377 insertions, 241 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 2c9fc8f9dd..d91965a350 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -44,7 +44,6 @@
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qjsvalue_p.h>
-#include <private/qqmlaccessors_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmltypewrapper_p.h>
@@ -54,6 +53,7 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qv8engine_p.h>
+#include <private/qv4arraybuffer_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4variantobject_p.h>
@@ -74,6 +74,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qmetaobject.h>
QT_BEGIN_NAMESPACE
@@ -83,7 +84,7 @@ QT_WARNING_DISABLE_GCC("-Wstrict-aliasing")
using namespace QV4;
-static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
+QPair<QObject *, int> QObjectMethod::extractQtMethod(const QV4::FunctionObject *function)
{
QV4::ExecutionEngine *v4 = function->engine();
if (v4) {
@@ -103,7 +104,7 @@ static QPair<QObject *, int> extractQtSignal(const Value &value)
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
- return extractQtMethod(function);
+ return QObjectMethod::extractQtMethod(function);
QV4::Scoped<QV4::QmlSignalHandler> handler(scope, value);
if (handler)
@@ -113,132 +114,87 @@ static QPair<QObject *, int> extractQtSignal(const Value &value)
return qMakePair((QObject *)0, -1);
}
-
-struct ReadAccessor {
- static inline void Indirect(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(n == 0);
- Q_UNUSED(n);
-
- void *args[] = { output, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
- }
-
- static inline void Direct(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(n == 0);
- Q_UNUSED(n);
-
- void *args[] = { output, 0 };
- object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
- }
-
- static inline void Accessor(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(property.accessors);
-
- property.accessors->read(object, output);
- if (n) property.accessors->notifier(object, n);
- }
-};
-
-// Load value properties
-template<void (*ReadFunction)(QObject *, const QQmlPropertyData &,
- void *, QQmlNotifier **)>
-static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object,
- const QQmlPropertyData &property,
- QQmlNotifier **notifier)
+static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object,
+ const QQmlPropertyData &property)
{
Q_ASSERT(!property.isFunction());
QV4::Scope scope(v4);
if (property.isQObject()) {
QObject *rv = 0;
- ReadFunction(object, property, &rv, notifier);
+ property.readProperty(object, &rv);
return QV4::QObjectWrapper::wrap(v4, rv);
} else if (property.isQList()) {
- return QmlListWrapper::create(v4, object, property.coreIndex, property.propType);
- } else if (property.propType == QMetaType::QReal) {
+ return QmlListWrapper::create(v4, object, property.coreIndex(), property.propType());
+ } else if (property.propType() == QMetaType::QReal) {
qreal v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Int || property.isEnum()) {
+ } else if (property.propType() == QMetaType::Int || property.isEnum()) {
int v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Bool) {
+ } else if (property.propType() == QMetaType::Bool) {
bool v = false;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::QString) {
+ } else if (property.propType() == QMetaType::QString) {
QString v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return v4->newString(v)->asReturnedValue();
- } else if (property.propType == QMetaType::UInt) {
+ } else if (property.propType() == QMetaType::UInt) {
uint v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Float) {
+ } else if (property.propType() == QMetaType::Float) {
float v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Double) {
+ } else if (property.propType() == QMetaType::Double) {
double v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.isV4Handle()) {
QQmlV4Handle handle;
- ReadFunction(object, property, &handle, notifier);
+ property.readProperty(object, &handle);
return handle;
- } else if (property.propType == qMetaTypeId<QJSValue>()) {
+ } else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QJSValuePrivate::convertedToValue(v4, v);
} else if (property.isQVariant()) {
QVariant v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
if (QQmlValueTypeFactory::isValueType(v.userType())) {
if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.userType()))
- return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, v.userType()); // VariantReference value-type.
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, v.userType()); // VariantReference value-type.
}
return scope.engine->fromVariant(v);
- } else if (QQmlValueTypeFactory::isValueType(property.propType)) {
- Q_ASSERT(notifier == 0);
-
- if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType))
- return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, property.propType);
+ } else if (QQmlValueTypeFactory::isValueType(property.propType())) {
+ if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType()))
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, property.propType());
} else {
- Q_ASSERT(notifier == 0);
-
// see if it's a sequence type
bool succeeded = false;
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType, object, property.coreIndex, &succeeded));
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), &succeeded));
if (succeeded)
return retn->asReturnedValue();
}
- if (property.propType == QMetaType::UnknownType) {
- QMetaProperty p = object->metaObject()->property(property.coreIndex);
+ if (property.propType() == QMetaType::UnknownType) {
+ QMetaProperty p = object->metaObject()->property(property.coreIndex());
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
"'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
return QV4::Encode::undefined();
} else {
- QVariant v(property.propType, (void *)0);
- ReadFunction(object, property, v.data(), notifier);
+ QVariant v(property.propType(), (void *)0);
+ property.readProperty(object, v.data());
return scope.engine->fromVariant(v);
}
}
-Heap::QObjectWrapper::QObjectWrapper(QObject *object)
- : object(object)
-{
-}
-
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
@@ -249,21 +205,21 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
{
Q_UNUSED(revisionMode);
- QQmlData *ddata = QQmlData::get(d()->object, false);
+ QQmlData *ddata = QQmlData::get(d()->object(), false);
if (!ddata)
return 0;
QQmlPropertyData *result = 0;
if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name, d()->object, qmlContext);
+ result = ddata->propertyCache->property(name, d()->object(), qmlContext);
else
- result = QQmlPropertyCache::property(engine->jsEngine(), d()->object, name, qmlContext, *local);
+ result = QQmlPropertyCache::property(engine->jsEngine(), d()->object(), name, qmlContext, *local);
return result;
}
ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports) const
{
- if (QQmlData::wasDeleted(d()->object)) {
+ if (QQmlData::wasDeleted(d()->object())) {
if (hasProperty)
*hasProperty = false;
return QV4::Encode::undefined();
@@ -276,7 +232,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
ExecutionContext *global = v4->rootContext();
- return QV4::QObjectMethod::create(global, d()->object, index);
+ return QV4::QObjectMethod::create(global, d()->object(), index);
}
QQmlPropertyData local;
@@ -295,10 +251,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(v4, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object(),
r.type, Heap::QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(v4, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object(),
qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
@@ -308,7 +264,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return QV4::Object::get(this, name, hasProperty);
}
- QQmlData *ddata = QQmlData::get(d()->object, false);
+ QQmlData *ddata = QQmlData::get(d()->object(), false);
if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) {
if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) {
@@ -321,69 +277,44 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- return getProperty(v4, d()->object, result);
+ return getProperty(v4, d()->object(), result);
}
ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QQmlData::flushPendingBinding(object, property->coreIndex);
+ QQmlData::flushPendingBinding(object, QQmlPropertyIndex(property->coreIndex()));
if (property->isFunction() && !property->isVarProperty()) {
if (property->isVMEFunction()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- return vmemo->vmeMethod(property->coreIndex);
+ return vmemo->vmeMethod(property->coreIndex());
} else if (property->isV4Function()) {
Scope scope(engine);
ScopedContext global(scope, engine->qmlContext());
if (!global)
global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex);
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
- return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex)->asReturnedValue();
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
} else {
ExecutionContext *global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex);
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
}
}
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
- if (property->hasAccessors()) {
- QQmlNotifier *n = 0;
- QQmlNotifier **nptr = 0;
-
- if (ep && ep->propertyCapture && property->accessors->notifier)
- nptr = &n;
-
- Scope scope(engine);
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
-
- if (captureRequired) {
- if (property->accessors->notifier) {
- if (n && ep->propertyCapture)
- ep->propertyCapture->captureProperty(n);
- } else {
- if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
- }
- }
-
- return rv->asReturnedValue();
- }
-
if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
- ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
+ ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- return vmemo->vmeProperty(property->coreIndex);
- } else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
+ return vmemo->vmeProperty(property->coreIndex());
} else {
- return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
+ return loadProperty(engine, object, *property);
}
}
@@ -446,13 +377,13 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
- if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
+ if (!property->isVarProperty() && property->propType() != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ");
- if (!QMetaType::typeName(property->propType))
+ if (!QMetaType::typeName(property->propType()))
error += QLatin1String("[unknown property type]");
else
- error += QLatin1String(QMetaType::typeName(property->propType));
+ error += QLatin1String(QMetaType::typeName(property->propType()));
scope.engine->throwError(error);
return;
}
@@ -463,21 +394,21 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, object, callingQmlContext);
- newBinding->setTarget(object, *property);
+ newBinding = QQmlBinding::create(property, value, object, callingQmlContext);
+ newBinding->setTarget(object, *property, nullptr);
}
}
if (newBinding)
QQmlPropertyPrivate::setBinding(newBinding);
else
- QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
+ QQmlPropertyPrivate::removeBinding(object, QQmlPropertyIndex(property->coreIndex()));
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(property->coreIndex, value);
+ vmemo->setVMEProperty(property->coreIndex(), value);
return;
}
@@ -486,44 +417,44 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
int status = -1; \
int flags = 0; \
void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex(), argv);
if (value.isNull() && property->isQObject()) {
PROPERTY_STORE(QObject*, 0);
} else if (value.isUndefined() && property->isResettable()) {
void *a[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
- } else if (value.isUndefined() && property->propType == qMetaTypeId<QVariant>()) {
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex(), a);
+ } else if (value.isUndefined() && property->propType() == qMetaTypeId<QVariant>()) {
PROPERTY_STORE(QVariant, QVariant());
- } else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
+ } else if (value.isUndefined() && property->propType() == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
- } else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
+ } else if (!newBinding && property->propType() == qMetaTypeId<QJSValue>()) {
PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
- } else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
+ } else if (value.isUndefined() && property->propType() != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
- if (!QMetaType::typeName(property->propType))
+ if (!QMetaType::typeName(property->propType()))
error += QLatin1String("[unknown property type]");
else
- error += QLatin1String(QMetaType::typeName(property->propType));
+ error += QLatin1String(QMetaType::typeName(property->propType()));
scope.engine->throwError(error);
return;
} else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
- } else if (property->propType == QMetaType::Int && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
- } else if (property->propType == QMetaType::QReal && value.isNumber()) {
+ } else if (property->propType() == QMetaType::QReal && value.isNumber()) {
PROPERTY_STORE(qreal, qreal(value.asDouble()));
- } else if (property->propType == QMetaType::Float && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Float && value.isNumber()) {
PROPERTY_STORE(float, float(value.asDouble()));
- } else if (property->propType == QMetaType::Double && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Double && value.isNumber()) {
PROPERTY_STORE(double, double(value.asDouble()));
- } else if (property->propType == QMetaType::QString && value.isString()) {
+ } else if (property->propType() == QMetaType::QString && value.isString()) {
PROPERTY_STORE(QString, value.toQStringNoThrow());
} else if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(property->coreIndex, value);
- } else if (property->propType == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
+ vmemo->setVMEProperty(property->coreIndex(), value);
+ } else if (property->propType() == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
QQmlScriptString ss(value.toQStringNoThrow(), 0 /* context */, object);
if (value.isNumber()) {
ss.d->numberValue = value.toNumber();
@@ -538,7 +469,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
if (property->isQList())
v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = scope.engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType());
QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
@@ -546,7 +477,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
if (v.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(v.userType());
- const char *targetTypeName = QMetaType::typeName(property->propType);
+ const char *targetTypeName = QMetaType::typeName(property->propType());
if (!targetTypeName)
targetTypeName = "an unregistered type";
@@ -641,11 +572,14 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
{
- setProperty(engine, d()->object, propertyIndex, value);
+ setProperty(engine, d()->object(), propertyIndex, value);
}
void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
+ Q_ASSERT(propertyIndex < 0xffff);
+ Q_ASSERT(propertyIndex >= 0);
+
if (QQmlData::wasDeleted(object))
return;
QQmlData *ddata = QQmlData::get(object, /*create*/false);
@@ -697,12 +631,12 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = that->engine();
- if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
+ if (v4->hasException || QQmlData::wasDeleted(that->d()->object()))
return;
QQmlContextData *qmlContext = v4->callingQmlContext();
- if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
- QQmlData *ddata = QQmlData::get(that->d()->object);
+ if (!setQmlProperty(v4, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
+ QQmlData *ddata = QQmlData::get(that->d()->object());
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
// as regular JavaScript properties, like on JavaScript objects.
if (ddata && ddata->context) {
@@ -740,8 +674,8 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- if (that->d()->object) {
- const QMetaObject *mo = that->d()->object->metaObject();
+ if (that->d()->object()) {
+ const QMetaObject *mo = that->d()->object()->metaObject();
// These indices don't apply to gadgets, so don't block them.
const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
@@ -801,8 +735,8 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
if (!v4)
break;
- QVarLengthArray<int, 9> dummy;
- int *argsTypes = QQmlMetaObject(r).methodParameterTypes(This->signalIndex, dummy, 0);
+ QQmlMetaObject::ArgTypeStorage storage;
+ int *argsTypes = QQmlMetaObject(r).methodParameterTypes(This->signalIndex, &storage, 0);
int argCount = argsTypes ? argsTypes[0]:0;
@@ -820,7 +754,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
}
}
- f->call(callData);
+ f->call(scope, callData);
if (scope.hasException()) {
QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
@@ -865,7 +799,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
(connection->thisObject.isUndefined() || RuntimeHelpers::strictEqual(*connection->thisObject.valueRef(), thisObject))) {
QV4::ScopedFunctionObject f(scope, connection->function.value());
- QPair<QObject *, int> connectedFunctionData = extractQtMethod(f);
+ QPair<QObject *, int> connectedFunctionData = QObjectMethod::extractQtMethod(f);
if (connectedFunctionData.first == receiverToDisconnect &&
connectedFunctionData.second == slotIndexToDisconnect) {
*ret = true;
@@ -980,7 +914,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
if (!functionThisValue->isUndefined() && !functionThisValue->isObject())
V4THROW_ERROR("Function.prototype.disconnect: target this is not an object");
- QPair<QObject *, int> functionData = extractQtMethod(functionValue);
+ QPair<QObject *, int> functionData = QObjectMethod::extractQtMethod(functionValue);
void *a[] = {
ctx->d()->engine,
@@ -1011,7 +945,7 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
{
QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
- if (QObject *o = This->object.data()) {
+ if (QObject *o = This->object()) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
if (vme)
vme->mark(e);
@@ -1033,18 +967,18 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (!h->internalClass)
return; // destroyObject already got called
- if (h->object) {
- QQmlData *ddata = QQmlData::get(h->object, false);
+ if (h->object()) {
+ QQmlData *ddata = QQmlData::get(h->object(), false);
if (ddata) {
- if (!h->object->parent() && !ddata->indestructible) {
+ if (!h->object()->parent() && !ddata->indestructible) {
if (ddata && ddata->ownContext && ddata->context)
ddata->context->emitDestruction();
// This object is notionally destroyed now
ddata->isQueuedForDeletion = true;
if (lastCall)
- delete h->object;
+ delete h->object();
else
- h->object->deleteLater();
+ h->object()->deleteLater();
} else {
// If the object is C++-owned, we still have to release the weak reference we have
// to it.
@@ -1108,6 +1042,7 @@ private:
// Pointers to allocData
union {
QString *qstringPtr;
+ QByteArray *qbyteArrayPtr;
QVariant *qvariantPtr;
QList<QObject *> *qlistPtr;
QJSValue *qjsValuePtr;
@@ -1122,7 +1057,8 @@ private:
}
static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index, int returnType, int argCount,
- int *argTypes, QV4::ExecutionEngine *engine, QV4::CallData *callArgs)
+ int *argTypes, QV4::ExecutionEngine *engine, QV4::CallData *callArgs,
+ QMetaObject::Call callType = QMetaObject::InvokeMetaMethod)
{
if (argCount > 0) {
// Convert all arguments.
@@ -1134,7 +1070,7 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
for (int ii = 0; ii < args.count(); ++ii)
argData[ii] = args[ii].dataPtr();
- object.metacall(QMetaObject::InvokeMetaMethod, index, argData.data());
+ object.metacall(callType, index, argData.data());
return args[0].toValue(engine);
@@ -1145,14 +1081,14 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
void *args[] = { arg.dataPtr() };
- object.metacall(QMetaObject::InvokeMetaMethod, index, args);
+ object.metacall(callType, index, args);
return arg.toValue(engine);
} else {
void *args[] = { 0 };
- object.metacall(QMetaObject::InvokeMetaMethod, index, args);
+ object.metacall(callType, index, args);
return Encode::undefined();
}
@@ -1229,6 +1165,13 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
+ } else if (actual.as<ArrayBuffer>()) {
+ switch (conversionType) {
+ case QMetaType::QByteArray:
+ return 0;
+ default:
+ return 10;
+ }
} else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
@@ -1246,6 +1189,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
}
} else if (actual.isNull()) {
switch (conversionType) {
+ case QMetaType::Nullptr:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
case QMetaType::QJsonValue:
@@ -1318,34 +1262,34 @@ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
if (!current->isOverload())
return 0;
- Q_ASSERT(!current->overrideIndexIsProperty);
+ Q_ASSERT(!current->overrideIndexIsProperty());
if (propertyCache) {
- return propertyCache->method(current->overrideIndex);
+ return propertyCache->method(current->overrideIndex());
} else {
const QMetaObject *mo = object.metaObject();
int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
- while (methodOffset > current->overrideIndex) {
+ while (methodOffset > current->overrideIndex()) {
mo = mo->superClass();
methodOffset -= QMetaObject_methods(mo);
}
// If we've been called before with the same override index, then
// we can't go any further...
- if (&dummy == current && dummy.coreIndex == current->overrideIndex)
+ if (&dummy == current && dummy.coreIndex() == current->overrideIndex())
return 0;
- QMetaMethod method = mo->method(current->overrideIndex);
+ QMetaMethod method = mo->method(current->overrideIndex());
dummy.load(method);
// Look for overloaded methods
QByteArray methodName = method.name();
- for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
+ for (int ii = current->overrideIndex() - 1; ii >= methodOffset; --ii) {
if (methodName == mo->method(ii).name()) {
- dummy.setFlags(dummy.getFlags() | QQmlPropertyData::IsOverload);
- dummy.overrideIndexIsProperty = 0;
- dummy.overrideIndex = ii;
+ dummy.setOverload(true);
+ dummy.setOverrideIndexIsProperty(0);
+ dummy.setOverrideIndex(ii);
return &dummy;
}
}
@@ -1355,7 +1299,8 @@ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
}
static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQmlPropertyData &data,
- QV4::ExecutionEngine *engine, QV4::CallData *callArgs)
+ QV4::ExecutionEngine *engine, QV4::CallData *callArgs,
+ QMetaObject::Call callType = QMetaObject::InvokeMetaMethod)
{
QByteArray unknownTypeError;
@@ -1370,9 +1315,13 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (data.hasArguments()) {
int *args = 0;
- QVarLengthArray<int, 9> dummy;
+ QQmlMetaObject::ArgTypeStorage storage;
- args = object.methodParameterTypes(data.coreIndex, dummy, &unknownTypeError);
+ if (data.isConstructor())
+ args = static_cast<const QQmlStaticMetaObject&>(object).constructorParameterTypes(
+ data.coreIndex(), &storage, &unknownTypeError);
+ else
+ args = object.methodParameterTypes(data.coreIndex(), &storage, &unknownTypeError);
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
@@ -1385,11 +1334,11 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
return engine->throwError(error);
}
- return CallMethod(object, data.coreIndex, returnType, args[0], args + 1, engine, callArgs);
+ return CallMethod(object, data.coreIndex(), returnType, args[0], args + 1, engine, callArgs, callType);
} else {
- return CallMethod(object, data.coreIndex, returnType, 0, 0, engine, callArgs);
+ return CallMethod(object, data.coreIndex(), returnType, 0, 0, engine, callArgs, callType);
}
}
@@ -1408,7 +1357,8 @@ Resolve the overloaded method to call. The algorithm works conceptually like th
score is constructed by adding the matchScore() result for each of the parameters.
*/
static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const QQmlPropertyData &data,
- QV4::ExecutionEngine *engine, QV4::CallData *callArgs, const QQmlPropertyCache *propertyCache)
+ QV4::ExecutionEngine *engine, QV4::CallData *callArgs, const QQmlPropertyCache *propertyCache,
+ QMetaObject::Call callType = QMetaObject::InvokeMetaMethod)
{
int argumentCount = callArgs->argc;
@@ -1423,11 +1373,11 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
QV4::ScopedValue v(scope);
do {
- QVarLengthArray<int, 9> dummy;
+ QQmlMetaObject::ArgTypeStorage storage;
int methodArgumentCount = 0;
int *methodArgTypes = 0;
if (attempt->hasArguments()) {
- int *args = object.methodParameterTypes(attempt->coreIndex, dummy, 0);
+ int *args = object.methodParameterTypes(attempt->coreIndex(), &storage, 0);
if (!args) // Must be an unknown argument
continue;
@@ -1458,13 +1408,13 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
} while ((attempt = RelatedMethod(object, attempt, dummy, propertyCache)) != 0);
if (best.isValid()) {
- return CallPrecise(object, best, engine, callArgs);
+ return CallPrecise(object, best, engine, callArgs, callType);
} else {
QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
const QQmlPropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
- QString::fromUtf8(object.metaObject()->method(candidate->coreIndex)
+ QString::fromUtf8(object.metaObject()->method(candidate->coreIndex())
.methodSignature());
candidate = RelatedMethod(object, candidate, dummy, propertyCache);
}
@@ -1487,6 +1437,8 @@ void CallArgument::cleanup()
{
if (type == QMetaType::QString) {
qstringPtr->~QString();
+ } else if (type == QMetaType::QByteArray) {
+ qbyteArrayPtr->~QByteArray();
} else if (type == -1 || type == QMetaType::QVariant) {
qvariantPtr->~QVariant();
} else if (type == qMetaTypeId<QJSValue>()) {
@@ -1686,6 +1638,8 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
return QV4::Encode(floatValue);
} else if (type == QMetaType::QString) {
return QV4::Encode(engine->newString(*qstringPtr));
+ } else if (type == QMetaType::QByteArray) {
+ return QV4::Encode(engine->newArrayBuffer(*qbyteArrayPtr));
} else if (type == QMetaType::QObjectStar) {
QObject *object = qobjectPtr;
if (object)
@@ -1728,10 +1682,10 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
{
Scope valueScope(scope);
Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
- method->d()->object = object;
+ method->d()->setObject(object);
if (QQmlData *ddata = QQmlData::get(object))
- method->d()->propertyCache = ddata->propertyCache;
+ method->d()->setPropertyCache(ddata->propertyCache);
method->d()->index = index;
return method.asReturnedValue();
@@ -1740,23 +1694,23 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
- method->d()->propertyCache = valueType->d()->propertyCache;
+ Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope));
+ method->d()->setPropertyCache(valueType->d()->propertyCache());
method->d()->index = index;
method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
-Heap::QObjectMethod::QObjectMethod(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope)
+void Heap::QObjectMethod::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope);
}
const QMetaObject *Heap::QObjectMethod::metaObject()
{
- if (propertyCache)
- return propertyCache->createMetaObject();
- return object->metaObject();
+ if (propertyCache())
+ return propertyCache()->createMetaObject();
+ return object()->metaObject();
}
QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
@@ -1764,17 +1718,13 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
- result += QString::fromUtf8(metaObject->className());
- result += QLatin1String("(0x");
- result += QString::number((quintptr)d()->object.data(),16);
+ result += QString::fromUtf8(metaObject->className()) +
+ QLatin1String("(0x") + QString::number((quintptr)d()->object(),16);
- if (d()->object) {
- QString objectName = d()->object->objectName();
- if (!objectName.isEmpty()) {
- result += QLatin1String(", \"");
- result += objectName;
- result += QLatin1Char('\"');
- }
+ if (d()->object()) {
+ QString objectName = d()->object()->objectName();
+ if (!objectName.isEmpty())
+ result += QLatin1String(", \"") + objectName + QLatin1Char('\"');
}
result += QLatin1Char(')');
@@ -1787,9 +1737,9 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co
QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
{
- if (!d()->object)
+ if (!d()->object())
return Encode::undefined();
- if (QQmlData::keepAliveDuringGarbageCollection(d()->object))
+ if (QQmlData::keepAliveDuringGarbageCollection(d()->object()))
return ctx->engine()->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
int delay = 0;
@@ -1797,80 +1747,90 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
delay = args[0].toUInt32();
if (delay > 0)
- QTimer::singleShot(delay, d()->object, SLOT(deleteLater()));
+ QTimer::singleShot(delay, d()->object(), SLOT(deleteLater()));
else
- d()->object->deleteLater();
+ d()->object()->deleteLater();
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
+void QObjectMethod::call(const Managed *m, Scope &scope, CallData *callData)
{
const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
- return This->callInternal(callData);
+ This->callInternal(callData, scope);
}
-ReturnedValue QObjectMethod::callInternal(CallData *callData) const
+void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
{
ExecutionEngine *v4 = engine();
ExecutionContext *context = v4->currentContext;
- if (d()->index == DestroyMethod)
- return method_destroy(context, callData->args, callData->argc);
- else if (d()->index == ToStringMethod)
- return method_toString(context);
+ if (d()->index == DestroyMethod) {
+ scope.result = method_destroy(context, callData->args, callData->argc);
+ return;
+ }
+
+ else if (d()->index == ToStringMethod) {
+ scope.result = method_toString(context);
+ return;
+ }
- QQmlObjectOrGadget object(d()->object.data());
- if (!d()->object) {
- if (!d()->valueTypeWrapper)
- return Encode::undefined();
+ QQmlObjectOrGadget object(d()->object());
+ if (!d()->object()) {
+ if (!d()->valueTypeWrapper) {
+ scope.result = Encode::undefined();
+ return;
+ }
- object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr);
}
QQmlPropertyData method;
- if (d()->propertyCache) {
- QQmlPropertyData *data = d()->propertyCache->method(d()->index);
- if (!data)
- return QV4::Encode::undefined();
+ if (d()->propertyCache()) {
+ QQmlPropertyData *data = d()->propertyCache()->method(d()->index);
+ if (!data) {
+ scope.result = QV4::Encode::undefined();
+ return;
+ }
method = *data;
} else {
- const QMetaObject *mo = d()->object->metaObject();
+ const QMetaObject *mo = d()->object()->metaObject();
const QMetaMethod moMethod = mo->method(d()->index);
method.load(moMethod);
- if (method.coreIndex == -1)
- return QV4::Encode::undefined();
+ if (method.coreIndex() == -1) {
+ scope.result = QV4::Encode::undefined();
+ return;
+ }
// Look for overloaded methods
QByteArray methodName = moMethod.name();
const int methodOffset = mo->methodOffset();
for (int ii = d()->index - 1; ii >= methodOffset; --ii) {
if (methodName == mo->method(ii).name()) {
- method.setFlags(method.getFlags() | QQmlPropertyData::IsOverload);
- method.overrideIndexIsProperty = 0;
- method.overrideIndex = ii;
+ method.setOverload(true);
+ method.setOverrideIndexIsProperty(0);
+ method.setOverrideIndex(ii);
break;
}
}
}
if (method.isV4Function()) {
- Scope scope(v4);
- QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
- QQmlV4Function func(callData, rv, v4);
+ scope.result = QV4::Encode::undefined();
+ QQmlV4Function func(callData, &scope.result, v4);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
- object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex, args);
+ object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex(), args);
- return rv->asReturnedValue();
+ return;
}
if (!method.isOverload()) {
- return CallPrecise(object, method, v4, callData);
+ scope.result = CallPrecise(object, method, v4, callData);
} else {
- return CallOverloaded(object, method, v4, callData, d()->propertyCache);
+ scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache());
}
}
@@ -1885,17 +1845,193 @@ void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
DEFINE_OBJECT_VTABLE(QObjectMethod);
-Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex)
- : object(object)
- , signalIndex(signalIndex)
+
+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) {
+
+ QV4::Scope scope(engine);
+ Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocObject<QV4::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), Primitive::fromInt32(value));
+ }
+ }
+}
+
+void QMetaObjectWrapper::construct(const Managed *m, Scope &scope, CallData *callData)
+{
+ const QMetaObjectWrapper *This = static_cast<const QMetaObjectWrapper*>(m);
+ scope.result = This->constructInternal(callData);
+}
+
+ReturnedValue QMetaObjectWrapper::constructInternal(CallData * callData) const {
+
+ d()->ensureConstructorsCache();
+
+ ExecutionEngine *v4 = engine();
+ const QMetaObject* mo = d()->metaObject;
+ if (d()->constructorCount == 0) {
+ return v4->throwTypeError(QStringLiteral("%1 has no invokable constructor")
+ .arg(QLatin1String(mo->className())));
+ }
+
+ Scope scope(v4);
+ Scoped<QObjectWrapper> object(scope);
+
+ if (d()->constructorCount == 1) {
+ object = callConstructor(d()->constructors[0], v4, callData);
+ }
+ else {
+ object = callOverloadedConstructor(v4, callData);
+ }
+ Scoped<QMetaObjectWrapper> metaObject(scope, this);
+ object->defineDefaultProperty(v4->id_constructor(), metaObject);
+ object->setPrototype(const_cast<QMetaObjectWrapper*>(this));
+ return object.asReturnedValue();
+
+}
+
+ReturnedValue QMetaObjectWrapper::callConstructor(const QQmlPropertyData &data, QV4::ExecutionEngine *engine, QV4::CallData *callArgs) const {
+
+ const QMetaObject* mo = d()->metaObject;
+ const QQmlStaticMetaObject object(mo);
+ return CallPrecise(object, data, engine, callArgs, QMetaObject::CreateInstance);
+}
+
+
+ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine *engine, QV4::CallData *callArgs) const {
+ const int numberOfConstructors = d()->constructorCount;
+ const int argumentCount = callArgs->argc;
+ const QQmlStaticMetaObject object(d()->metaObject);
+
+ QQmlPropertyData best;
+ int bestParameterScore = INT_MAX;
+ int bestMatchScore = INT_MAX;
+
+ QV4::Scope scope(engine);
+ QV4::ScopedValue v(scope);
+
+ for (int i = 0; i < numberOfConstructors; i++) {
+ const QQmlPropertyData & attempt = d()->constructors[i];
+ int methodArgumentCount = 0;
+ int *methodArgTypes = 0;
+ if (attempt.hasArguments()) {
+ QQmlMetaObject::ArgTypeStorage storage;
+ int *args = object.constructorParameterTypes(attempt.coreIndex(), &storage, 0);
+ if (!args) // Must be an unknown argument
+ continue;
+
+ methodArgumentCount = args[0];
+ methodArgTypes = args + 1;
+ }
+
+ if (methodArgumentCount > argumentCount)
+ continue; // We don't have sufficient arguments to call this method
+
+ int methodParameterScore = argumentCount - methodArgumentCount;
+ if (methodParameterScore > bestParameterScore)
+ continue; // We already have a better option
+
+ int methodMatchScore = 0;
+ for (int ii = 0; ii < methodArgumentCount; ++ii)
+ methodMatchScore += MatchScore((v = callArgs->args[ii]), methodArgTypes[ii]);
+
+ if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
+ best = attempt;
+ bestParameterScore = methodParameterScore;
+ bestMatchScore = methodMatchScore;
+ }
+
+ if (bestParameterScore == 0 && bestMatchScore == 0)
+ break; // We can't get better than that
+ };
+
+ if (best.isValid()) {
+ return CallPrecise(object, best, engine, callArgs, QMetaObject::CreateInstance);
+ } else {
+ QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
+ for (int i = 0; i < numberOfConstructors; i++) {
+ const QQmlPropertyData & candidate = d()->constructors[i];
+ error += QLatin1String("\n ") +
+ QString::fromUtf8(d()->metaObject->constructor(candidate.coreIndex())
+ .methodSignature());
+ }
+
+ return engine->throwError(error);
+ }
+}
+
+bool QMetaObjectWrapper::isEqualTo(Managed *a, Managed *b)
+{
+ Q_ASSERT(a->as<QMetaObjectWrapper>());
+ QMetaObjectWrapper *aMetaObject = a->as<QMetaObjectWrapper>();
+ QMetaObjectWrapper *bMetaObject = b->as<QMetaObjectWrapper>();
+ if (!bMetaObject)
+ return true;
+ return aMetaObject->metaObject() == bMetaObject->metaObject();
+}
+
+DEFINE_OBJECT_VTABLE(QMetaObjectWrapper);
+
+
+
+
+void Heap::QmlSignalHandler::init(QObject *object, int signalIndex)
{
+ Object::init();
+ this->signalIndex = signalIndex;
+ setObject(object);
}
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
void QmlSignalHandler::initProto(ExecutionEngine *engine)
{
- if (engine->signalHandlerPrototype()->d())
+ if (engine->signalHandlerPrototype()->d_unchecked())
return;
Scope scope(engine);