1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 
42 #ifndef QSCRIPTENGINEFWD_P_H
43 #define QSCRIPTENGINEFWD_P_H
44 
45 #ifndef QT_NO_QOBJECT
46 #include "private/qobject_p.h"
47 #endif
48 
49 
50 #include <qobjectdefs.h>
51 
52 #include <QHash>
53 #include <QList>
54 #include <QRegExp>
55 #include <QSet>
56 #include <QStringList>
57 #include <QTime>
58 #include <QVector>
59 
60 #include "qscriptengine.h"
61 #include "qscriptrepository_p.h"
62 #include "qscriptgc_p.h"
63 #include "qscriptobjectfwd_p.h"
64 #include "qscriptclassinfo_p.h"
65 #include "qscriptstring_p.h"
66 
67 QT_BEGIN_NAMESPACE
68 
69 //
70 //  W A R N I N G
71 //  -------------
72 //
73 // This file is not part of the Qt API.  It exists purely as an
74 // implementation detail.  This header file may change from version to
75 // version without notice, or even be removed.
76 //
77 // We mean it.
78 //
79 
80 class QScriptClass;
81 class QScriptContext;
82 
83 namespace QScript {
84 
85 namespace AST {
86     class Node;
87 } // namespace AST
88 
89 namespace Ecma {
90     class Object;
91     class Number;
92     class Boolean;
93     class String;
94     class Math;
95     class Date;
96     class Function;
97     class Array;
98     class RegExp;
99     class Error;
100 } // namespace Ecma
101 
102 namespace Ext {
103     class Enumeration;
104     class Variant;
105 } // namespace Ext
106 
107 class ExtQObject;
108 class ExtQMetaObject;
109 
110 class Array;
111 class Lexer;
112 class Code;
113 class CompilationUnit;
114 class IdTable;
115 class MemoryPool;
116 
117 class IdTable
118 {
119 public:
IdTable()120     inline IdTable()
121         : id_constructor(0), id_false(0), id_null(0),
122           id_object(0), id_pointer(0), id_prototype(0),
123           id_arguments(0), id_this(0), id_toString(0),
124           id_true(0), id_undefined(0), id_valueOf(0),
125           id_length(0), id_callee(0), id___proto__(0),
126           id___qt_sender__(0)
127     {}
128 
129     QScriptNameIdImpl *id_constructor;
130     QScriptNameIdImpl *id_false;
131     QScriptNameIdImpl *id_null;
132     QScriptNameIdImpl *id_object;
133     QScriptNameIdImpl *id_pointer;
134     QScriptNameIdImpl *id_prototype;
135     QScriptNameIdImpl *id_arguments;
136     QScriptNameIdImpl *id_this;
137     QScriptNameIdImpl *id_toString;
138     QScriptNameIdImpl *id_true;
139     QScriptNameIdImpl *id_undefined;
140     QScriptNameIdImpl *id_valueOf;
141     QScriptNameIdImpl *id_length;
142     QScriptNameIdImpl *id_callee;
143     QScriptNameIdImpl *id___proto__;
144     QScriptNameIdImpl *id___qt_sender__;
145 };
146 
147 } // namespace QScript
148 
149 #ifndef QT_NO_QOBJECT
150 class QScriptQObjectData;
151 class QScriptMetaObject;
152 #endif
153 
154 class QScriptCustomTypeInfo
155 {
156 public:
QScriptCustomTypeInfo()157     QScriptCustomTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0)
158     { prototype.invalidate(); }
159 
160     QByteArray signature;
161     QScriptEngine::MarshalFunction marshal;
162     QScriptEngine::DemarshalFunction demarshal;
163     QScriptValueImpl prototype;
164 };
165 
166 class QScriptEnginePrivate
167 #ifndef QT_NO_QOBJECT
168     : public QObjectPrivate
169 #endif
170 {
171     Q_DECLARE_PUBLIC(QScriptEngine)
172 
173     enum {
174         DefaultHashSize = 1021
175     };
176 
177 public:
178     QScriptEnginePrivate();
179     virtual ~QScriptEnginePrivate();
180 
181     void init();
182     void initStringRepository();
183 
184     static inline QScriptEnginePrivate *get(QScriptEngine *q);
185     static inline const QScriptEnginePrivate *get(const QScriptEngine *q);
186     static inline QScriptEngine *get(QScriptEnginePrivate *d);
187 
188     QScript::AST::Node *createAbstractSyntaxTree(
189         const QString &source, int lineNumber,
190         QString *errorMessage, int *errorLineNumber);
191     QScript::AST::Node *changeAbstractSyntaxTree(QScript::AST::Node *program);
192 
193     inline QScript::AST::Node *abstractSyntaxTree() const;
194     inline bool hasUncaughtException() const;
195     inline QScriptValueImpl uncaughtException() const;
196     QStringList uncaughtExceptionBacktrace() const;
197     void clearExceptions();
198 #ifndef QT_NO_QOBJECT
199     void emitSignalHandlerException();
200 #endif
201 
202     static bool canEvaluate(const QString &program);
203     static QScriptSyntaxCheckResult checkSyntax(const QString &program);
204 
205     inline QScriptContextPrivate *currentContext() const;
206     inline QScriptContextPrivate *pushContext();
207     inline void popContext();
208 
209     inline QScript::MemoryPool *nodePool();
210     inline QScript::Lexer *lexer();
211     inline QScriptObject *allocObject();
212 
213     inline void maybeGC();
214 
215     void maybeGC_helper(bool do_string_gc);
216 
217     inline bool blockGC(bool block);
218 
219     void gc();
220     bool isCollecting() const;
221     void processMarkStack(int generation);
222 
223     inline void adjustBytesAllocated(int bytes);
224 
225     void markObject(const QScriptValueImpl &object, int generation);
226     void markFrame(QScriptContextPrivate *context, int generation);
227 
228     inline void markString(QScriptNameIdImpl *id, int generation);
229 
230     inline QScriptValueImpl createFunction(QScriptFunction *fun);
231     inline QScriptValueImpl newArray(const QScript::Array &value);
232     inline QScriptValueImpl newArray(uint length = 0);
233 
234     void evaluate(QScriptContextPrivate *context, const QString &contents,
235                   int lineNumber, const QString &fileName = QString());
236 
237     inline void setLexer(QScript::Lexer *lexer);
238 
239     inline void setNodePool(QScript::MemoryPool *pool);
240 
241     inline QScriptClassInfo *registerClass(const QString &pname, int type);
242 
243     inline QScriptClassInfo *registerClass(const QString &name);
244 
245     int registerCustomClassType();
246 
247     inline QScriptValueImpl createFunction(QScriptInternalFunctionSignature fun,
248                                            int length, QScriptClassInfo *classInfo,
249                                            const QString &name = QString());
250 
251     static inline QString toString(QScriptNameIdImpl *id);
252     inline QString memberName(const QScript::Member &member) const;
253     inline void newReference(QScriptValueImpl *object, int mode);
254     inline void newActivation(QScriptValueImpl *object);
255     inline void newFunction(QScriptValueImpl *object, QScriptFunction *function);
256     inline void newConstructor(QScriptValueImpl *ctor, QScriptFunction *function,
257                         QScriptValueImpl &proto);
258     inline void newInteger(QScriptValueImpl *object, int i);
259     inline void newPointer(QScriptValueImpl *object, void *ptr);
260     inline void newNameId(QScriptValueImpl *object, const QString &s);
261     inline void newNameId(QScriptValueImpl *object, QScriptNameIdImpl *id);
262     inline void newString(QScriptValueImpl *object, const QString &s);
263     inline void newArguments(QScriptValueImpl *object, const QScriptValueImpl &activation,
264                       uint length, const QScriptValueImpl &callee);
265     static inline QString convertToNativeString(const QScriptValueImpl &value);
266     static QString convertToNativeString_helper(const QScriptValueImpl &value);
267     static inline qsreal convertToNativeDouble(const QScriptValueImpl &value);
268     static qsreal convertToNativeDouble_helper(const QScriptValueImpl &value);
269     static inline bool convertToNativeBoolean(const QScriptValueImpl &value);
270     static bool convertToNativeBoolean_helper(const QScriptValueImpl &value);
271     static inline qint32 convertToNativeInt32(const QScriptValueImpl &value);
272     static inline QScriptFunction *convertToNativeFunction(const QScriptValueImpl &value);
273 
274     inline QScriptValue toPublic(const QScriptValueImpl &value);
275     inline QScriptValueImpl toImpl(const QScriptValue &value);
276     QScriptValueImpl toImpl_helper(const QScriptValue &value);
277     inline QScriptValueImplList toImplList(const QScriptValueList &lst);
278 
279     inline const QScript::IdTable *idTable() const;
280 
281     inline QScriptValueImpl toObject(const QScriptValueImpl &value);
282     QScriptValueImpl toObject_helper(const QScriptValueImpl &value);
283 
284     inline QScriptValueImpl toPrimitive(const QScriptValueImpl &object,
285                                         QScriptValueImpl::TypeHint hint = QScriptValueImpl::NoTypeHint);
286     QScriptValueImpl toPrimitive_helper(const QScriptValueImpl &object,
287                                         QScriptValueImpl::TypeHint hint);
288 
289     static const qsreal D16;
290     static const qsreal D32;
291 
292     inline static qsreal toInteger(qsreal n);
293     inline static qint32 toInt32(qsreal m);
294     inline static quint32 toUint32(qsreal n);
295     inline static quint16 toUint16(qsreal n);
296 
297     inline QDateTime toDateTime(const QScriptValueImpl &value) const;
298 
299     inline void newArray(QScriptValueImpl *object, const QScript::Array &value);
300 
301     inline void newObject(QScriptValueImpl *o, const QScriptValueImpl &proto,
302                           QScriptClassInfo *oc = 0);
303     inline void newObject(QScriptValueImpl *o, QScriptClassInfo *oc = 0);
304     QScriptValueImpl newObject(QScriptClass *scriptClass, const QScriptValueImpl &data);
305 
306     inline QScriptValueImpl newObject();
307 
308     inline void newVariant(QScriptValueImpl *out, const QVariant &value,
309                            bool setDefaultPrototype = true);
310 
311 #ifndef QT_NO_QOBJECT
312     void newQObject(QScriptValueImpl *out, QObject *object,
313                     QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership,
314                     const QScriptEngine::QObjectWrapOptions &options = 0,
315                     bool setDefaultPrototype = true);
316 
317 # ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE
318     inline QScriptMetaObject *cachedMetaObject(const QMetaObject *meta);
319 # endif
320 #endif
321 
322     inline QScriptNameIdImpl *nameId(const QString &str, bool persistent = false);
323 
324     inline QScriptNameIdImpl *intern(const QChar *u, int s);
325 
326     QScriptString internedString(const QString &str);
327     QScriptString internedString(QScriptNameIdImpl *nid);
328     void uninternString(QScriptStringPrivate *d);
329 
330     inline QScriptValueImpl valueFromVariant(const QVariant &v);
331 
332     inline QScriptValueImpl undefinedValue();
333 
334     inline QScriptValueImpl nullValue();
335 
336     inline QScriptValueImpl defaultPrototype(int metaTypeId) const;
337 
338     inline void setDefaultPrototype(int metaTypeId, const QScriptValueImpl &prototype);
339 
340     QScriptValueImpl call(const QScriptValueImpl &callee, const QScriptValueImpl &thisObject,
341                           const QScriptValueImplList &args, bool asConstructor);
342     QScriptValueImpl call(const QScriptValueImpl &callee, const QScriptValueImpl &thisObject,
343                           const QScriptValueImpl &args, bool asConstructor);
344 
345     void rehashStringRepository(bool resize = true);
346     inline QScriptNameIdImpl *toStringEntry(const QString &s);
347     QScriptNameIdImpl *insertStringEntry(const QString &s);
348 
349     QScriptValueImpl create(int type, const void *ptr);
350     static bool convert(const QScriptValueImpl &value, int type, void *ptr,
351                         QScriptEnginePrivate *eng);
352     QScriptEngine::DemarshalFunction demarshalFunction(int type) const;
353 
354     QScriptValueImpl arrayFromStringList(const QStringList &lst);
355     static QStringList stringListFromArray(const QScriptValueImpl &arr);
356 
357     QScriptValueImpl arrayFromVariantList(const QVariantList &lst);
358     static QVariantList variantListFromArray(const QScriptValueImpl &arr);
359 
360     QScriptValueImpl objectFromVariantMap(const QVariantMap &vmap);
361     static QVariantMap variantMapFromObject(const QScriptValueImpl &obj);
362 
363     static inline bool lessThan(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs);
364     static inline bool equals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs);
365     static inline bool strictlyEquals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs);
366 
367     QScriptValuePrivate *registerValue(const QScriptValueImpl &value);
368     inline void unregisterValue(QScriptValuePrivate *p);
369 
370     inline QScriptValueImpl globalObject() const;
371 
372     QScriptValueImpl objectById(qint64 id) const;
373 
374     QScriptValueImpl importExtension(const QString &extension);
375     QStringList availableExtensions() const;
376     QStringList importedExtensions() const;
377 
378     inline void maybeProcessEvents();
379     void setupProcessEvents();
380     void processEvents();
381 
382 #ifndef QT_NO_QOBJECT
383     QScriptQObjectData *qobjectData(QObject *object);
384 
385     bool scriptConnect(QObject *sender, const char *signal,
386                        const QScriptValueImpl &receiver,
387                        const QScriptValueImpl &function,
388                        Qt::ConnectionType type);
389     bool scriptDisconnect(QObject *sender, const char *signal,
390                           const QScriptValueImpl &receiver,
391                           const QScriptValueImpl &function);
392 
393     bool scriptConnect(QObject *sender, int index,
394                        const QScriptValueImpl &receiver,
395                        const QScriptValueImpl &function,
396                        const QScriptValueImpl &senderWrapper,
397                        Qt::ConnectionType type);
398     bool scriptDisconnect(QObject *sender, int index,
399                           const QScriptValueImpl &receiver,
400                           const QScriptValueImpl &function);
401 
402     bool scriptConnect(const QScriptValueImpl &signal,
403                        const QScriptValueImpl &receiver,
404                        const QScriptValueImpl &function,
405                        Qt::ConnectionType type);
406     bool scriptDisconnect(const QScriptValueImpl &signal,
407                           const QScriptValueImpl &receiver,
408                           const QScriptValueImpl &function);
409 
410     void _q_objectDestroyed(QObject *object);
411 
412     void disposeQObject(QObject *object);
413     void deletePendingQObjects();
414 
415     static bool convertToNativeQObject(const QScriptValueImpl &value,
416                                        const QByteArray &targetType,
417                                        void **result);
418 #endif
419 
420     void abortEvaluation(const QScriptValueImpl &result);
421     inline bool shouldAbort() const;
422     inline void resetAbortFlag();
423 
424     void setAgent(QScriptEngineAgent *agent);
425     QScriptEngineAgent *agent() const;
426 
427     void agentDeleted(QScriptEngineAgent *agent);
428 
429     void installTranslatorFunctions(QScriptValueImpl &object);
430 
431 #ifndef Q_SCRIPT_NO_EVENT_NOTIFY
432     qint64 nextScriptId();
433     inline bool shouldNotify() const;
434     inline void notifyScriptLoad(qint64 id, const QString &program,
435                                  const QString &fileName, int lineNumber);
436     void notifyScriptLoad_helper(qint64 id, const QString &program,
437                                  const QString &fileName, int lineNumber);
438     inline void notifyScriptUnload(qint64 id);
439     void notifyScriptUnload_helper(qint64 id);
440     inline void notifyPositionChange(QScriptContextPrivate *ctx);
441     void notifyPositionChange_helper(QScriptContextPrivate *ctx);
442     inline void notifyContextPush();
443     void notifyContextPush_helper();
444     inline void notifyContextPop();
445     void notifyContextPop_helper();
446     inline void notifyFunctionEntry(QScriptContextPrivate *ctx);
447     void notifyFunctionEntry_helper(QScriptContextPrivate *ctx);
448     inline void notifyFunctionExit(QScriptContextPrivate *ctx);
449     void notifyFunctionExit_helper(QScriptContextPrivate *ctx);
450     inline void notifyException(QScriptContextPrivate *ctx);
451     void notifyException_helper(QScriptContextPrivate *ctx);
452     inline void notifyExceptionCatch(QScriptContextPrivate *ctx);
453     void notifyExceptionCatch_helper(QScriptContextPrivate *ctx);
454     void notifyDebugger(QScriptContextPrivate *ctx);
455 #endif // Q_SCRIPT_NO_EVENT_NOTIFY
456 
457 public: // attributes
458     bool m_evaluating;
459     bool m_abort;
460     int m_callDepth;
461     int m_maxCallDepth;
462     int m_gc_depth;
463     QList<QScriptValueImpl> m_markStack;
464     QScriptValueImpl m_globalObject;
465     int m_oldStringRepositorySize;
466     int m_oldTempStringRepositorySize;
467     QVector<QScriptNameIdImpl*> m_stringRepository;
468     int m_newAllocatedStringRepositoryChars;
469     QVector<QScriptNameIdImpl*> m_tempStringRepository;
470     int m_newAllocatedTempStringRepositoryChars;
471     QScriptNameIdImpl **m_string_hash_base;
472     int m_string_hash_size;
473     QScript::GCAlloc<QScriptObject> objectAllocator;
474     int m_objectGeneration;
475     QScript::Repository<QScriptContext, QScriptContextPrivate> m_frameRepository;
476     QScriptContextPrivate *m_context;
477     QScriptValueImpl *tempStackBegin;
478     QScriptValueImpl *tempStackEnd;
479     QScript::AST::Node *m_abstractSyntaxTree;
480     QScript::Lexer *m_lexer;
481     QScript::MemoryPool *m_pool;
482     QStringList m_exceptionBacktrace;
483     qint64 m_scriptCounter;
484 
485     QScriptValueImpl m_undefinedValue;
486     QScriptValueImpl m_nullValue;
487 
488     QScript::Ecma::Object *objectConstructor;
489     QScript::Ecma::Number *numberConstructor;
490     QScript::Ecma::Boolean *booleanConstructor;
491     QScript::Ecma::String *stringConstructor;
492     QScript::Ecma::Date *dateConstructor;
493     QScript::Ecma::Function *functionConstructor;
494     QScript::Ecma::Array *arrayConstructor;
495     QScript::Ecma::RegExp *regexpConstructor;
496     QScript::Ecma::Error *errorConstructor;
497     QScript::Ext::Enumeration *enumerationConstructor;
498     QScript::Ext::Variant *variantConstructor;
499     QScript::ExtQObject *qobjectConstructor;
500     QScript::ExtQMetaObject *qmetaObjectConstructor;
501 
502     QHash<int, QScriptCustomTypeInfo> m_customTypes;
503 
504     QScriptFunction *m_evalFunction;
505 
506     QList<QScriptClassInfo*> m_allocated_classes;
507     QScriptClassInfo *m_class_object;
508     QScriptClassInfo *m_class_function;
509     QScriptClassInfo *m_class_with;
510     QScriptClassInfo *m_class_arguments;
511     QScriptClassInfo *m_class_activation;
512 
513     int m_class_prev_id;
514     qint64 m_next_object_id;
515 
516     QScript::Repository<QScriptValuePrivate, QScriptValuePrivate> m_handleRepository;
517     QHash<QScriptObject*, QScriptValuePrivate*> m_objectHandles;
518     QHash<QScriptNameIdImpl*, QScriptValuePrivate*> m_stringHandles;
519     QVector<QScriptValuePrivate*> m_otherHandles;
520 
521     QScript::Repository<QScriptStringPrivate,
522                         QScriptStringPrivate> m_internedStringRepository;
523     QHash<QScriptNameIdImpl*, QScriptStringPrivate*> m_internedStrings;
524 
525     QSet<QScriptObject*> visitedArrayElements;
526 
527 #ifndef QT_NO_REGEXP
528     QHash<QString, QRegExp> m_regExpLiterals;
529 #endif
530 
531     QScript::IdTable m_id_table;
532 
533     QSet<QString> m_importedExtensions;
534     QSet<QString> m_extensionsBeingImported;
535 
536     int m_processEventsInterval;
537     int m_nextProcessEvents;
538     int m_processEventIncr;
539     QTime m_processEventTracker;
540 
541     QList<QScriptEngineAgent*> m_agents;
542     QScriptEngineAgent *m_agent;
543 
544 #ifndef QT_NO_QOBJECT
545     QList<QObject*> m_qobjectsToBeDeleted;
546     QHash<QObject*, QScriptQObjectData*> m_qobjectData;
547 
548 # ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE
549     QHash<const QMetaObject*, QScriptMetaObject*> m_cachedMetaObjects;
550 # endif
551 #endif
552 
553 #ifdef QT_NO_QOBJECT
554     QScriptEngine *q_ptr;
555 #endif
556 };
557 
558 QT_END_NAMESPACE
559 
560 
561 #endif
562