aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmljavascriptexpression_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmljavascriptexpression_p.h')
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
new file mode 100644
index 0000000000..5d790e4570
--- /dev/null
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLJAVASCRIPTEXPRESSION_P_H
+#define QQMLJAVASCRIPTEXPRESSION_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/qv8_p.h>
+#include <QtCore/qglobal.h>
+#include <QtQml/qqmlerror.h>
+#include <private/qqmlengine_p.h>
+#include <private/qpointervaluepair_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDelayedError
+{
+public:
+ inline QQmlDelayedError() : nextError(0), prevError(0) {}
+ inline ~QQmlDelayedError() { removeError(); }
+
+ QQmlError error;
+
+ bool addError(QQmlEnginePrivate *);
+
+ inline void removeError() {
+ if (!prevError) return;
+ if (nextError) nextError->prevError = prevError;
+ *prevError = nextError;
+ nextError = 0;
+ prevError = 0;
+ }
+
+private:
+ QQmlDelayedError *nextError;
+ QQmlDelayedError **prevError;
+};
+
+class QQmlJavaScriptExpression
+{
+public:
+ // Although this looks crazy, we implement our own "vtable" here, rather than relying on
+ // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage
+ // location that is use for the vtable to also store the rarely used delayed error.
+ // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
+ // memory for every expression.
+ struct VTable {
+ QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
+ void (*expressionChanged)(QQmlJavaScriptExpression *);
+ };
+
+ QQmlJavaScriptExpression(VTable *vtable);
+
+ v8::Local<v8::Value> evaluate(QQmlContextData *, v8::Handle<v8::Function>,
+ bool *isUndefined);
+
+ inline bool requiresThisObject() const;
+ inline void setRequiresThisObject(bool v);
+ inline bool useSharedContext() const;
+ inline void setUseSharedContext(bool v);
+ inline bool notifyOnValueChanged() const;
+
+ void setNotifyOnValueChanged(bool v);
+ void resetNotifyOnValueChanged();
+
+ inline QObject *scopeObject() const;
+ inline void setScopeObject(QObject *v);
+
+ class DeleteWatcher {
+ public:
+ inline DeleteWatcher(QQmlJavaScriptExpression *);
+ inline ~DeleteWatcher();
+ inline bool wasDeleted() const;
+ private:
+ friend class QQmlJavaScriptExpression;
+ QObject *_c;
+ QQmlJavaScriptExpression **_w;
+ QQmlJavaScriptExpression *_s;
+ };
+
+ inline bool hasError() const;
+ inline bool hasDelayedError() const;
+ QQmlError error() const;
+ void clearError();
+ QQmlDelayedError *delayedError();
+
+ static void exceptionToError(v8::Handle<v8::Message>, QQmlError &);
+ static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
+ const QString &code, const QString &filename,
+ int line,
+ v8::Persistent<v8::Object> *qmlscope = 0);
+ static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
+ const char *code, int codeLength,
+ const QString &filename, int line,
+ v8::Persistent<v8::Object> *qmlscope = 0);
+protected:
+ ~QQmlJavaScriptExpression();
+
+private:
+ typedef QQmlJavaScriptExpressionGuard Guard;
+ friend class QQmlJavaScriptExpressionGuard;
+
+ struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
+ GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e)
+ : engine(engine), expression(e), errorString(0) { }
+
+ ~GuardCapture() {
+ Q_ASSERT(guards.isEmpty());
+ Q_ASSERT(errorString == 0);
+ }
+
+ virtual void captureProperty(QQmlNotifier *);
+ virtual void captureProperty(QObject *, int, int);
+
+ QQmlEngine *engine;
+ QQmlJavaScriptExpression *expression;
+ QFieldList<Guard, &Guard::next> guards;
+ QStringList *errorString;
+ };
+
+ QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
+
+ // We store some flag bits in the following flag pointers.
+ // m_scopeObject:flag1 - requiresThisObject
+ // activeGuards:flag1 - notifyOnValueChanged
+ // activeGuards:flag2 - useSharedContext
+ QBiPointer<QObject, DeleteWatcher> m_scopeObject;
+ QForwardFieldList<Guard, &Guard::next> activeGuards;
+
+ void clearGuards();
+};
+
+QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
+: _c(0), _w(0), _s(e)
+{
+ if (e->m_scopeObject.isT1()) {
+ _w = &_s;
+ _c = e->m_scopeObject.asT1();
+ e->m_scopeObject = this;
+ } else {
+ // Another watcher is already registered
+ _w = &e->m_scopeObject.asT2()->_s;
+ }
+}
+
+QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher()
+{
+ Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2()));
+ if (*_w && _s->m_scopeObject.asT2() == this)
+ _s->m_scopeObject = _c;
+}
+
+bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const
+{
+ return *_w == 0;
+}
+
+bool QQmlJavaScriptExpression::requiresThisObject() const
+{
+ return m_scopeObject.flag();
+}
+
+void QQmlJavaScriptExpression::setRequiresThisObject(bool v)
+{
+ m_scopeObject.setFlagValue(v);
+}
+
+bool QQmlJavaScriptExpression::useSharedContext() const
+{
+ return activeGuards.flag2();
+}
+
+void QQmlJavaScriptExpression::setUseSharedContext(bool v)
+{
+ activeGuards.setFlag2Value(v);
+}
+
+bool QQmlJavaScriptExpression::notifyOnValueChanged() const
+{
+ return activeGuards.flag();
+}
+
+QObject *QQmlJavaScriptExpression::scopeObject() const
+{
+ if (m_scopeObject.isT1()) return m_scopeObject.asT1();
+ else return m_scopeObject.asT2()->_c;
+}
+
+void QQmlJavaScriptExpression::setScopeObject(QObject *v)
+{
+ if (m_scopeObject.isT1()) m_scopeObject = v;
+ else m_scopeObject.asT2()->_c = v;
+}
+
+bool QQmlJavaScriptExpression::hasError() const
+{
+ return m_vtable.hasValue() && m_vtable.constValue()->error.isValid();
+}
+
+bool QQmlJavaScriptExpression::hasDelayedError() const
+{
+ return m_vtable.hasValue();
+}
+
+QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
+: expression(e), next(0)
+{
+ callback = &endpointCallback;
+}
+
+void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e)
+{
+ QQmlJavaScriptExpression *expression =
+ static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
+
+ expression->m_vtable->expressionChanged(expression);
+}
+
+QQmlJavaScriptExpressionGuard *
+QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e,
+ QQmlEngine *engine)
+{
+ Q_ASSERT(e);
+ return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e);
+}
+
+void QQmlJavaScriptExpressionGuard::Delete()
+{
+ QRecyclePool<QQmlJavaScriptExpressionGuard>::Delete(this);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QQMLJAVASCRIPTEXPRESSION_P_H