summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-09-30 08:13:04 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-10-05 02:39:03 (GMT)
commitdff7f0593d86e90eb14c805a96ebbda778f45a82 (patch)
treee2c8c52170bf2884b4c8d138627492739944966b /src/declarative
parent49527e854a9edb0a92e64264d6efac6be46cf0ed (diff)
downloadQt-dff7f0593d86e90eb14c805a96ebbda778f45a82.zip
Qt-dff7f0593d86e90eb14c805a96ebbda778f45a82.tar.gz
Qt-dff7f0593d86e90eb14c805a96ebbda778f45a82.tar.bz2
Improve script lookup caching
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qml.pri10
-rw-r--r--src/declarative/qml/qmlcompiler.cpp20
-rw-r--r--src/declarative/qml/qmlcompiler_p.h4
-rw-r--r--src/declarative/qml/qmlcontext.cpp47
-rw-r--r--src/declarative/qml/qmlcontext_p.h10
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp190
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h89
-rw-r--r--src/declarative/qml/qmlengine.cpp264
-rw-r--r--src/declarative/qml/qmlengine_p.h62
-rw-r--r--src/declarative/qml/qmlinstruction_p.h2
-rw-r--r--src/declarative/qml/qmlintegercache.cpp108
-rw-r--r--src/declarative/qml/qmlintegercache_p.h103
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp2
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp283
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h98
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp20
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h37
-rw-r--r--src/declarative/qml/qmlvme.cpp4
18 files changed, 998 insertions, 355 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 216adb1..1a6dad3 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -35,7 +35,10 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlsqldatabase.cpp \
qml/qmetaobjectbuilder.cpp \
qml/qmlwatcher.cpp \
- qml/qmlpropertycache.cpp
+ qml/qmlpropertycache.cpp \
+ qml/qmlintegercache.cpp \
+ qml/qmlobjectscriptclass.cpp \
+ qml/qmlcontextscriptclass.cpp
HEADERS += qml/qmlparser_p.h \
qml/qmlinstruction_p.h \
@@ -88,7 +91,10 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlsqldatabase_p.h \
qml/qmetaobjectbuilder_p.h \
qml/qmlwatcher_p.h \
- qml/qmlpropertycache_p.h
+ qml/qmlpropertycache_p.h \
+ qml/qmlintegercache_p.h \
+ qml/qmlobjectscriptclass_p.h \
+ qml/qmlcontextscriptclass_p.h
# for qtscript debugger
contains(QT_CONFIG, scripttools):QT += scripttools
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 0b4ac20..5cb2158 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -633,7 +633,7 @@ void QmlCompiler::compileTree(Object *tree)
init.line = 0;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
output->bytecode << init;
genObject(tree);
@@ -964,7 +964,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj)
init.type = QmlInstruction::Init;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
init.line = obj->location.start.line;
output->bytecode << init;
@@ -2263,6 +2263,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
output->bytecode << store;
}
+int QmlCompiler::genContextCache()
+{
+ if (compileState.ids.count() == 0)
+ return -1;
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ for (QHash<QString, QmlParser::Object *>::ConstIterator iter = compileState.ids.begin();
+ iter != compileState.ids.end();
+ ++iter)
+ cache->add(iter.key(), (*iter)->idIndex);
+
+ output->contextCaches.append(cache);
+ return output->contextCaches.count() - 1;
+}
+
bool QmlCompiler::completeComponentBuild()
{
for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 677aba7..1cb66c7 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -63,6 +63,7 @@
#include <private/qmlengine_p.h>
#include <private/qbitfield_p.h>
#include <private/qmlpropertycache_p.h>
+#include <private/qmlintegercache_p.h>
QT_BEGIN_NAMESPACE
@@ -111,6 +112,7 @@ public:
QList<QmlInstruction> bytecode;
QList<QScriptProgram *> programs;
QList<QmlPropertyCache *> propertyCaches;
+ QList<QmlIntegerCache *> contextCaches;
void dumpInstructions();
private:
@@ -232,7 +234,7 @@ private:
QmlParser::Property *prop,
QmlParser::Object *obj,
QmlParser::Property *valueTypeProperty = 0);
-
+ int genContextCache();
int componentTypeRef();
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 97ab375..1c9d177 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -55,7 +55,7 @@
QT_BEGIN_NAMESPACE
QmlContextPrivate::QmlContextPrivate()
-: parent(0), engine(0), isInternal(false), notifyIndex(-1),
+: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1),
highPriorityCount(0), expressions(0), idValues(0), idValueCount(0)
{
}
@@ -103,8 +103,8 @@ void QmlContextPrivate::init()
//set scope chain
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- QScriptValue scopeObj =
- scriptEngine->newObject(QmlEnginePrivate::get(engine)->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
+ QScriptValue scopeObj = QmlEnginePrivate::get(engine)->contextClass->newContext(q);
+
//### no longer need to push global object once we switch to JSC (test with objects added to globalObject)
//if (parent)
// scopeChain = parent->d_func()->scopeChain;
@@ -304,6 +304,9 @@ QmlContext::~QmlContext()
d->contextObjects.clear();
delete [] d->idValues;
+
+ if (d->propertyNames)
+ d->propertyNames->release();
}
void QmlContextPrivate::invalidateEngines()
@@ -361,13 +364,16 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value)
QObject *o = QmlMetaType::toQObject(value);
setContextProperty(name, o);
} else {
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+
+ int idx = d->propertyNames->value(name);
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(value);
} else {
- d->propertyValues[*iter] = value;
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = value;
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
}
@@ -380,15 +386,19 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx,
notifyIndex = q->metaObject()->methodCount();
}
- propertyNames.insert(name, idx);
+ propertyNames->add(name, idx);
idValues[idx].priv = this;
idValues[idx] = obj;
}
-void QmlContextPrivate::setIdPropertyCount(int count)
+void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data)
{
- idValues = new ContextGuard[count];
- idValueCount = count;
+ Q_ASSERT(!propertyNames);
+ propertyNames = data;
+ propertyNames->addref();
+
+ idValueCount = data->count();
+ idValues = new ContextGuard[idValueCount];
}
/*!
@@ -402,14 +412,15 @@ void QmlContext::setContextProperty(const QString &name, QObject *value)
if (d->notifyIndex == -1)
d->notifyIndex = this->metaObject()->methodCount();
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+ int idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(QVariant::fromValue(value));
} else {
- int idx = *iter;
- d->propertyValues[*iter] = QVariant::fromValue(value);
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = QVariant::fromValue(value);
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index b305408..64faa6d 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -61,6 +61,7 @@
#include <QtCore/qset.h>
#include <private/qguard_p.h>
#include <private/qmlengine_p.h>
+#include <private/qmlintegercache_p.h>
QT_BEGIN_NAMESPACE
@@ -82,7 +83,8 @@ public:
QmlEngine *engine;
bool isInternal;
- QHash<QString, int> propertyNames;
+ QmlIntegerCache *propertyNames;
+// QHash<QString, int> propertyNames;
QList<QVariant> propertyValues;
int notifyIndex;
@@ -125,9 +127,13 @@ public:
ContextGuard *idValues;
int idValueCount;
void setIdProperty(const QString &, int, QObject *);
- void setIdPropertyCount(int);
+ void setIdPropertyData(QmlIntegerCache *);
void destroyed(ContextGuard *);
+ static QmlContextPrivate *get(QmlContext *context) {
+ return static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ }
+
// Only used for debugging
QList<QPointer<QObject> > instances;
};
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
new file mode 100644
index 0000000..baea60a
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcontextscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ContextData {
+ ContextData(QmlContext *c) : context(c) {}
+ QGuard<QmlContext> context;
+};
+
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
+ lastPropertyIndex(-1), lastDefaultObject(-1)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, (Object)new ContextData(context));
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(const Object &object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ if (!bindContext)
+ return 0;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ lastPropertyIndex = -1;
+ lastDefaultObject = -1;
+
+ lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1;
+ if (lastPropertyIndex != -1)
+ return QScriptClass::HandlesReadAccess;
+
+ // ### Check for attached properties
+#if 0
+ QmlType *type = 0; ImportedNamespace *ns = 0;
+ if (currentExpression && bindContext == currentExpression->context() &&
+ propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) {
+
+ if (type || ns) {
+ // Must be either an attached property, or an enum
+ resolveData.object = bindContext->d_func()->defaultObjects.first();
+ resolveData.type = type;
+ resolveData.ns = ns;
+ return QScriptClass::HandlesReadAccess;
+ }
+
+ }
+#endif
+
+ for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags);
+
+ if (rv) {
+ lastDefaultObject = ii;
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue QmlContextScriptClass::property(const Object &object, const Identifier &name)
+{
+ Q_UNUSED(object);
+
+ Q_ASSERT(lastPropertyIndex != -1 || lastDefaultObject != -1);
+
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+
+ // ### Check for attached properties
+#if 0
+ if (resolveData.type || resolveData.ns) {
+ QmlTypeNameBridge tnb = {
+ resolveData.object,
+ resolveData.type,
+ resolveData.ns
+ };
+ return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb)));
+ }
+#endif
+
+ if (lastPropertyIndex != -1) {
+
+ QScriptValue rv;
+ if (lastPropertyIndex < cp->idValueCount) {
+ rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data());
+ } else {
+ QVariant value = cp->propertyValues.at(lastPropertyIndex);
+ if (QmlMetaType::isObject(value.userType())) {
+ rv = ep->objectClass->newQObject(QmlMetaType::toQObject(value));
+ } else {
+ // ### Shouldn't this be qScriptValueFromValue()
+ rv = ep->scriptEngine.newVariant(value);
+ }
+ }
+
+ ep->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(bindContext, -1,
+ lastPropertyIndex + cp->notifyIndex);
+
+ return rv;
+ } else {
+
+ // Default object property
+ return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name);
+
+ }
+}
+
+void QmlContextScriptClass::setProperty(const Object &object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_ASSERT(lastDefaultObject != -1);
+
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
new file mode 100644
index 0000000..9ef090d
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXTSCRIPTCLASS_P_H
+#define QMLCONTEXTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlContextScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ QScriptValue newContext(QmlContext *);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual QScriptValue property(const Object &, const Identifier &);
+ virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &);
+
+private:
+ QmlEngine *engine;
+
+ int lastPropertyIndex;
+ int lastDefaultObject;
+
+ uint m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 757670b..d680fa1 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -193,8 +193,6 @@ QmlEnginePrivate::~QmlEnginePrivate()
contextClass = 0;
delete objectClass;
objectClass = 0;
- delete objectClass2;
- objectClass2 = 0;
delete valueTypeClass;
valueTypeClass = 0;
delete typeNameClass;
@@ -242,7 +240,6 @@ void QmlEnginePrivate::init()
scriptEngine.installTranslatorFunctions();
contextClass = new QmlContextScriptClass(q);
objectClass = new QmlObjectScriptClass(q);
- objectClass2 = new QScriptDeclarativeClass(&scriptEngine);
valueTypeClass = new QmlValueTypeScriptClass(q);
typeNameClass = new QmlTypeNameScriptClass(q);
rootContext = new QmlContext(q,true);
@@ -288,95 +285,6 @@ struct QmlValueTypeReference {
};
Q_DECLARE_METATYPE(QmlValueTypeReference);
-////////////////////////////////////////////////////////////////////
-QScriptClass::QueryFlags
-QmlEnginePrivate::queryContext(const QString &propName, uint *id,
- QmlContext *bindContext)
-{
- resolveData.safetyCheckId++;
- *id = resolveData.safetyCheckId;
- resolveData.clear();
-
- QHash<QString, int>::Iterator contextProperty =
- bindContext->d_func()->propertyNames.find(propName);
-
- if (contextProperty != bindContext->d_func()->propertyNames.end()) {
-
- resolveData.context = bindContext;
- resolveData.contextIndex = *contextProperty;
-
- return QScriptClass::HandlesReadAccess;
- }
-
- QmlType *type = 0; ImportedNamespace *ns = 0;
- if (currentExpression && bindContext == currentExpression->context() &&
- propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) {
-
- if (type || ns) {
- // Must be either an attached property, or an enum
- resolveData.object = bindContext->d_func()->defaultObjects.first();
- resolveData.type = type;
- resolveData.ns = ns;
- return QScriptClass::HandlesReadAccess;
- }
-
- }
-
- QScriptClass::QueryFlags rv = 0;
- for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
- rv = queryObject(propName, id,
- bindContext->d_func()->defaultObjects.at(ii));
- }
-
- return rv;
-}
-
-QScriptValue QmlEnginePrivate::propertyContext(const QScriptString &name, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
-
- if (resolveData.type || resolveData.ns) {
- QmlTypeNameBridge tnb = {
- resolveData.object,
- resolveData.type,
- resolveData.ns
- };
- return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb)));
- } else if (resolveData.context) {
- QmlContext *bindContext = resolveData.context;
- QmlContextPrivate *contextPrivate = bindContext->d_func();
- int index = resolveData.contextIndex;
-
- QScriptValue rv;
- if (index < contextPrivate->idValueCount) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data())));
- } else {
- QVariant value = contextPrivate->propertyValues.at(index);
- if (QmlMetaType::isObject(value.userType())) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value));
- } else {
- rv = scriptEngine.newVariant(value);
- }
- }
- capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex);
- return rv;
-
- } else {
-
- return propertyObject(name, resolveData.object, id);
-
- }
-
- return QScriptValue();
-}
-
-void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id)
-{
- // As context properties cannot be written, we can assume that the
- // write is a object property write
- setPropertyObject(value, id);
-}
-
void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id)
{
Q_ASSERT(id == resolveData.safetyCheckId);
@@ -430,7 +338,7 @@ QmlEnginePrivate::queryObject(const QString &propName,
return rv;
}
-QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
+QScriptValue QmlEnginePrivate::propertyObject(const QString &propName,
QObject *obj, uint id)
{
Q_ASSERT(id == resolveData.safetyCheckId);
@@ -461,7 +369,7 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
if (!varobj)
varobj = qvariant_cast<QObject *>(var);
if (varobj) {
- return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
+ return objectClass->newQObject(varobj);
} else {
return qScriptValueFromValue(&scriptEngine, var);
}
@@ -784,8 +692,8 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
QmlEngine* engine)
{
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- return scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newQObject(object, QScriptEngine::AutoOwnership));
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ return enginePriv->objectClass->newQObject(object);
}
/*!
@@ -901,7 +809,7 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi
QUrl url;
if(ctxt->argumentCount() > 2)
url = QUrl(ctxt->argument(2).toString());
- QObject *parentArg = ctxt->argument(1).data().toQObject();
+ QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
QmlContext *qmlCtxt = qmlContext(parentArg);
url = qmlCtxt->resolvedUrl(url);
QmlComponent component(activeEngine, qml.toUtf8(), url);
@@ -1138,13 +1046,15 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
QmlEnginePrivate *ep =
static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == ep->objectClass)
+ return QVariant::fromValue(ep->objectClass->toQObject(val));
+ else if (dc == ep->contextClass)
+ return QVariant();
+
QScriptClass *sc = val.scriptClass();
if (!sc) {
return val.toVariant();
- } else if (sc == ep->contextClass) {
- return QVariant();
- } else if (sc == ep->objectClass) {
- return QVariant::fromValue(val.data().toQObject());
} else if (sc == ep->valueTypeClass) {
QmlValueTypeReference ref =
qvariant_cast<QmlValueTypeReference>(val.data().toVariant());
@@ -1160,56 +1070,6 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
}
/////////////////////////////////////////////////////////////
-/*
- The QmlContextScriptClass handles property access for a QmlContext
- via QtScript.
- */
-QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
-}
-
-QmlContextScriptClass::~QmlContextScriptClass()
-{
-}
-
-QScriptClass::QueryFlags
-QmlContextScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QmlContext *bindContext =
- static_cast<QmlContext*>(object.data().toQObject());
-
- QString propName = name.toString();
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->queryContext(propName, id, bindContext);
-}
-
-QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- Q_UNUSED(object);
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->propertyContext(name, id);
-}
-
-void QmlContextScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_UNUSED(name);
-
- QmlEnginePrivate::get(engine)->setPropertyContext(value, id);
-}
-
-/////////////////////////////////////////////////////////////
QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine)
: QmlScriptClass(engine), object(0), type(0)
{
@@ -1365,108 +1225,6 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
ref.type->write(ref.object, ref.property);
}
-/////////////////////////////////////////////////////////////
-/*
- The QmlObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-
-QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- QString ret = QLatin1String("Qml Object, ");
- if(obj){
- //###Should this be designer or developer details? Dev for now.
- //TODO: Can we print the id too?
- ret += QLatin1String("\"");
- ret += obj->objectName();
- ret += QLatin1String("\" ");
- ret += QLatin1String(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
- ret += QLatin1String(")");
- }else{
- ret += QLatin1String("null");
- }
- return engine->newVariant(ret);
-}
-
-QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- if(obj){
- int delay = 0;
- if(context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- //### Should this be delayed as well?
- context->thisObject().setData(QScriptValue(engine, 0));
- }
- return engine->nullValue();
-}
-
-QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
- engine = bindEngine;
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
- prototypeObject = scriptEngine->newObject();
- prototypeObject.setProperty(QLatin1String("toStr"),//TODO: Why won't toString work?
- scriptEngine->newFunction(QmlObjectToString));
- prototypeObject.setProperty(QLatin1String("destroy"),
- scriptEngine->newFunction(QmlObjectDestroy));
-}
-
-QmlObjectScriptClass::~QmlObjectScriptClass()
-{
-}
-
-QScriptValue QmlObjectScriptClass::prototype() const
-{
- return prototypeObject;
-}
-
-QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QObject *obj = object.data().toQObject();
- QueryFlags rv = 0;
- QString propName = name.toString();
-
- if (obj)
- rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, obj);
-
- return rv;
-}
-
-QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- QObject *obj = object.data().toQObject();
-
- QScriptValue rv =
- QmlEnginePrivate::get(engine)->propertyObject(name, obj, id);
- if (rv.isValid())
- return rv;
-
- return QScriptValue();
-}
-
-void QmlObjectScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(name);
- Q_UNUSED(object);
- QmlEnginePrivate::get(engine)->setPropertyObject(value, id);
-}
-
-
struct QmlEnginePrivate::ImportedNamespace {
QStringList urls;
QList<int> majversions;
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 68019e2..764cc6c 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -73,6 +73,8 @@
#include <QtScript/qscriptengine.h>
#include <private/qmlmetaproperty_p.h>
#include <private/qmlpropertycache_p.h>
+#include <private/qmlobjectscriptclass_p.h>
+#include <private/qmlcontextscriptclass_p.h>
QT_BEGIN_NAMESPACE
@@ -100,13 +102,9 @@ public:
void init();
- QScriptClass::QueryFlags queryContext(const QString &name, uint *id,
- QmlContext *);
- QScriptValue propertyContext(const QScriptString &propName, uint id);
- void setPropertyContext(const QScriptValue &, uint id);
QScriptClass::QueryFlags queryObject(const QString &name, uint *id,
QObject *);
- QScriptValue propertyObject(const QScriptString &propName, QObject *,
+ QScriptValue propertyObject(const QString &propName, QObject *,
uint id = 0);
void setPropertyObject(const QScriptValue &, uint id);
@@ -151,7 +149,6 @@ public:
} resolveData;
QmlContextScriptClass *contextClass;
QmlObjectScriptClass *objectClass;
- QScriptDeclarativeClass *objectClass2;
QmlValueTypeScriptClass *valueTypeClass;
QmlTypeNameScriptClass *typeNameClass;
// Used by DOM Core 3 API
@@ -215,6 +212,7 @@ public:
// ### Fixme
typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
FunctionCache functionCache;
+
QHash<const QMetaObject *, QmlPropertyCache *> propertyCache;
QmlPropertyCache *cache(QObject *obj) {
Q_Q(QmlEngine);
@@ -285,19 +283,6 @@ public:
class QmlScriptClass : public QScriptClass
{
public:
- enum ClassId
- {
- InvalidId = -1,
-
- FunctionId = 0x80000000,
- VariantPropertyId = 0x40000000,
- PropertyId = 0x00000000,
-
- ClassIdMask = 0xC0000000,
-
- ClassIdSelectorMask = 0x3F000000,
- };
-
QmlScriptClass(QmlEngine *);
static QVariant toVariant(QmlEngine *, const QScriptValue &);
@@ -305,45 +290,6 @@ protected:
QmlEngine *engine;
};
-class QmlContextScriptClass : public QmlScriptClass
-{
-public:
- QmlContextScriptClass(QmlEngine *);
- ~QmlContextScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
-class QmlObjectScriptClass : public QmlScriptClass
-{
-public:
- QmlObjectScriptClass(QmlEngine *);
- ~QmlObjectScriptClass();
-
- virtual QScriptValue prototype () const;
- QScriptValue prototypeObject;
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
class QmlTypeNameScriptClass : public QmlScriptClass
{
public:
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index e62bfdf..38b3191 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -165,7 +165,7 @@ public:
struct {
int bindingsSize;
int parserStatusSize;
- int idSize;
+ int contextCache;
} init;
struct {
int type;
diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp
new file mode 100644
index 0000000..1bc4086
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlintegercache_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlIntegerCache::QmlIntegerCache(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlIntegerCache::~QmlIntegerCache()
+{
+ qDeleteAll(stringCache);
+}
+
+void QmlIntegerCache::add(const QString &id, int value)
+{
+ Q_ASSERT(!stringCache.contains(id));
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### use contextClass
+ QScriptDeclarativeClass::PersistentIdentifier<Data> *d =
+ enginePriv->objectClass->createPersistentIdentifier<Data>(id);
+ d->value = value;
+
+ stringCache.insert(id, d);
+ identifierCache.insert(d->identifier, d);
+}
+
+int QmlIntegerCache::value(const QString &id)
+{
+ Data *d = stringCache.value(id);
+ return d?d->value:-1;
+}
+
+QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engine)
+{
+ Q_ASSERT(type);
+ Q_ASSERT(engine);
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ const QMetaObject *mo = type->metaObject();
+
+ for (int ii = mo->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum enumerator = mo->enumerator(ii);
+
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ QString name = QLatin1String(enumerator.key(jj));
+ int value = enumerator.value(jj);
+
+ if (!name.at(0).isUpper())
+ continue;
+
+ if (cache->stringCache.contains(name))
+ continue;
+
+ cache->add(name, value);
+ }
+ }
+
+ return cache;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h
new file mode 100644
index 0000000..fda80c6
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINTEGERCACHE_P_H
+#define QMLINTEGERCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlIntegerCache : public QmlRefCount
+{
+public:
+ QmlIntegerCache(QmlEngine *);
+ virtual ~QmlIntegerCache();
+
+ inline int count() const;
+ void add(const QString &, int);
+ int value(const QString &);
+ inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+
+ static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *);
+private:
+ struct Data {
+ int value;
+ };
+
+ typedef QHash<QString, QScriptDeclarativeClass::PersistentIdentifier<Data> *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, QScriptDeclarativeClass::PersistentIdentifier<Data> *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+int QmlIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+{
+ Data *d = identifierCache.value(id);
+ return d?d->value:-1;
+}
+
+int QmlIntegerCache::count() const
+{
+ return stringCache.count();
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLINTEGERCACHE_P_H
+
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index f7882dc..ec143a7 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -218,7 +218,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (cache) {
QmlPropertyCache::Data *data = cache->property(name);
- if (data && !data->isFunction) {
+ if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) {
type = QmlMetaProperty::Property;
propType = data->propType;
coreIdx = data->coreIndex;
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
new file mode 100644
index 0000000..0ae1809
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlobjectscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qguard_p.h>
+#include <private/qmldeclarativedata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ObjectData {
+ ObjectData(QObject *o) : object(o) {}
+ QGuard<QObject> object;
+};
+
+static QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine)
+{
+ QObject* obj = context->thisObject().data().toQObject();
+ QString ret = QLatin1String("Qml Object, ");
+ if(obj){
+ //###Should this be designer or developer details? Dev for now.
+ //TODO: Can we print the id too?
+ ret += QLatin1String("\"");
+ ret += obj->objectName();
+ ret += QLatin1String("\" ");
+ ret += QLatin1String(obj->metaObject()->className());
+ ret += QLatin1String("(0x");
+ ret += QString::number((quintptr)obj,16);
+ ret += QLatin1String(")");
+ }else{
+ ret += QLatin1String("null");
+ }
+ return engine->newVariant(ret);
+}
+
+static QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine)
+{
+ QObject* obj = context->thisObject().toQObject();
+ if(obj){
+ int delay = 0;
+ if(context->argumentCount() > 0)
+ delay = context->argument(0).toInt32();
+ obj->deleteLater();
+ //### Should this be delayed as well?
+ context->thisObject().setData(QScriptValue(engine, 0));
+ }
+ return engine->nullValue();
+}
+
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript. It is also used to provide a more useful API in
+ QtScript for QML.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0),
+ engine(bindEngine)
+{
+ engine = bindEngine;
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
+
+ m_destroy = scriptEngine->newFunction(QmlObjectDestroy);
+ m_destroyId = createPersistentIdentifier<Dummy>(QLatin1String("destroy"));
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+ delete m_destroyId;
+}
+
+QScriptValue QmlObjectScriptClass::newQObject(QObject *object)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, (Object)new ObjectData(object));
+}
+
+QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const
+{
+ return value.toQObject();
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(const Object &object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ return queryProperty(toQObject(object), name, flags);
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+ lastData = 0;
+
+ if (name == m_destroyId->identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ if (!obj)
+ return 0;
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (ddata) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (cache) {
+ QmlPropertyCache::Data *property = cache->property(name);
+ if (!property) return 0;
+
+ if (flags == QScriptClass::HandlesReadAccess) {
+ lastData = property;
+ return QScriptClass::HandlesReadAccess;
+ } else if (property->propType > 0 && property->propType < QVariant::UserType) {
+ lastData = property;
+ return flags;
+ }
+ }
+
+ // Fallback
+ return QmlEnginePrivate::get(engine)->queryObject(toString(name), &m_id, obj);
+}
+
+QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifier &name)
+{
+ return property(toQObject(object), name);
+}
+
+QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
+{
+ if (name == m_destroyId->identifier)
+ return m_destroy;
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (!obj) {
+ return QScriptValue();
+ } else if (lastData) {
+
+ if (lastData->flags & QmlPropertyCache::Data::IsFunction) {
+ // ### Optimize
+ QScriptValue sobj = scriptEngine->newQObject(obj);
+ return sobj.property(toString(name));
+ } else {
+ QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
+ if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
+ enginePriv->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex,
+ lastData->notifyIndex);
+ }
+
+ if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ QObject *rv = *(QObject **)var.constData();
+ return newQObject(rv);
+ } else {
+ return qScriptValueFromValue(scriptEngine, var);
+ }
+ }
+
+ } else {
+ return QmlEnginePrivate::get(engine)->propertyObject(toString(name), obj, m_id);
+ }
+}
+
+void QmlObjectScriptClass::setProperty(const Object &object,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ return setProperty(toQObject(object), name, value);
+}
+
+void QmlObjectScriptClass::setProperty(QObject *obj,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(object);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (!obj) {
+ return;
+ } else if (lastData) {
+ switch (lastData->propType) {
+ case 1:
+ {
+ bool b = value.toBoolean();
+ void *a[1];
+ a[0] = &b;
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a);
+ }
+ break;
+
+ case 2:
+ {
+ int b = value.toInteger();
+ void *a[1];
+ a[0] = &b;
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a);
+ }
+ break;
+
+ case 6:
+ {
+ double b = value.toNumber();
+ void *a[1];
+ a[0] = &b;
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a);
+ }
+ break;
+
+ default:
+ {
+ QMetaProperty p = obj->metaObject()->property(lastData->coreIndex);
+ p.write(obj, value.toVariant());
+ }
+ }
+ } else {
+ QmlEnginePrivate::get(engine)->setPropertyObject(value, m_id);
+ }
+}
+
+QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok)
+{
+ if (ok) *ok = true;
+
+ ObjectData *data = (ObjectData*)object;
+ return data->object.data();
+}
+
+void QmlObjectScriptClass::destroyed(const Object &object)
+{
+ ObjectData *data = (ObjectData*)object;
+ delete data;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
new file mode 100644
index 0000000..c25718c
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBJECTSCRIPTCLASS_P_H
+#define QMLOBJECTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlObjectScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ QScriptValue newQObject(QObject *);
+ QObject *toQObject(const QScriptValue &) const;
+
+ QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ QScriptValue property(QObject *, const Identifier &);
+ void setProperty(QObject *, const Identifier &name, const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(const Object &, const Identifier &);
+ virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &);
+ virtual QObject *toQObject(const Object &, bool *ok = 0);
+ virtual void destroyed(const Object &);
+
+private:
+ uint m_id;
+ QmlPropertyCache::Data *lastData;
+ struct Dummy {};
+ PersistentIdentifier<Dummy> *m_destroyId;
+ QScriptValue m_destroy;
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLOBJECTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
index f88b3a3..95b819a 100644
--- a/src/declarative/qml/qmlpropertycache.cpp
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -42,6 +42,8 @@
#include "qmlpropertycache_p.h"
#include "qmlengine_p.h"
+QT_BEGIN_NAMESPACE
+
QmlPropertyCache::QmlPropertyCache()
{
}
@@ -78,12 +80,19 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject
QMetaProperty p = metaObject->property(ii);
QString propName = QLatin1String(p.name());
- QScriptDeclarativeClass::PersistentIdentifier<Data> *data =
- enginePriv->objectClass2->createPersistentIdentifier<Data>(propName);
+ QScriptDeclarativeClass::PersistentIdentifier<RData> *data =
+ enginePriv->objectClass->createPersistentIdentifier<RData>(propName);
+
data->propType = p.userType();
data->coreIndex = ii;
+ data->notifyIndex = p.notifySignalIndex();
data->name = propName;
+ if (p.isConstant())
+ data->flags |= Data::IsConstant;
+ if (QmlMetaType::isObject(data->propType))
+ data->flags |= Data::IsQObjectDerived;
+
cache->indexCache[ii] = data;
if (cache->stringCache.contains(propName))
@@ -107,14 +116,14 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject
if (cache->stringCache.contains(methodName))
continue;
- QScriptDeclarativeClass::PersistentIdentifier<Data> *data =
- enginePriv->objectClass2->createPersistentIdentifier<Data>(methodName);
+ QScriptDeclarativeClass::PersistentIdentifier<RData> *data =
+ enginePriv->objectClass->createPersistentIdentifier<RData>(methodName);
cache->stringCache.insert(methodName, data);
cache->identifierCache.insert(data->identifier, data);
data->addref();
data->addref();
- data->isFunction = true;
+ data->flags |= Data::IsFunction;
}
return cache;
@@ -135,3 +144,4 @@ QmlPropertyCache::property(const QString &str) const
return stringCache.value(str);
}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index c10fafa..21c8ef3 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -67,33 +67,50 @@ public:
QmlPropertyCache();
virtual ~QmlPropertyCache();
- struct Data : public QmlRefCount {
- Data() : isFunction(false) {}
+ struct Data {
+ inline Data();
- bool isFunction;
+ enum Flag { IsFunction = 0x00000001,
+ IsQObjectDerived = 0x00000002,
+ IsConstant = 0x00000004 };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ Flags flags;
int propType;
int coreIndex;
+ int notifyIndex;
QString name;
};
static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
- Data *property(const QScriptDeclarativeClass::Identifier &id) const {
- return identifierCache.value(id);
- }
-
+ inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
Data *property(const QString &) const;
Data *property(int) const;
private:
- typedef QVector<QScriptDeclarativeClass::PersistentIdentifier<Data> *> IndexCache;
- typedef QHash<QString, QScriptDeclarativeClass::PersistentIdentifier<Data> *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, QScriptDeclarativeClass::PersistentIdentifier<Data> *> IdentifierCache;
+ struct RData : public Data, public QmlRefCount {};
+
+ typedef QVector<QScriptDeclarativeClass::PersistentIdentifier<RData> *> IndexCache;
+ typedef QHash<QString, QScriptDeclarativeClass::PersistentIdentifier<RData> *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, QScriptDeclarativeClass::PersistentIdentifier<RData> *> IdentifierCache;
IndexCache indexCache;
StringCache stringCache;
IdentifierCache identifierCache;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlPropertyCache::Data::Flags);
+
+QmlPropertyCache::Data::Data()
+: flags(0), propType(0), coreIndex(-1), notifyIndex(-1)
+{
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index a5d2732..4ba412b 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -166,8 +166,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (instr.init.parserStatusSize)
parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
- if (instr.init.idSize)
- cp->setIdPropertyCount(instr.init.idSize);
+ if (instr.init.contextCache != -1)
+ cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
}
break;