Implement strict mode for qmldir modules
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmljavascriptexpression_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QQMLJAVASCRIPTEXPRESSION_P_H
43 #define QQMLJAVASCRIPTEXPRESSION_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
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.
52 //
53 // We mean it.
54 //
55
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>
61
62 QT_BEGIN_NAMESPACE
63
64 class QQmlDelayedError
65 {
66 public:
67     inline QQmlDelayedError() : nextError(0), prevError(0) {}
68     inline ~QQmlDelayedError() { qPersistentDispose(m_message); removeError(); }
69
70     bool addError(QQmlEnginePrivate *);
71
72     inline void removeError() {
73         if (!prevError) return;
74         if (nextError) nextError->prevError = prevError;
75         *prevError = nextError;
76         nextError = 0;
77         prevError = 0;
78     }
79
80     inline bool isValid() const { return !m_message.IsEmpty() || m_error.isValid(); }
81     inline const QQmlError &error(QQmlEngine *engine) const { convertMessageToError(engine); return m_error; }
82     inline void clearError() { qPersistentDispose(m_message); m_error = QQmlError(); }
83
84     void setMessage(v8::Handle<v8::Message> message);
85     void setErrorLocation(const QUrl &url, int line, int column);
86     void setErrorDescription(const QString &description);
87
88 private:
89     void convertMessageToError(QQmlEngine *engine) const;
90
91     mutable QQmlError m_error;
92     mutable v8::Persistent<v8::Message> m_message;
93
94     QQmlDelayedError  *nextError;
95     QQmlDelayedError **prevError;
96 };
97
98 class QQmlJavaScriptExpression
99 {
100 public:
101     // Although this looks crazy, we implement our own "vtable" here, rather than relying on
102     // C++ virtuals, to save memory.  By doing it ourselves, we can overload the storage
103     // location that is use for the vtable to also store the rarely used delayed error.
104     // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
105     // memory for every expression.
106     struct VTable {
107         QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
108         void (*expressionChanged)(QQmlJavaScriptExpression *);
109     };
110
111     QQmlJavaScriptExpression(VTable *vtable);
112
113     v8::Local<v8::Value> evaluate(QQmlContextData *, v8::Handle<v8::Function>,
114                                   bool *isUndefined);
115
116     inline bool requiresThisObject() const;
117     inline void setRequiresThisObject(bool v);
118     inline bool useSharedContext() const;
119     inline void setUseSharedContext(bool v);
120     inline bool notifyOnValueChanged() const;
121
122     void setNotifyOnValueChanged(bool v);
123     void resetNotifyOnValueChanged();
124
125     inline QObject *scopeObject() const;
126     inline void setScopeObject(QObject *v);
127
128     class DeleteWatcher {
129     public:
130         inline DeleteWatcher(QQmlJavaScriptExpression *);
131         inline ~DeleteWatcher();
132         inline bool wasDeleted() const;
133     private:
134         friend class QQmlJavaScriptExpression;
135         QObject *_c;
136         QQmlJavaScriptExpression **_w;
137         QQmlJavaScriptExpression *_s;
138     };
139
140     inline bool hasError() const;
141     inline bool hasDelayedError() const;
142     QQmlError error(QQmlEngine *) const;
143     void clearError();
144     QQmlDelayedError *delayedError();
145
146     static void exceptionToError(v8::Handle<v8::Message>, QQmlError &);
147     static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
148                                                      const QString &code, const QString &filename,
149                                                      int line,
150                                                      v8::Persistent<v8::Object> *qmlscope = 0);
151     static v8::Persistent<v8::Function> evalFunction(QQmlContextData *ctxt, QObject *scope,
152                                                      const char *code, int codeLength,
153                                                      const QString &filename, int line,
154                                                      v8::Persistent<v8::Object> *qmlscope = 0);
155 protected:
156     ~QQmlJavaScriptExpression();
157
158 private:
159     typedef QQmlJavaScriptExpressionGuard Guard;
160     friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
161
162     struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
163         GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e)
164         : engine(engine), expression(e), errorString(0) { }
165
166         ~GuardCapture()  {
167             Q_ASSERT(guards.isEmpty());
168             Q_ASSERT(errorString == 0);
169         }
170
171         virtual void captureProperty(QQmlNotifier *);
172         virtual void captureProperty(QObject *, int, int);
173
174         QQmlEngine *engine;
175         QQmlJavaScriptExpression *expression;
176         QFieldList<Guard, &Guard::next> guards;
177         QStringList *errorString;
178     };
179
180     QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
181
182     // We store some flag bits in the following flag pointers.
183     //    m_scopeObject:flag1 - requiresThisObject
184     //    activeGuards:flag1  - notifyOnValueChanged
185     //    activeGuards:flag2  - useSharedContext
186     QBiPointer<QObject, DeleteWatcher> m_scopeObject;
187     QForwardFieldList<Guard, &Guard::next> activeGuards;
188
189     void clearGuards();
190 };
191
192 QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
193 : _c(0), _w(0), _s(e)
194 {
195     if (e->m_scopeObject.isT1()) {
196         _w = &_s;
197         _c = e->m_scopeObject.asT1();
198         e->m_scopeObject = this;
199     } else {
200         // Another watcher is already registered
201         _w = &e->m_scopeObject.asT2()->_s;
202     }
203 }
204
205 QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher()
206 {
207     Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2()));
208     if (*_w && _s->m_scopeObject.asT2() == this)
209         _s->m_scopeObject = _c;
210 }
211
212 bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const
213 {
214     return *_w == 0;
215 }
216
217 bool QQmlJavaScriptExpression::requiresThisObject() const
218 {
219     return m_scopeObject.flag();
220 }
221
222 void QQmlJavaScriptExpression::setRequiresThisObject(bool v)
223 {
224     m_scopeObject.setFlagValue(v);
225 }
226
227 bool QQmlJavaScriptExpression::useSharedContext() const
228 {
229     return activeGuards.flag2();
230 }
231
232 void QQmlJavaScriptExpression::setUseSharedContext(bool v)
233 {
234     activeGuards.setFlag2Value(v);
235 }
236
237 bool QQmlJavaScriptExpression::notifyOnValueChanged() const
238 {
239     return activeGuards.flag();
240 }
241
242 QObject *QQmlJavaScriptExpression::scopeObject() const
243 {
244     if (m_scopeObject.isT1()) return m_scopeObject.asT1();
245     else return m_scopeObject.asT2()->_c;
246 }
247
248 void QQmlJavaScriptExpression::setScopeObject(QObject *v)
249 {
250     if (m_scopeObject.isT1()) m_scopeObject = v;
251     else m_scopeObject.asT2()->_c = v;
252 }
253
254 bool QQmlJavaScriptExpression::hasError() const
255 {
256     return m_vtable.hasValue() && m_vtable.constValue()->isValid();
257 }
258
259 bool QQmlJavaScriptExpression::hasDelayedError() const
260 {
261     return m_vtable.hasValue();
262 }
263
264 QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
265 : expression(e), next(0)
266 {
267     setCallback(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard);
268 }
269
270 QQmlJavaScriptExpressionGuard *
271 QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e,
272                                            QQmlEngine *engine)
273 {
274     Q_ASSERT(e);
275     return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e);
276 }
277
278 void QQmlJavaScriptExpressionGuard::Delete()
279 {
280     QRecyclePool<QQmlJavaScriptExpressionGuard>::Delete(this);
281 }
282
283
284 QT_END_NAMESPACE
285
286 #endif // QQMLJAVASCRIPTEXPRESSION_P_H