1
/****************************************************************************
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/
6
** This file is part of the QtQml module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** GNU Lesser General Public License Usage
10
** This file may be used under the terms of the GNU Lesser General Public
11
** License version 2.1 as published by the Free Software Foundation and
12
** appearing in the file LICENSE.LGPL included in the packaging of this
13
** file. Please review the following information to ensure the GNU Lesser
14
** General Public License version 2.1 requirements will be met:
15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
** In addition, as a special exception, Nokia gives you certain additional
18
** rights. These rights are described in the Nokia Qt LGPL Exception
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
** GNU General Public License Usage
22
** Alternatively, this file may be used under the terms of the GNU General
23
** Public License version 3.0 as published by the Free Software Foundation
24
** and appearing in the file LICENSE.GPL included in the packaging of this
25
** file. Please review the following information to ensure the GNU General
26
** Public License version 3.0 requirements will be met:
27
** http://www.gnu.org/copyleft/gpl.html.
30
** Alternatively, this file may be used in accordance with the terms and
31
** conditions contained in a signed written agreement between you and Nokia.
40
****************************************************************************/
42
#ifndef QQMLJAVASCRIPTEXPRESSION_P_H
43
#define QQMLJAVASCRIPTEXPRESSION_P_H
49
// This file is not part of the Qt API. It exists purely as an
50
// implementation detail. This header file may change from version to
51
// version without notice, or even be removed.
56
#include <private/qv8_p.h>
57
#include <QtCore/qglobal.h>
58
#include <QtQml/qqmlerror.h>
59
#include <private/qqmlengine_p.h>
60
#include <private/qpointervaluepair_p.h>
64
class QQmlDelayedError
67
inline QQmlDelayedError() : nextError(0), prevError(0) {}
68
inline ~QQmlDelayedError() { removeError(); }
72
bool addError(QQmlEnginePrivate *);
74
inline void removeError() {
75
if (!prevError) return;
76
if (nextError) nextError->prevError = prevError;
77
*prevError = nextError;
83
QQmlDelayedError *nextError;
84
QQmlDelayedError **prevError;
87
class QQmlJavaScriptExpression
90
// Although this looks crazy, we implement our own "vtable" here, rather than relying on
91
// C++ virtuals, to save memory. By doing it ourselves, we can overload the storage
92
// location that is use for the vtable to also store the rarely used delayed error.
93
// If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
94
// memory for every expression.
96
QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
97
void (*expressionChanged)(QQmlJavaScriptExpression *);
100
QQmlJavaScriptExpression(VTable *vtable);
102
v8::Local<v8::Value> evaluate(QQmlContextData *, v8::Handle<v8::Function>,
105
inline bool requiresThisObject() const;
106
inline void setRequiresThisObject(bool v);
107
inline bool useSharedContext() const;
108
inline void setUseSharedContext(bool v);
109
inline bool notifyOnValueChanged() const;
111
void setNotifyOnValueChanged(bool v);
112
void resetNotifyOnValueChanged();
114
inline QObject *scopeObject() const;
115
inline void setScopeObject(QObject *v);
117
class DeleteWatcher {
119
inline DeleteWatcher(QQmlJavaScriptExpression *);
120
inline ~DeleteWatcher();
121
inline bool wasDeleted() const;
123
friend class QQmlJavaScriptExpression;
125
QQmlJavaScriptExpression **_w;
126
QQmlJavaScriptExpression *_s;
129
inline bool hasError() const;
130
inline bool hasDelayedError() const;
131
QQmlError error() const;
133
QQmlDelayedError *delayedError();
135
static void exceptionToError(v8::Handle<v8::Message>, QQmlError &);
136
static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
137
const QString &code, const QString &filename,
139
v8::Persistent<v8::Object> *qmlscope = 0);
140
static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
141
const char *code, int codeLength,
142
const QString &filename, int line,
143
v8::Persistent<v8::Object> *qmlscope = 0);
145
~QQmlJavaScriptExpression();
148
typedef QQmlJavaScriptExpressionGuard Guard;
149
friend class QQmlJavaScriptExpressionGuard;
151
struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
152
GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e)
153
: engine(engine), expression(e), errorString(0) { }
156
Q_ASSERT(guards.isEmpty());
157
Q_ASSERT(errorString == 0);
160
virtual void captureProperty(QQmlNotifier *);
161
virtual void captureProperty(QObject *, int, int);
164
QQmlJavaScriptExpression *expression;
165
QFieldList<Guard, &Guard::next> guards;
166
QStringList *errorString;
169
QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
171
// We store some flag bits in the following flag pointers.
172
// m_scopeObject:flag1 - requiresThisObject
173
// activeGuards:flag1 - notifyOnValueChanged
174
// activeGuards:flag2 - useSharedContext
175
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
176
QForwardFieldList<Guard, &Guard::next> activeGuards;
181
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
182
: _c(0), _w(0), _s(e)
184
if (e->m_scopeObject.isT1()) {
186
_c = e->m_scopeObject.asT1();
187
e->m_scopeObject = this;
189
// Another watcher is already registered
190
_w = &e->m_scopeObject.asT2()->_s;
194
QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher()
196
Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2()));
197
if (*_w && _s->m_scopeObject.asT2() == this)
198
_s->m_scopeObject = _c;
201
bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const
206
bool QQmlJavaScriptExpression::requiresThisObject() const
208
return m_scopeObject.flag();
211
void QQmlJavaScriptExpression::setRequiresThisObject(bool v)
213
m_scopeObject.setFlagValue(v);
216
bool QQmlJavaScriptExpression::useSharedContext() const
218
return activeGuards.flag2();
221
void QQmlJavaScriptExpression::setUseSharedContext(bool v)
223
activeGuards.setFlag2Value(v);
226
bool QQmlJavaScriptExpression::notifyOnValueChanged() const
228
return activeGuards.flag();
231
QObject *QQmlJavaScriptExpression::scopeObject() const
233
if (m_scopeObject.isT1()) return m_scopeObject.asT1();
234
else return m_scopeObject.asT2()->_c;
237
void QQmlJavaScriptExpression::setScopeObject(QObject *v)
239
if (m_scopeObject.isT1()) m_scopeObject = v;
240
else m_scopeObject.asT2()->_c = v;
243
bool QQmlJavaScriptExpression::hasError() const
245
return m_vtable.hasValue() && m_vtable.constValue()->error.isValid();
248
bool QQmlJavaScriptExpression::hasDelayedError() const
250
return m_vtable.hasValue();
253
QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
254
: expression(e), next(0)
256
callback = &endpointCallback;
259
void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e)
261
QQmlJavaScriptExpression *expression =
262
static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
264
expression->m_vtable->expressionChanged(expression);
267
QQmlJavaScriptExpressionGuard *
268
QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e,
272
return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e);
275
void QQmlJavaScriptExpressionGuard::Delete()
277
QRecyclePool<QQmlJavaScriptExpressionGuard>::Delete(this);
283
#endif // QQMLJAVASCRIPTEXPRESSION_P_H