/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qmutex.h>
#include <QtCore/qstack.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QThreadStorage>
#include <private/qv8_p.h>
#include <qjsengine.h>
#include "qv8listwrapper_p.h"
#include "qv8variantwrapper_p.h"
#include "qv8valuetypewrapper_p.h"
+#include "qv8sequencewrapper_p.h"
QT_BEGIN_NAMESPACE
QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
- ListModelType, Context2DType, ParticleDataType };
+ ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType,
+ ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType,
+ SequenceType, LocaleDataType };
virtual ResourceType resourceType() const = 0;
QV8Engine *engine;
class QNetworkAccessManager;
class QDeclarativeContextData;
+class Q_AUTOTEST_EXPORT QV8GCCallback
+{
+private:
+ class ThreadData;
+public:
+ static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags);
+ static void registerGcPrologueCallback();
+
+ class Q_AUTOTEST_EXPORT Node {
+ public:
+ typedef void (*PrologueCallback)(Node *node);
+ Node(PrologueCallback callback);
+ ~Node();
+
+ QIntrusiveListNode node;
+ PrologueCallback prologueCallback;
+ };
+
+ static void addGcCallbackNode(Node *node);
+};
+
class Q_DECLARATIVE_EXPORT QV8Engine
{
public:
QV8Engine(QJSEngine* qq,QJSEngine::ContextOwnership ownership = QJSEngine::CreateNewContext);
~QV8Engine();
+ // ### TODO get rid of it, do we really need CppOwnership?
+ // This enum should be in sync with QDeclarativeEngine::ObjectOwnership
+ enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
+
struct Deletable {
virtual ~Deletable() {}
};
QV8ListWrapper *listWrapper() { return &m_listWrapper; }
QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
+ QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; }
void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
void *sqlDatabaseData() { return m_sqlDatabaseData; }
// Return a JS wrapper for the given QObject \a object
inline v8::Handle<v8::Value> newQObject(QObject *object);
+ inline v8::Handle<v8::Value> newQObject(QObject *object, const ObjectOwnership ownership);
inline bool isQObject(v8::Handle<v8::Value>);
inline QObject *toQObject(v8::Handle<v8::Value>);
inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
+ // Create a new sequence type object
+ inline v8::Handle<v8::Value> newSequence(int sequenceType, QObject *, int coreIndex, bool *succeeded);
+
// Create a new QVariant object. This doesn't examine the type of the variant, but always returns
// a QVariant wrapper
inline v8::Handle<v8::Value> newQVariant(const QVariant &);
virtual QNetworkAccessManager *networkAccessManager();
// Return the list of illegal id names (the names of the properties on the global object)
- const QSet<QString> &illegalNames() const;
+ const QStringHash<bool> &illegalNames() const;
inline void collectGarbage() { gc(); }
static void gc();
void setExtensionData(int, Deletable *);
inline v8::Handle<v8::Value> makeJSValue(bool value);
- inline v8::Handle<v8::Value> makeJSValue(int value);
- inline v8::Handle<v8::Value> makeJSValue(uint value);
- inline v8::Handle<v8::Value> makeJSValue(double value);
+ inline v8::Local<v8::Value> makeJSValue(int value);
+ inline v8::Local<v8::Value> makeJSValue(uint value);
+ inline v8::Local<v8::Value> makeJSValue(double value);
inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
- inline v8::Handle<v8::Value> makeJSValue(const QString& value);
+ inline v8::Local<v8::Value> makeJSValue(const QString &value);
inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
QScriptPassPointer<QJSValuePrivate> newArray(uint length);
- v8::Handle<v8::Object> newVariant(const QVariant &variant);
+ v8::Local<v8::Object> newVariant(const QVariant &variant);
QScriptPassPointer<QJSValuePrivate> newVariant(QJSValuePrivate* value, const QVariant &variant);
- v8::Handle<v8::Array> variantListToJS(const QVariantList &lst);
+ v8::Local<v8::Array> variantListToJS(const QVariantList &lst);
QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray);
- v8::Handle<v8::Object> variantMapToJS(const QVariantMap &vmap);
+ v8::Local<v8::Object> variantMapToJS(const QVariantMap &vmap);
QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject);
v8::Handle<v8::Value> variantToJS(const QVariant &value);
void emitSignalHandlerException();
+ // used for console.time(), console.timeEnd()
+ void startTimer(const QString &timerName);
+ qint64 stopTimer(const QString &timerName, bool *wasRunning);
+
+ // used for console.count()
+ int consoleCountHelper(const QString &file, int line, int column);
+
QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
QSet<int> visitedConversionObjects;
+
+ static QDateTime qtDateTimeFromJsDate(double jsDate);
+
+ void addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle);
+ void addRelationshipForGC(QObject *object, QObject *other);
+
+ struct ThreadData {
+ ThreadData();
+ ~ThreadData();
+ v8::Isolate* isolate;
+ bool gcPrologueCallbackRegistered;
+ QIntrusiveList<QV8GCCallback::Node, &QV8GCCallback::Node::node> gcCallbackNodes;
+ };
+
+ static bool hasThreadData();
+ static ThreadData* threadData();
+ static void ensurePerThreadIsolate();
+
+ v8::Persistent<v8::Object> m_strongReferencer;
+
protected:
QJSEngine* q;
QDeclarativeEngine *m_engine;
QV8ListWrapper m_listWrapper;
QV8VariantWrapper m_variantWrapper;
QV8ValueTypeWrapper m_valueTypeWrapper;
+ QV8SequenceWrapper m_sequenceWrapper;
v8::Persistent<v8::Function> m_getOwnPropertyNames;
v8::Persistent<v8::Function> m_freezeObject;
QVector<Deletable *> m_extensionData;
Deletable *m_listModelData;
- QSet<QString> m_illegalNames;
+ QStringHash<bool> m_illegalNames;
Exception m_exception;
+ QElapsedTimer m_time;
+ QHash<QString, qint64> m_startedTimers;
+
+ QHash<QString, quint32> m_consoleCount;
+
QVariant toBasicVariant(v8::Handle<v8::Value>);
void initializeGlobal(v8::Handle<v8::Object>);
- static v8::Handle<v8::Value> gc(const v8::Arguments &args);
- static v8::Handle<v8::Value> print(const v8::Arguments &args);
- static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
- static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
- static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
- static v8::Handle<v8::Value> rect(const v8::Arguments &args);
- static v8::Handle<v8::Value> point(const v8::Arguments &args);
- static v8::Handle<v8::Value> size(const v8::Arguments &args);
- static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
- static v8::Handle<v8::Value> vector4d(const v8::Arguments &args);
- static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
- static v8::Handle<v8::Value> darker(const v8::Arguments &args);
- static v8::Handle<v8::Value> tint(const v8::Arguments &args);
- static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
- static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
- static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
- static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
- static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
- static v8::Handle<v8::Value> md5(const v8::Arguments &args);
- static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
- static v8::Handle<v8::Value> atob(const v8::Arguments &args);
- static v8::Handle<v8::Value> quit(const v8::Arguments &args);
- static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
- static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
- static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTr(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTrId(const v8::Arguments &args);
- static v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args);
- static v8::Handle<v8::Value> stringArg(const v8::Arguments &args);
-
double qtDateTimeToJsDate(const QDateTime &dt);
- QDateTime qtDateTimeFromJsDate(double jsDate);
private:
+ static v8::Persistent<v8::Object> *findOwnerAndStrength(QObject *object, bool *shouldBeStrong);
+
typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
ValueList m_values;
typedef QScriptIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList;
ValueIteratorList m_valueIterators;
Q_DISABLE_COPY(QV8Engine)
- friend class QV8DebugService;
};
// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated
return m_qobjectWrapper.newQObject(object);
}
+v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership)
+{
+ if (!object)
+ return v8::Null();
+
+ v8::Handle<v8::Value> result = newQObject(object);
+ QDeclarativeData *ddata = QDeclarativeData::get(object, true);
+ if (ownership == JavaScriptOwnership && ddata) {
+ ddata->indestructible = false;
+ ddata->explicitIndestructibleSet = true;
+ }
+ return result;
+}
+
v8::Local<v8::String> QV8Engine::toString(const QString &string)
{
return m_stringWrapper.toString(string);
return m_valueTypeWrapper.newValueType(value, type);
}
+v8::Handle<v8::Value> QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded)
+{
+ return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded);
+}
+
// XXX Can this be made more optimal? It is called prior to resolving each and every
// unqualified name in QV8ContextWrapper.
bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)