diff options
-rw-r--r-- | src/declarative/qml/qmlcompileddata.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 34 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression.cpp | 32 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlobjectscriptclass.cpp | 25 | ||||
-rw-r--r-- | src/declarative/qml/qmlpropertycache.cpp | 81 | ||||
-rw-r--r-- | src/declarative/qml/qmlpropertycache_p.h | 20 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject.cpp | 85 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject_p.h | 14 | ||||
-rw-r--r-- | tests/auto/declarative/qmlecmascript/data/MethodsObject.qml | 6 | ||||
-rw-r--r-- | tests/auto/declarative/qmlecmascript/data/methods.4.qml | 11 | ||||
-rw-r--r-- | tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 9 | ||||
-rw-r--r-- | tests/benchmarks/declarative/script/tst_script.cpp | 4 |
17 files changed, 266 insertions, 72 deletions
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index 198b574..de9bf96 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -162,7 +162,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l) } QmlCompiledData::QmlCompiledData() -: importCache(0), root(0) +: importCache(0), root(0), rootPropertyCache(0) { } @@ -182,6 +182,9 @@ QmlCompiledData::~QmlCompiledData() if (importCache) importCache->release(); + if (rootPropertyCache) + rootPropertyCache->release(); + qDeleteAll(cachedPrograms); qDeleteAll(cachedClosures); } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 7f11a23..7f8bc7a 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -90,7 +90,7 @@ using namespace QmlParser; Instantiate a new QmlCompiler. */ QmlCompiler::QmlCompiler() -: output(0), engine(0) +: output(0), engine(0), unitRoot(0), unit(0) { } @@ -611,6 +611,7 @@ bool QmlCompiler::compile(QmlEngine *engine, this->engine = engine; this->unit = unit; + this->unitRoot = root; compileTree(root); if (!isError()) { @@ -626,6 +627,8 @@ bool QmlCompiler::compile(QmlEngine *engine, savedCompileStates.clear(); output = 0; this->engine = 0; + this->unit = 0; + this->unitRoot = 0; return !isError(); } @@ -836,7 +839,19 @@ void QmlCompiler::genObject(QmlParser::Object *obj) meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); // ### Surely the creation of this property cache could be more efficient - output->propertyCaches << QmlPropertyCache::create(engine, obj->metaObject()); + QmlPropertyCache *propertyCache = 0; + if (tr.component && QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache) { + propertyCache = QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache->copy(); + } else { + propertyCache = QmlPropertyCache::create(engine, obj->metaObject()->superClass()); + } + propertyCache->append(engine, obj->metaObject(), QmlPropertyCache::Data::NoFlags, + QmlPropertyCache::Data::IsVMEFunction); + if (obj == unitRoot) { + propertyCache->addref(); + output->rootPropertyCache = propertyCache; + } + output->propertyCaches << propertyCache; output->bytecode << meta; } @@ -2341,13 +2356,24 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const Object::DynamicSlot &s = obj->dynamicSlots.at(ii); + Object::DynamicSlot &s = obj->dynamicSlots[ii]; QByteArray sig(s.name + '('); + QString funcScript(QLatin1String("(function(")); + for (int jj = 0; jj < s.parameterNames.count(); ++jj) { - if (jj) sig.append(','); + if (jj) { + sig.append(','); + funcScript.append(QLatin1Char(',')); + } + funcScript.append(s.parameterNames.at(jj)); sig.append("QVariant"); } sig.append(')'); + funcScript.append(QLatin1Char(')')); + funcScript.append(s.body); + funcScript.append(QLatin1Char(')')); + s.body = funcScript; + QMetaMethodBuilder b = builder.addSlot(sig); b.setReturnType("QVariant"); b.setParameterNames(s.parameterNames); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 740d97c..c0e50e4 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -107,6 +107,7 @@ public: const QMetaObject *root; QAbstractDynamicMetaObject rootData; + QmlPropertyCache *rootPropertyCache; QList<QString> primitives; QList<float> floatData; QList<int> intData; @@ -324,6 +325,7 @@ private: QList<QmlError> exceptions; QmlCompiledData *output; QmlEngine *engine; + QmlParser::Object *unitRoot; QmlCompositeTypeData *unit; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index e063981..e7ac864 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() -: parent(0), engine(0), isInternal(false), isTemporary(false), propertyNames(0), +: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1), highPriorityCount(0), imports(0), expressions(0), contextObjects(0), idValues(0), idValueCount(0), optimizedBindings(0) { diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index cb89474..e682ee2 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -88,7 +88,6 @@ public: QmlEngine *engine; bool isInternal; - bool isTemporary; QmlIntegerCache *propertyNames; QList<QVariant> propertyValues; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 9c795bd..5479463 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -649,10 +649,7 @@ QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt) QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3); Q_ASSERT(scopeNode.isValid()); Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass); - QmlContext *context = contextClass->contextFromValue(scopeNode); - while (context && QmlContextPrivate::get(context)->isTemporary) - context = context->parentContext(); - return context; + return contextClass->contextFromValue(scopeNode); } QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt, diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 1321601..1587d61 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -138,19 +138,13 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, dd->cachedPrograms[progIdx] = new QScriptProgram(data->expression, data->url, data->line); } -#endif - - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); -#if !defined(Q_OS_SYMBIAN) - data->expressionFunction = scriptEngine->evaluate(*dd->cachedPrograms.at(progIdx)); + data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx)); #else - data->expressionFunction = scriptEngine->evaluate(data->expression); + data->expressionFunction = evalInObjectScope(ctxt, me, data->expression); #endif data->expressionFunctionValid = true; - scriptEngine->popContext(); } } @@ -158,6 +152,28 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, data->me = me; } +QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object, + const QString &program) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine()); + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); + scriptContext->pushScope(ep->contextClass->newContext(context, object)); + QScriptValue rv = ep->scriptEngine.evaluate(program); + ep->scriptEngine.popContext(); + return rv; +} + +QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object, + const QScriptProgram &program) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine()); + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); + scriptContext->pushScope(ep->contextClass->newContext(context, object)); + QScriptValue rv = ep->scriptEngine.evaluate(program); + ep->scriptEngine.popContext(); + return rv; +} + /*! \class QmlExpression \brief The QmlExpression class evaluates ECMAScript in a QML context. diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 3f87b2f..8561a57 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -164,6 +164,8 @@ public: } static void exceptionToError(QScriptEngine *, QmlError &); + static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QString &); + static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QScriptProgram &); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 73dfd75..cb665d1 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -48,6 +48,7 @@ #include "qmllistscriptclass_p.h" #include "qmlbinding.h" #include "qmlguard_p.h" +#include "qmlvmemetaobject_p.h" #include <QtCore/qtimer.h> @@ -216,9 +217,13 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace); } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) { - // ### Optimize - QScriptValue sobj = scriptEngine->newQObject(obj); - return sobj.property(toString(name)); + if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) { + return ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex); + } else { + // ### Optimize + QScriptValue sobj = scriptEngine->newQObject(obj); + return sobj.property(toString(name)); + } } else { if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) { enginePriv->capturedProperties << @@ -251,37 +256,37 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name qreal rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::Int) { int rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::Bool) { bool rv = false; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::QString) { QString rv; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::UInt) { uint rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::Float) { float rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else if (lastData->propType == QMetaType::Double) { double rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); - return QScriptValue(rv); + return QScriptValue(scriptEngine, rv); } else { QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); return enginePriv->scriptValueFromVariant(var); diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index bc7d7de..394fa35 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -87,8 +87,8 @@ void QmlPropertyCache::Data::load(const QMetaMethod &m) } -QmlPropertyCache::QmlPropertyCache(QmlEngine *engine) -: QmlCleanup(engine) +QmlPropertyCache::QmlPropertyCache(QmlEngine *e) +: QmlCleanup(e), engine(e) { } @@ -145,6 +145,83 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, return rv; } +QmlPropertyCache *QmlPropertyCache::copy() const +{ + QmlPropertyCache *cache = new QmlPropertyCache(engine); + cache->indexCache = indexCache; + cache->stringCache = stringCache; + cache->identifierCache = identifierCache; + + for (int ii = 0; ii < indexCache.count(); ++ii) + indexCache.at(ii)->addref(); + for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) + (*iter)->addref(); + for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter) + (*iter)->addref(); + + return cache; +} + +void QmlPropertyCache::append(QmlEngine *engine, const QMetaObject *metaObject, + Data::Flag propertyFlags, Data::Flag methodFlags) +{ + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + int propCount = metaObject->propertyCount(); + int propOffset = metaObject->propertyOffset(); + + indexCache.resize(propCount); + for (int ii = propOffset; ii < propCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + QString propName = QString::fromUtf8(p.name()); + + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); + + data->load(p, engine); + data->flags |= propertyFlags; + + indexCache[ii] = data; + + if (stringCache.contains(propName)) { + stringCache[propName]->release(); + identifierCache[data->identifier.identifier]->release(); + } + + stringCache.insert(propName, data); + identifierCache.insert(data->identifier.identifier, data); + data->addref(); + data->addref(); + } + + int methodCount = metaObject->methodCount(); + int methodOffset = metaObject->methodOffset(); + for (int ii = methodOffset; ii < methodCount; ++ii) { + QMetaMethod m = metaObject->method(ii); + QString methodName = QString::fromUtf8(m.signature()); + + int parenIdx = methodName.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + methodName = methodName.left(parenIdx); + + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName); + + if (stringCache.contains(methodName)) { + stringCache[methodName]->release(); + identifierCache[data->identifier.identifier]->release(); + } + + data->load(m); + if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method) + data->flags |= methodFlags; + + stringCache.insert(methodName, data); + identifierCache.insert(data->identifier.identifier, data); + data->addref(); + } +} + // ### Optimize - check engine for the parent meta object etc. QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject) { diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 50b4cf2..feaa683 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -75,18 +75,21 @@ public: inline bool operator==(const Data &); enum Flag { + NoFlags = 0x00000000, + // Can apply to all properties, except IsFunction IsConstant = 0x00000001, IsWritable = 0x00000002, // These are mutually exclusive IsFunction = 0x00000004, - IsQObjectDerived = 0x00000008, - IsEnumType = 0x00000010, - IsQmlList = 0x00000020, - IsQList = 0x00000040, - IsQmlBinding = 0x00000080, - IsQScriptValue = 0x00000100 + IsVMEFunction = 0x00000008, + IsQObjectDerived = 0x00000010, + IsEnumType = 0x00000020, + IsQmlList = 0x00000040, + IsQList = 0x00000080, + IsQmlBinding = 0x00000100, + IsQScriptValue = 0x00000200 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -112,6 +115,10 @@ public: void update(QmlEngine *, const QMetaObject *); + QmlPropertyCache *copy() const; + void append(QmlEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags, + Data::Flag methodFlags = Data::NoFlags); + static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); static Data create(const QMetaObject *, const QString &); @@ -131,6 +138,7 @@ private: typedef QHash<QString, RData *> StringCache; typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache; + QmlEngine *engine; IndexCache indexCache; StringCache stringCache; IdentifierCache identifierCache; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index 3b1f068..c863ffd 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -44,6 +44,7 @@ #include "qml.h" #include "qmlrefcount_p.h" #include "qmlexpression.h" +#include "qmlexpression_p.h" #include "qmlcontext_p.h" #include <QColor> @@ -56,11 +57,11 @@ QT_BEGIN_NAMESPACE QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QmlVMEMetaData *meta, - QmlRefCount *rc) -: object(obj), ref(rc), ctxt(qmlContext(obj)), metaData(meta), parent(0) + QmlCompiledData *cdata) +: object(obj), compiledData(cdata), ctxt(qmlContext(obj)), metaData(meta), methods(0), + parent(0) { - if (ref) - ref->addref(); + compiledData->addref(); *static_cast<QMetaObject *>(this) = *other; this->d.superdata = obj->metaObject(); @@ -91,12 +92,11 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, QmlVMEMetaObject::~QmlVMEMetaObject() { - if (ref) - ref->release(); - if (parent) - delete parent; + compiledData->release(); + delete parent; qDeleteAll(listProperties); delete [] data; + delete [] methods; } int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) @@ -260,29 +260,25 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) id -= plainSignals; if (id < metaData->methodCount) { - QmlVMEMetaData::MethodData *data = metaData->methodData() + id; - const QChar *body = - (const QChar *)(((const char*)metaData) + data->bodyOffset); + if (!ctxt->engine()) + return -1; // We can't run the method - QString code = QString::fromRawData(body, data->bodyLength); + QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine()); - QVariant rv; - if (0 == (metaData->methodData() + id)->parameterCount) { - QmlExpression expr(ctxt, code, object); - expr.setTrackChange(false); - rv = expr.value(); - } else { - QmlContext newCtxt(ctxt); - QmlContextPrivate::get(&newCtxt)->isTemporary = true; - QMetaMethod m = method(_id); - QList<QByteArray> names = m.parameterNames(); - for (int ii = 0; ii < names.count(); ++ii) - newCtxt.setContextProperty(QString::fromLatin1(names.at(ii)), *(QVariant *)a[ii + 1]); - QmlExpression expr(&newCtxt, code, object); - expr.setTrackChange(false); - rv = expr.value(); + QScriptValue function = method(id); + + QScriptValueList args; + QmlVMEMetaData::MethodData *data = metaData->methodData() + id; + if (data->parameterCount) { + for (int ii = 0; ii < data->parameterCount; ++ii) { + args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]); + } } - if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = rv; + QScriptValue rv = function.call(ep->objectClass->newQObject(object), args); + + if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv); + + return -1; } return -1; } @@ -294,6 +290,29 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) return object->qt_metacall(c, _id, a); } +QScriptValue QmlVMEMetaObject::method(int index) +{ + if (!methods) + methods = new QScriptValue[metaData->methodCount]; + + if (!methods[index].isValid()) { + QmlVMEMetaData::MethodData *data = metaData->methodData() + index; + + const QChar *body = + (const QChar *)(((const char*)metaData) + data->bodyOffset); + + QString code = QString::fromRawData(body, data->bodyLength); + + // XXX Use QScriptProgram + // XXX We should evaluate all methods in a single big script block to + // improve the call time between dynamic methods defined on the same + // object + methods[index] = QmlExpressionPrivate::evalInObjectScope(ctxt, object, code); + } + + return methods[index]; +} + void QmlVMEMetaObject::listChanged(int id) { activate(object, methodOffset + id, 0); @@ -307,5 +326,15 @@ void QmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QmlPropert interceptors.insert(index, qMakePair(valueIndex, interceptor)); } +QScriptValue QmlVMEMetaObject::vmeMethod(int index) +{ + if (index < methodOffset) { + Q_ASSERT(parent); + return static_cast<QmlVMEMetaObject *>(parent)->vmeMethod(index); + } + int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount; + Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + metaData->methodCount)); + return method(index - methodOffset - plainSignals); +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 462f652..497d8f6 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -62,6 +62,7 @@ #include <private/qobject_p.h> #include "qmlguard_p.h" +#include "qmlcompiler_p.h" QT_BEGIN_NAMESPACE @@ -88,7 +89,7 @@ struct QmlVMEMetaData int parameterCount; int bodyOffset; int bodyLength; - int _dummy; + int scriptProgram; }; PropertyData *propertyData() const { @@ -108,18 +109,18 @@ class QmlRefCount; class QmlVMEMetaObject : public QAbstractDynamicMetaObject { public: - QmlVMEMetaObject(QObject *, const QMetaObject *, const QmlVMEMetaData *data, - QmlRefCount * = 0); + QmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QmlVMEMetaData *data, + QmlCompiledData *compiledData); ~QmlVMEMetaObject(); void registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor); - + QScriptValue vmeMethod(int index); protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); private: QObject *object; - QmlRefCount *ref; + QmlCompiledData *compiledData; QmlGuard<QmlContext> ctxt; const QmlVMEMetaData *metaData; @@ -131,6 +132,9 @@ private: QBitArray aInterceptors; QHash<int, QPair<int, QmlPropertyValueInterceptor*> > interceptors; + QScriptValue *methods; + QScriptValue method(int); + QAbstractDynamicMetaObject *parent; void listChanged(int); diff --git a/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml b/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml new file mode 100644 index 0000000..f51ca86 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/MethodsObject.qml @@ -0,0 +1,6 @@ +import Qt 4.6 + +QtObject { + function testFunction() { return 19; } + function testFunction2() { return 18; } +} diff --git a/tests/auto/declarative/qmlecmascript/data/methods.4.qml b/tests/auto/declarative/qmlecmascript/data/methods.4.qml new file mode 100644 index 0000000..aac711c --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/methods.4.qml @@ -0,0 +1,11 @@ +import Qt 4.6 + +MethodsObject { + function testFunction2() { return 17; } + function testFunction3() { return 16; } + + property int test: testFunction() + property int test2: testFunction2() + property int test3: testFunction3() +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index f560a90..6f7832a 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -206,6 +206,15 @@ void tst_qmlecmascript::methods() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 19); } + + { + QmlComponent component(&engine, TEST_FILE("methods.4.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 17); + QCOMPARE(object->property("test3").toInt(), 16); + } } void tst_qmlecmascript::bindingLoop() diff --git a/tests/benchmarks/declarative/script/tst_script.cpp b/tests/benchmarks/declarative/script/tst_script.cpp index 3c0805a..f417d0c 100644 --- a/tests/benchmarks/declarative/script/tst_script.cpp +++ b/tests/benchmarks/declarative/script/tst_script.cpp @@ -157,10 +157,10 @@ void tst_script::property_js() } } -static QScriptValue property_getter_method(QScriptContext *, QScriptEngine *) +static QScriptValue property_getter_method(QScriptContext *, QScriptEngine *engine) { static int x = 0; - return QScriptValue(x++); + return QScriptValue(engine,x++); } void tst_script::property_getter() |