summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp5
-rw-r--r--src/declarative/qml/qmlcompiler.cpp34
-rw-r--r--src/declarative/qml/qmlcompiler_p.h2
-rw-r--r--src/declarative/qml/qmlcontext.cpp2
-rw-r--r--src/declarative/qml/qmlcontext_p.h1
-rw-r--r--src/declarative/qml/qmlengine.cpp5
-rw-r--r--src/declarative/qml/qmlexpression.cpp32
-rw-r--r--src/declarative/qml/qmlexpression_p.h2
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp25
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp81
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h20
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp85
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/MethodsObject.qml6
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.4.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp9
-rw-r--r--tests/benchmarks/declarative/script/tst_script.cpp4
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()