diff options
author | Chris Adams <christopher.adams@nokia.com> | 2012-03-27 16:56:08 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-29 00:40:48 +0200 |
commit | 53d5deb5034bf5adb8719723bc66eb3a61638a32 (patch) | |
tree | 011c99abcadf6c4ef723586e25c8f56cd6f3b113 /src/qml/qml/qqmlboundsignal.cpp | |
parent | e4baefacff3e04ea3b599c5279e883d75d2ad489 (diff) |
Use minimal javascript expression for bound signals
Previously, QQmlBoundSignal used QQmlExpression internally. This
commit adds a new, more optimal QQmlJavaScriptExpression subclass
specifically designed for QQmlBoundSignal, and converts the code
to use it instead of QQmlExpression where appropriate.
Task-number: QTBUG-24460
Change-Id: I2865a119ce840235e27a7722d8052ca61c265f69
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src/qml/qml/qqmlboundsignal.cpp')
-rw-r--r-- | src/qml/qml/qqmlboundsignal.cpp | 119 |
1 files changed, 109 insertions, 10 deletions
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index b375a70d50..446bad855a 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -49,6 +49,7 @@ #include "qqml.h" #include "qqmlcontext.h" #include "qqmlglobal_p.h" +#include "qqmlrewrite_p.h" #include <private/qqmlprofilerservice_p.h> #include <private/qv8debugservice_p.h> @@ -59,6 +60,105 @@ Q_DECLARE_METATYPE(QJSValue) QT_BEGIN_NAMESPACE +static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = { + QQmlBoundSignalExpression::expressionIdentifier, + QQmlBoundSignalExpression::expressionChanged +}; + +QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression, + bool isRewritten, const QString &fileName, int line, int column) + : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable) +{ + setNotifyOnValueChanged(false); + setContext(ctxt); + setScopeObject(scope); + m_expression = QString::fromUtf8(expression); + m_expressionFunctionValid = false; + m_expressionFunctionRewritten = isRewritten; + m_fileName = fileName; + m_line = line; + m_column = column; +} + +QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression, + bool isRewritten, const QString &fileName, int line, int column) + : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable) +{ + setNotifyOnValueChanged(false); + setContext(ctxt); + setScopeObject(scope); + m_expression = expression; + m_expressionFunctionValid = false; + m_expressionFunctionRewritten = isRewritten; + m_fileName = fileName; + m_line = line; + m_column = column; +} + +QQmlBoundSignalExpression::~QQmlBoundSignalExpression() +{ + qPersistentDispose(m_v8function); + qPersistentDispose(m_v8qmlscope); +} + +QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e) +{ + QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e); + return QLatin1String("\"") + This->m_expression + QLatin1String("\""); +} + +void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *) +{ + // bound signals do not notify on change. +} + +// This mirrors code in QQmlExpressionPrivate::value() and v8value(). +// Any change made here should be made there and vice versa. +void QQmlBoundSignalExpression::evaluate(QObject *secondaryScope) +{ + Q_ASSERT (context() && engine()); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine()); + + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. + { + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(ep->v8engine()->context()); + if (!m_expressionFunctionValid) { + bool ok = true; + QString code; + if (m_expressionFunctionRewritten) { + code = m_expression; + } else { + QQmlRewrite::RewriteSignalHandler rewriteSignalHandler; + code = rewriteSignalHandler(m_expression, m_functionName, &ok); + } + + if (ok) + m_v8function = evalFunction(context(), scopeObject(), code, m_fileName, m_line, &m_v8qmlscope); + + if (m_v8function.IsEmpty() || m_v8function->IsNull()) { + ep->dereferenceScarceResources(); + return; // could not evaluate function. Not valid. + } + + setUseSharedContext(false); + m_expressionFunctionValid = true; + } + + if (secondaryScope) { + QObject *restoreSecondaryScope = 0; + restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, secondaryScope); + QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0); + ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, restoreSecondaryScope); + } else { + QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0); + } + } + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. +} + +//////////////////////////////////////////////////////////////////////// + class QQmlBoundSignalParameters : public QObject { Q_OBJECT @@ -144,7 +244,7 @@ int QQmlBoundSignal::index() const /*! Returns the signal expression. */ -QQmlExpression *QQmlBoundSignal::expression() const +QQmlBoundSignalExpression *QQmlBoundSignal::expression() const { return m_expression; } @@ -156,9 +256,9 @@ QQmlExpression *QQmlBoundSignal::expression() const The QQmlBoundSignal instance takes ownership of \a e. The caller is assumes ownership of the returned QQmlExpression. */ -QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e) +QQmlBoundSignalExpression *QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e) { - QQmlExpression *rv = m_expression; + QQmlBoundSignalExpression *rv = m_expression; m_expression = e; if (m_expression) m_expression->setNotifyOnValueChanged(false); return rv; @@ -183,8 +283,8 @@ int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } if (m_params) m_params->setValues(a); - if (m_expression && m_expression->engine()) { - QQmlExpressionPrivate::get(m_expression)->value(m_params); + if (m_expression && m_expression->context() && m_expression->engine()) { + m_expression->evaluate(m_params); if (m_expression && m_expression->hasError()) QQmlEnginePrivate::warning(m_expression->engine(), m_expression->error()); } @@ -324,7 +424,7 @@ int QQmlBoundSignalNoParams::index() const /*! Returns the signal expression. */ -QQmlExpression *QQmlBoundSignalNoParams::expression() const +QQmlBoundSignalExpression *QQmlBoundSignalNoParams::expression() const { return m_expression; } @@ -336,9 +436,9 @@ QQmlExpression *QQmlBoundSignalNoParams::expression() const The QQmlBoundSignalNoParams instance takes ownership of \a e. The caller is assumes ownership of the returned QQmlExpression. */ -QQmlExpression *QQmlBoundSignalNoParams::setExpression(QQmlExpression *e) +QQmlBoundSignalExpression *QQmlBoundSignalNoParams::setExpression(QQmlBoundSignalExpression *e) { - QQmlExpression *rv = m_expression; + QQmlBoundSignalExpression *rv = m_expression; m_expression = e; if (m_expression) m_expression->setNotifyOnValueChanged(false); return rv; @@ -356,9 +456,8 @@ void QQmlBoundSignalNoParams::subscriptionCallback(QQmlNotifierEndpoint *e) QQmlHandlingSignalProfiler prof(s->m_owner, s->m_index, s->m_expression); s->m_isEvaluating = true; - if (s->m_expression && s->m_expression->engine()) { - QQmlExpressionPrivate::get(s->m_expression)->value(); + s->m_expression->evaluate(); // evaluate signal expression. if (s->m_expression && s->m_expression->hasError()) QQmlEnginePrivate::warning(s->m_expression->engine(), s->m_expression->error()); } |