aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2012-07-11 13:01:33 +1000
committerQt by Nokia <qt-info@nokia.com>2012-08-03 03:38:49 +0200
commitaa25ad8d5f476d6db59012a122833ebe677eaf69 (patch)
tree37eb955dabc252304aefe821d03be5e3857f22c9 /src/qml
parentd64224041efe9febc683cf5ee7155a9cc88058d9 (diff)
Make QQmlScriptString opaque.
Allow for future optimization by encapsulating the raw script data. Change-Id: I1863103e8e6d74ede60593cabb240e16f2ae657e Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qqmlbinding.cpp48
-rw-r--r--src/qml/qml/qqmlbinding_p.h2
-rw-r--r--src/qml/qml/qqmlcompiler.cpp3
-rw-r--r--src/qml/qml/qqmlexpression.cpp30
-rw-r--r--src/qml/qml/qqmlexpression.h2
-rw-r--r--src/qml/qml/qqmlinstruction_p.h3
-rw-r--r--src/qml/qml/qqmlscriptstring.cpp63
-rw-r--r--src/qml/qml/qqmlscriptstring.h16
-rw-r--r--src/qml/qml/qqmlscriptstring_p.h12
-rw-r--r--src/qml/qml/qqmlvme.cpp8
10 files changed, 140 insertions, 47 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 38d305a64e..5860cbe19d 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -50,6 +50,7 @@
#include <private/qqmltrace_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlrewrite_p.h>
+#include <private/qqmlscriptstring_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
@@ -114,6 +115,53 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
v8function = evalFunction(context(), obj, code, QString(), 0);
}
+QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
+: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+{
+ if (ctxt && !ctxt->isValid())
+ return;
+
+ const QQmlScriptStringPrivate *scriptPrivate = script.d.data();
+ if (!ctxt && (!scriptPrivate->context || !scriptPrivate->context->isValid()))
+ return;
+
+ bool needRewrite = true;
+ QString code;
+
+ int id = scriptPrivate->bindingId;
+ if (id >= 0) {
+ QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
+ if (engine && ctxtdata && !ctxtdata->url.isEmpty()) {
+ QQmlTypeData *typeData = engine->typeLoader.getType(ctxtdata->url);
+ Q_ASSERT(typeData);
+
+ if (QQmlCompiledData *cdata = typeData->compiledData()) {
+ needRewrite = false;
+ code = cdata->primitives.at(id);
+ m_url = cdata->name;
+ }
+
+ typeData->release();
+ }
+ }
+
+ if (needRewrite) {
+ QQmlRewrite::RewriteBinding rewriteBinding;
+ code = rewriteBinding(scriptPrivate->script);
+ }
+
+ setNotifyOnValueChanged(true);
+ QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
+ setScopeObject(obj ? obj : scriptPrivate->scope);
+
+ m_expression = scriptPrivate->script.toUtf8();
+ m_lineNumber = scriptPrivate->lineNumber;
+ m_columnNumber = scriptPrivate->columnNumber;
+
+ v8function = evalFunction(context(), scopeObject(), code, QString(), m_lineNumber);
+}
+
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt)
: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding),
m_lineNumber(-1), m_columnNumber(-1)
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index bea74e43e2..888145126c 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -57,6 +57,7 @@
#include "qqmlpropertyvaluesource.h"
#include "qqmlexpression.h"
#include "qqmlproperty.h"
+#include "qqmlscriptstring.h"
#include "qqmlproperty_p.h"
#include <QtCore/QObject>
@@ -79,6 +80,7 @@ public:
Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag)
QQmlBinding(const QString &, QObject *, QQmlContext *);
+ QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *);
QQmlBinding(const QString &, QObject *, QQmlContextData *);
QQmlBinding(const QString &, bool isRewritten, QObject *, QQmlContextData *,
const QString &url, int lineNumber, int columnNumber);
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 539b6c402a..453ee0841b 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -1265,6 +1265,9 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
ss.bindingId = rewriteBinding(prop->values.first()->value, QString()); // XXX
ss.line = prop->location.start.line;
ss.column = prop->location.start.column;
+ ss.isStringLiteral = prop->values.first()->value.isString();
+ ss.isNumberLiteral = prop->values.first()->value.isNumber();
+ ss.numberValue = prop->values.first()->value.asNumber();
output->addInstruction(ss);
}
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 2ab412ba01..76d31448e5 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -202,38 +202,38 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt,
Create a QQmlExpression object that is a child of \a parent.
The \a script provides the expression to be evaluated, the context to evaluate it in,
- and the scope object to evaluate it with.
-
- This constructor is functionally equivalent to the following, but in most cases
- is more efficient.
- \code
- QQmlExpression expression(script.context(), script.scopeObject(), script.script(), parent);
- \endcode
+ and the scope object to evaluate it with. If provided, \a ctxt and \a scope will override
+ the context and scope object provided by \a script.
\sa QQmlScriptString
*/
-QQmlExpression::QQmlExpression(const QQmlScriptString &script, QObject *parent)
+QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt, QObject *scope, QObject *parent)
: QObject(*new QQmlExpressionPrivate, parent)
{
Q_D(QQmlExpression);
+ if (ctxt && !ctxt->isValid())
+ return;
- if (!script.context()->isValid())
+ const QQmlScriptStringPrivate *scriptPrivate = script.d.data();
+ if (!ctxt && (!scriptPrivate->context || !scriptPrivate->context->isValid()))
return;
bool defaultConstruction = true;
+ QQmlContextData *evalCtxtData = QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context);
+ QObject *scopeObject = scope ? scope : scriptPrivate->scope;
- int id = script.d.data()->bindingId;
+ int id = scriptPrivate->bindingId;
if (id >= 0) {
- QQmlContextData *ctxtdata = QQmlContextData::get(script.context());
- QQmlEnginePrivate *engine = QQmlEnginePrivate::get(script.context()->engine());
+ QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
if (engine && ctxtdata && !ctxtdata->url.isEmpty()) {
QQmlTypeData *typeData = engine->typeLoader.getType(ctxtdata->url);
Q_ASSERT(typeData);
if (QQmlCompiledData *cdata = typeData->compiledData()) {
defaultConstruction = false;
- d->init(ctxtdata, cdata->primitives.at(id), true, script.scopeObject(),
- cdata->name, script.d.data()->lineNumber, script.d.data()->columnNumber);
+ d->init(evalCtxtData, cdata->primitives.at(id), true, scopeObject,
+ cdata->name, scriptPrivate->lineNumber, scriptPrivate->columnNumber);
}
typeData->release();
@@ -241,7 +241,7 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QObject *parent)
}
if (defaultConstruction)
- d->init(QQmlContextData::get(script.context()), script.script(), script.scopeObject());
+ d->init(evalCtxtData, scriptPrivate->script, scopeObject);
}
/*!
diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h
index b60d9f1f86..e60af0b054 100644
--- a/src/qml/qml/qqmlexpression.h
+++ b/src/qml/qml/qqmlexpression.h
@@ -65,7 +65,7 @@ class Q_QML_EXPORT QQmlExpression : public QObject
public:
QQmlExpression();
QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = 0);
- explicit QQmlExpression(const QQmlScriptString &, QObject * = 0);
+ explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = 0, QObject * = 0, QObject * = 0);
virtual ~QQmlExpression();
QQmlEngine *engine() const;
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index 313aed137f..5cd06c2e3d 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -332,6 +332,9 @@ union QQmlInstruction
int bindingId;
ushort line;
ushort column;
+ double numberValue;
+ bool isStringLiteral;
+ bool isNumberLiteral;
};
struct instr_storeScript {
QML_INSTR_HEADER
diff --git a/src/qml/qml/qqmlscriptstring.cpp b/src/qml/qml/qqmlscriptstring.cpp
index ed7a6affa1..c38105d4eb 100644
--- a/src/qml/qml/qqmlscriptstring.cpp
+++ b/src/qml/qml/qqmlscriptstring.cpp
@@ -73,6 +73,11 @@ expr.evaluate();
\sa QQmlExpression
*/
+const QQmlScriptStringPrivate* QQmlScriptStringPrivate::get(const QQmlScriptString &script)
+{
+ return script.d.constData();
+}
+
/*!
Constructs an empty instance.
*/
@@ -82,6 +87,17 @@ QQmlScriptString::QQmlScriptString()
}
/*!
+ \internal
+*/
+QQmlScriptString::QQmlScriptString(const QString &script, QQmlContext *context, QObject *scope)
+: d(new QQmlScriptStringPrivate)
+{
+ d->script = script;
+ d->context = context;
+ d->scope = scope;
+}
+
+/*!
Copies \a other.
*/
QQmlScriptString::QQmlScriptString(const QQmlScriptString &other)
@@ -106,51 +122,62 @@ QQmlScriptString &QQmlScriptString::operator=(const QQmlScriptString &other)
}
/*!
-Returns the context for the script.
+Returns whether the QQmlScriptString is empty.
*/
-QQmlContext *QQmlScriptString::context() const
+bool QQmlScriptString::isEmpty() const
{
- return d->context;
+ return d->script.isEmpty();
}
/*!
-Sets the \a context for the script.
+Returns whether the content of the QQmlScriptString is the \c undefined literal.
*/
-void QQmlScriptString::setContext(QQmlContext *context)
+bool QQmlScriptString::isUndefinedLiteral() const
{
- d->context = context;
+ return d->script == QStringLiteral("undefined");
}
/*!
-Returns the scope object for the script.
+Returns whether the content of the QQmlScriptString is the \c null literal.
*/
-QObject *QQmlScriptString::scopeObject() const
+bool QQmlScriptString::isNullLiteral() const
{
- return d->scope;
+ return d->script == QStringLiteral("null");
}
/*!
-Sets the scope \a object for the script.
+If the content of the QQmlScriptString is a string literal, returns that string.
+Otherwise returns a null QString.
*/
-void QQmlScriptString::setScopeObject(QObject *object)
+QString QQmlScriptString::stringLiteral() const
{
- d->scope = object;
+ if (d->isStringLiteral)
+ return d->script.mid(1, d->script.length()-2);
+ return QString();
}
/*!
-Returns the script text.
+If the content of the QQmlScriptString is a number literal, returns that number and
+sets \a ok to true. Otherwise returns 0.0 and sets \a ok to false.
*/
-QString QQmlScriptString::script() const
+qreal QQmlScriptString::numberLiteral(bool *ok) const
{
- return d->script;
+ if (ok)
+ *ok = d->isNumberLiteral;
+ return d->isNumberLiteral ? d->numberValue : 0.;
}
/*!
-Sets the \a script text.
+If the content of the QQmlScriptString is a boolean literal, returns the boolean value and
+sets \a ok to true. Otherwise returns false and sets \a ok to false.
*/
-void QQmlScriptString::setScript(const QString &script)
+bool QQmlScriptString::booleanLiteral(bool *ok) const
{
- d->script = script;
+ bool isTrue = d->script == QStringLiteral("true");
+ bool isFalse = !isTrue && d->script == QStringLiteral("false");
+ if (ok)
+ *ok = isTrue || isFalse;
+ return isTrue ? true : false;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlscriptstring.h b/src/qml/qml/qqmlscriptstring.h
index 15db9088f7..f2ccbb76fd 100644
--- a/src/qml/qml/qqmlscriptstring.h
+++ b/src/qml/qml/qqmlscriptstring.h
@@ -64,20 +64,22 @@ public:
QQmlScriptString &operator=(const QQmlScriptString &);
- QQmlContext *context() const;
- void setContext(QQmlContext *);
+ bool isEmpty() const;
- QObject *scopeObject() const;
- void setScopeObject(QObject *);
-
- QString script() const;
- void setScript(const QString &);
+ bool isUndefinedLiteral() const;
+ bool isNullLiteral() const;
+ QString stringLiteral() const;
+ qreal numberLiteral(bool *ok) const;
+ bool booleanLiteral(bool *ok) const;
private:
+ QQmlScriptString(const QString &script, QQmlContext *context, QObject *scope);
QSharedDataPointer<QQmlScriptStringPrivate> d;
+ friend class QQmlScriptStringPrivate;
friend class QQmlVME;
friend class QQmlExpression;
+ friend class QQmlBinding;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlscriptstring_p.h b/src/qml/qml/qqmlscriptstring_p.h
index 15786c7aae..97c02d21d7 100644
--- a/src/qml/qml/qqmlscriptstring_p.h
+++ b/src/qml/qml/qqmlscriptstring_p.h
@@ -42,14 +42,19 @@
#ifndef QQMLSCRIPTSTRING_P_H
#define QQMLSCRIPTSTRING_P_H
+#include "qqmlscriptstring.h"
#include <QtQml/qqmlcontext.h>
QT_BEGIN_NAMESPACE
-class QQmlScriptStringPrivate : public QSharedData
+class Q_AUTOTEST_EXPORT QQmlScriptStringPrivate : public QSharedData
{
public:
- QQmlScriptStringPrivate() : context(0), scope(0), bindingId(-1), lineNumber(-1), columnNumber(-1) {}
+ QQmlScriptStringPrivate() : context(0), scope(0), bindingId(-1), lineNumber(-1), columnNumber(-1),
+ numberValue(0), isStringLiteral(false), isNumberLiteral(false) {}
+
+ //for testing
+ static const QQmlScriptStringPrivate* get(const QQmlScriptString &script);
QQmlContext *context;
QObject *scope;
@@ -57,6 +62,9 @@ public:
int bindingId;
int lineNumber;
int columnNumber;
+ double numberValue;
+ bool isStringLiteral;
+ bool isNumberLiteral;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index b33f7eed0f..f764b60701 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -772,13 +772,13 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(StoreScriptString)
QObject *target = objects.top();
QObject *scope = objects.at(objects.count() - 1 - instr.scope);
- QQmlScriptString ss;
- ss.setContext(CTXT->asQQmlContext());
- ss.setScopeObject(scope);
- ss.setScript(PRIMITIVES.at(instr.value));
+ QQmlScriptString ss(PRIMITIVES.at(instr.value), CTXT->asQQmlContext(), scope);
ss.d.data()->bindingId = instr.bindingId;
ss.d.data()->lineNumber = instr.line;
ss.d.data()->columnNumber = instr.column;
+ ss.d.data()->isStringLiteral = instr.isStringLiteral;
+ ss.d.data()->isNumberLiteral = instr.isNumberLiteral;
+ ss.d.data()->numberValue = instr.numberValue;
void *a[] = { &ss, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,