source: trunk/src/script/api/qscriptengine_p.h@ 618

Last change on this file since 618 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 19.0 KB
RevLine 
[556]1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
20** $QT_END_LICENSE$
21**
22****************************************************************************/
23
24#ifndef QSCRIPTENGINE_P_H
25#define QSCRIPTENGINE_P_H
26
27//
28// W A R N I N G
29// -------------
30//
31// This file is not part of the Qt API. It exists purely as an
32// implementation detail. This header file may change from version to
33// version without notice, or even be removed.
34//
35// We mean it.
36//
37
38#include "private/qobject_p.h"
39
40#include <QtCore/qhash.h>
41#include <QtCore/qset.h>
42#include "qscriptvalue_p.h"
43#include "qscriptstring_p.h"
44
45#include "Debugger.h"
46#include "Lexer.h"
47#include "RefPtr.h"
48#include "SourceProvider.h"
49#include "Structure.h"
50#include "JSGlobalObject.h"
51#include "JSValue.h"
52
53namespace JSC
54{
55 class EvalExecutable;
56 class ExecState;
57 typedef ExecState CallFrame;
58 class JSCell;
59 class JSGlobalObject;
60 class UString;
61}
62
63
64QT_BEGIN_NAMESPACE
65
66class QString;
67class QStringList;
68class QScriptContext;
69class QScriptValue;
70class QScriptTypeInfo;
71class QScriptEngineAgent;
72class QScriptEnginePrivate;
73class QScriptSyntaxCheckResult;
74class QScriptEngine;
75
76namespace QScript
77{
78 class QObjectPrototype;
79 class QMetaObjectPrototype;
80 class QVariantPrototype;
81#ifndef QT_NO_QOBJECT
82 class QObjectData;
83#endif
84 class TimeoutCheckerProxy;
85
86 //some conversion helper functions
87 inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec);
88 bool isFunction(JSC::JSValue value);
89
90 class UStringSourceProviderWithFeedback;
91
92struct GlobalClientData : public JSC::JSGlobalData::ClientData
93{
94 GlobalClientData(QScriptEnginePrivate *e)
95 : engine(e) {}
96 virtual ~GlobalClientData() {}
97 virtual void mark(JSC::MarkStack& markStack);
98
99 QScriptEnginePrivate *engine;
100};
101
102} // namespace QScript
103
104class QScriptEnginePrivate
105#ifndef QT_NO_QOBJECT
106 : public QObjectPrivate
107#endif
108{
109 Q_DECLARE_PUBLIC(QScriptEngine)
110public:
111 QScriptEnginePrivate();
112 virtual ~QScriptEnginePrivate();
113
114 static QScriptEnginePrivate *get(QScriptEngine *q) { return q ? q->d_func() : 0; }
115 static QScriptEngine *get(QScriptEnginePrivate *d) { return d ? d->q_func() : 0; }
116
117 static bool convert(const QScriptValue &value,
118 int type, void *ptr,
119 QScriptEnginePrivate *eng);
120 QScriptValue create(int type, const void *ptr);
121 bool hasDemarshalFunction(int type) const;
122
123 inline QScriptValue scriptValueFromJSCValue(JSC::JSValue value);
124 inline JSC::JSValue scriptValueToJSCValue(const QScriptValue &value);
125
126 QScriptValue scriptValueFromVariant(const QVariant &value);
127 QVariant scriptValueToVariant(const QScriptValue &value, int targetType);
128
129 JSC::JSValue jscValueFromVariant(const QVariant &value);
130 QVariant jscValueToVariant(JSC::JSValue value, int targetType);
131
132 QScriptValue arrayFromStringList(const QStringList &lst);
133 static QStringList stringListFromArray(const QScriptValue &arr);
134
135 QScriptValue arrayFromVariantList(const QVariantList &lst);
136 static QVariantList variantListFromArray(const QScriptValue &arr);
137
138 QScriptValue objectFromVariantMap(const QVariantMap &vmap);
139 static QVariantMap variantMapFromObject(const QScriptValue &obj);
140
141 JSC::JSValue defaultPrototype(int metaTypeId) const;
142 void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype);
143
144 static inline QScriptContext *contextForFrame(JSC::ExecState *frame);
145 static inline JSC::ExecState *frameForContext(QScriptContext *context);
146 static inline const JSC::ExecState *frameForContext(const QScriptContext *context);
147
148 JSC::JSGlobalObject *originalGlobalObject() const;
149 JSC::JSObject *getOriginalGlobalObjectProxy();
150 JSC::JSObject *customGlobalObject() const;
151 JSC::JSObject *globalObject() const;
152 void setGlobalObject(JSC::JSObject *object);
153 inline JSC::ExecState *globalExec() const;
154 JSC::JSValue toUsableValue(JSC::JSValue value);
155 static JSC::JSValue thisForContext(JSC::ExecState *frame);
156 static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame);
157
158 JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args,
159 JSC::JSObject *callee, bool calledAsConstructor = false, bool clearScopeChain = false);
160 void popContext();
161
162 void mark(JSC::MarkStack& markStack);
163 bool isCollecting() const;
164 void collectGarbage();
165
166 //flags that we set on the return value register for native function. (ie when codeBlock is 0)
167 enum ContextFlags {
168 NativeContext = 1,
169 CalledAsConstructorContext = 2,
170 HasScopeContext = 4, // Specifies that the is a QScriptActivationObject
171 ShouldRestoreCallFrame = 8
172 };
173 static uint contextFlags(JSC::ExecState *);
174 static void setContextFlags(JSC::ExecState *, uint);
175
176 QScript::TimeoutCheckerProxy *timeoutChecker() const;
177
178 void agentDeleted(QScriptEngineAgent *agent);
179
180 void setCurrentException(QScriptValue exception) { m_currentException = exception; }
181 QScriptValue currentException() const { return m_currentException; }
182 void clearCurrentException() { m_currentException.d_ptr.reset(); }
183
184#ifndef QT_NO_QOBJECT
185 JSC::JSValue newQObject(QObject *object,
186 QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership,
187 const QScriptEngine:: QObjectWrapOptions &options = 0);
188 JSC::JSValue newQMetaObject(const QMetaObject *metaObject,
189 JSC::JSValue ctor);
190
191 static QScriptSyntaxCheckResult checkSyntax(const QString &program);
192 static bool canEvaluate(const QString &program);
193 static bool convertToNativeQObject(const QScriptValue &value,
194 const QByteArray &targetType,
195 void **result);
196
197 JSC::JSValue evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
198 JSC::EvalExecutable *executable,
199 bool &compile);
200
201 QScript::QObjectData *qobjectData(QObject *object);
202 void disposeQObject(QObject *object);
203 void emitSignalHandlerException();
204
205 bool scriptConnect(QObject *sender, const char *signal,
206 JSC::JSValue receiver, JSC::JSValue function,
207 Qt::ConnectionType type);
208 bool scriptDisconnect(QObject *sender, const char *signal,
209 JSC::JSValue receiver, JSC::JSValue function);
210
211 bool scriptConnect(QObject *sender, int index,
212 JSC::JSValue receiver, JSC::JSValue function,
213 JSC::JSValue senderWrapper,
214 Qt::ConnectionType type);
215 bool scriptDisconnect(QObject *sender, int index,
216 JSC::JSValue receiver, JSC::JSValue function);
217
218 bool scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
219 JSC::JSValue function, Qt::ConnectionType type);
220 bool scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
221 JSC::JSValue function);
222
223 inline QScriptValuePrivate *allocateScriptValuePrivate(size_t);
224 inline void freeScriptValuePrivate(QScriptValuePrivate *p);
225
226 inline void registerScriptValue(QScriptValuePrivate *value);
227 inline void unregisterScriptValue(QScriptValuePrivate *value);
228 void detachAllRegisteredScriptValues();
229
230 inline void registerScriptString(QScriptStringPrivate *value);
231 inline void unregisterScriptString(QScriptStringPrivate *value);
232 void detachAllRegisteredScriptStrings();
233
234 // private slots
235 void _q_objectDestroyed(QObject *);
236#endif
237
238 JSC::JSGlobalData *globalData;
239 JSC::JSObject *originalGlobalObjectProxy;
240 JSC::ExecState *currentFrame;
241
242 WTF::RefPtr<JSC::Structure> scriptObjectStructure;
243
244 QScript::QObjectPrototype *qobjectPrototype;
245 WTF::RefPtr<JSC::Structure> qobjectWrapperObjectStructure;
246
247 QScript::QMetaObjectPrototype *qmetaobjectPrototype;
248 WTF::RefPtr<JSC::Structure> qmetaobjectWrapperObjectStructure;
249
250 QScript::QVariantPrototype *variantPrototype;
251 WTF::RefPtr<JSC::Structure> variantWrapperObjectStructure;
252
253 QList<QScriptEngineAgent*> ownedAgents;
254 QScriptEngineAgent *activeAgent;
255 int agentLineNumber;
256 QScriptValuePrivate *registeredScriptValues;
257 QScriptValuePrivate *freeScriptValues;
258 QScriptStringPrivate *registeredScriptStrings;
259 QHash<int, QScriptTypeInfo*> m_typeInfos;
260 int processEventsInterval;
261 QScriptValue abortResult;
262 bool inEval;
263
264 QSet<QString> importedExtensions;
265 QSet<QString> extensionsBeingImported;
266
267 QHash<intptr_t, QScript::UStringSourceProviderWithFeedback*> loadedScripts;
268 QScriptValue m_currentException;
269
270#ifndef QT_NO_QOBJECT
271 QHash<QObject*, QScript::QObjectData*> m_qobjectData;
272#endif
273
274#ifdef QT_NO_QOBJECT
275 QScriptEngine *q_ptr;
276#endif
277};
278
279namespace QScript
280{
281
282/*Helper class. Main purpose is to give debugger feedback about unloading and loading scripts.
283 It keeps pointer to JSGlobalObject assuming that it is always the same - there is no way to update
284 this data. Class is internal and used as an implementation detail in and only in QScriptEngine::evaluate.*/
285class UStringSourceProviderWithFeedback: public JSC::UStringSourceProvider
286{
287public:
288 static PassRefPtr<UStringSourceProviderWithFeedback> create(
289 const JSC::UString& source, const JSC::UString& url,
290 int lineNumber, QScriptEnginePrivate* engine)
291 {
292 return adoptRef(new UStringSourceProviderWithFeedback(source, url, lineNumber, engine));
293 }
294
295 /* Destruction means that there is no more copies of script so create scriptUnload event
296 and unregister script in QScriptEnginePrivate::loadedScripts */
297 virtual ~UStringSourceProviderWithFeedback()
298 {
299 if (m_ptr) {
300 if (JSC::Debugger* debugger = this->debugger())
301 debugger->scriptUnload(asID());
302 m_ptr->loadedScripts.remove(asID());
303 }
304 }
305
306 /* set internal QScriptEnginePrivate pointer to null and create unloadScript event, should be called
307 only if QScriptEnginePrivate is about to be destroyed.*/
308 void disconnectFromEngine()
309 {
310 if (JSC::Debugger* debugger = this->debugger())
311 debugger->scriptUnload(asID());
312 m_ptr = 0;
313 }
314
315 int columnNumberFromOffset(int offset) const
316 {
317 for (const UChar *c = m_source.data() + offset; c >= m_source.data(); --c) {
318 if (JSC::Lexer::isLineTerminator(*c))
319 return offset - static_cast<int>(c - data());
320 }
321 return offset + 1;
322 }
323
324protected:
325 UStringSourceProviderWithFeedback(const JSC::UString& source, const JSC::UString& url,
326 int lineNumber, QScriptEnginePrivate* engine)
327 : UStringSourceProvider(source, url),
328 m_ptr(engine)
329 {
330 if (JSC::Debugger* debugger = this->debugger())
331 debugger->scriptLoad(asID(), source, url, lineNumber);
332 if (m_ptr)
333 m_ptr->loadedScripts.insert(asID(), this);
334 }
335
336 JSC::Debugger* debugger()
337 {
338 //if m_ptr is null it mean that QScriptEnginePrivate was destroyed and scriptUnload was called
339 //else m_ptr is stable and we can use it as normal pointer without hesitation
340 if(!m_ptr)
341 return 0; //we are in ~QScriptEnginePrivate
342 else
343 return m_ptr->originalGlobalObject()->debugger(); //QScriptEnginePrivate is still alive
344 }
345
346 //trace global object and debugger instance
347 QScriptEnginePrivate* m_ptr;
348};
349
350class SaveFrameHelper
351{
352public:
353 SaveFrameHelper(QScriptEnginePrivate *eng,
354 JSC::ExecState *newFrame)
355 : engine(eng), oldFrame(eng->currentFrame)
356 {
357 eng->currentFrame = newFrame;
358 }
359 ~SaveFrameHelper()
360 {
361 engine->currentFrame = oldFrame;
362 }
363private:
364 QScriptEnginePrivate *engine;
365 JSC::ExecState *oldFrame;
366};
367
368inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec)
369{
370 return static_cast<GlobalClientData*>(exec->globalData().clientData)->engine;
371}
372
373} // namespace QScript
374
375inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size)
376{
377 if (freeScriptValues) {
378 QScriptValuePrivate *p = freeScriptValues;
379 freeScriptValues = p->next;
380 return p;
381 }
382 return reinterpret_cast<QScriptValuePrivate*>(qMalloc(size));
383}
384
385inline void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p)
386{
387 p->next = freeScriptValues;
388 freeScriptValues = p;