diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2012-07-11 13:01:33 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-03 03:38:49 +0200 |
commit | aa25ad8d5f476d6db59012a122833ebe677eaf69 (patch) | |
tree | 37eb955dabc252304aefe821d03be5e3857f22c9 /src/qml | |
parent | d64224041efe9febc683cf5ee7155a9cc88058d9 (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.cpp | 48 | ||||
-rw-r--r-- | src/qml/qml/qqmlbinding_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlexpression.cpp | 30 | ||||
-rw-r--r-- | src/qml/qml/qqmlexpression.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlinstruction_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlscriptstring.cpp | 63 | ||||
-rw-r--r-- | src/qml/qml/qqmlscriptstring.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlscriptstring_p.h | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 8 |
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, |