X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdeclarative%2Fqml%2Fv8%2Fqv8engine_p.h;h=f46a660c6dd3d63914b71295650003c8fba46cf9;hb=45b14259fc0cf704692df1c00da511527d1fba1d;hp=46ba0a4431d89606ab9dfe49c8bc93101e9033d7;hpb=ee67e60cad8f9da67d8e8f11aeaf6efb11de89e9;p=profile%2Fivi%2Fqtdeclarative.git diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h index 46ba0a4..f46a660 100644 --- a/src/declarative/qml/v8/qv8engine_p.h +++ b/src/declarative/qml/v8/qv8engine_p.h @@ -1,34 +1,34 @@ /**************************************************************************** ** -** 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_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** @@ -57,7 +57,18 @@ #include #include #include +#include +#include +#include +#include + #include +#include +#include +#include "qjsvalue_p.h" +#include "qjsvalueiterator_p.h" +#include "qscriptoriginalglobalobject_p.h" +#include "qscripttools_p.h" #include @@ -68,6 +79,7 @@ #include "qv8listwrapper_p.h" #include "qv8variantwrapper_p.h" #include "qv8valuetypewrapper_p.h" +#include "qv8sequencewrapper_p.h" QT_BEGIN_NAMESPACE @@ -90,6 +102,10 @@ private: v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ return v8::Handle(); \ } +#define V8THROW_TYPE(string) { \ + v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \ + return v8::Handle(); \ +} #define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data())); #define V8THROW_ERROR_SETTER(string) { \ v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ @@ -114,6 +130,7 @@ private: return rv; \ } \ + class QV8Engine; class QV8ObjectResource : public v8::Object::ExternalResource { @@ -121,7 +138,9 @@ public: QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); } enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType, - ListModelType, Context2DType }; + ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, + ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType, + SequenceType, LocaleDataType }; virtual ResourceType resourceType() const = 0; QV8Engine *engine; @@ -188,12 +207,13 @@ public: QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; } static QDeclarativeV8Handle fromHandle(v8::Handle h) { - return reinterpret_cast(h); + return QDeclarativeV8Handle(*h); } v8::Handle toHandle() const { - return reinterpret_cast &>(*this); + return v8::Handle((v8::Value *)d); } private: + QDeclarativeV8Handle(void *d) : d(d) {} void *d; }; @@ -202,26 +222,89 @@ class QDeclarativeEngine; class QDeclarativeValueType; class QNetworkAccessManager; class QDeclarativeContextData; -class Q_AUTOTEST_EXPORT QV8Engine + +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(); + static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); } + static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; } + + 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 { - ~Deletable() {} + virtual ~Deletable() {} }; - void init(QDeclarativeEngine *); + class Exception + { + typedef QPair, v8::Persistent > ValueMessagePair; + + v8::Persistent m_value; + v8::Persistent m_message; + QStack m_stack; + + Q_DISABLE_COPY(Exception) + public: + inline Exception(); + inline ~Exception(); + inline void set(v8::Handle value, v8::Handle message); + inline void clear(); + inline operator bool() const; + inline operator v8::Handle() const; + inline int lineNumber() const; + inline QStringList backtrace() const; + + inline void push(); + inline void pop(); + }; + void initDeclarativeGlobalObject(); + void setEngine(QDeclarativeEngine *engine); QDeclarativeEngine *engine() { return m_engine; } v8::Local global() { return m_context->Global(); } - v8::Handle context() { return m_context; } + v8::Handle context() const { return m_context; } + + inline void registerValue(QJSValuePrivate *data); + inline void unregisterValue(QJSValuePrivate *data); + inline void invalidateAllValues(); + + inline void registerValueIterator(QJSValueIteratorPrivate *data); + inline void unregisterValueIterator(QJSValueIteratorPrivate *data); + inline void invalidateAllIterators(); + QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; } QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; } QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; } 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; } @@ -232,6 +315,7 @@ public: QDeclarativeContextData *callingContext(); v8::Local getOwnPropertyNames(v8::Handle); + inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle object, v8::Handle property); void freezeObject(v8::Handle); inline QString toString(v8::Handle string); @@ -252,8 +336,12 @@ public: // Return the QML global "scope" object for the \a ctxt context and \a scope object. inline v8::Local qmlScope(QDeclarativeContextData *ctxt, QObject *scope); + QScriptPassPointer newRegExp(const QRegExp ®exp); + QScriptPassPointer newRegExp(const QString &pattern, const QString &flags); + // Return a JS wrapper for the given QObject \a object inline v8::Handle newQObject(QObject *object); + inline v8::Handle newQObject(QObject *object, const ObjectOwnership ownership); inline bool isQObject(v8::Handle); inline QObject *toQObject(v8::Handle); @@ -264,6 +352,9 @@ public: inline v8::Handle newValueType(QObject *, int coreIndex, QDeclarativeValueType *); inline v8::Handle newValueType(const QVariant &, QDeclarativeValueType *); + // Create a new sequence type object + inline v8::Handle 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 newQVariant(const QVariant &); @@ -274,10 +365,21 @@ public: virtual QNetworkAccessManager *networkAccessManager(); // Return the list of illegal id names (the names of the properties on the global object) - const QSet &illegalNames() const; + const QStringHash &illegalNames() const; + inline void collectGarbage() { gc(); } static void gc(); + void clearExceptions(); + void setException(v8::Handle value, v8::Handle message = v8::Handle()); + v8::Handle throwException(v8::Handle value); + bool hasUncaughtException() const; + int uncaughtExceptionLineNumber() const; + QStringList uncaughtExceptionBacktrace() const; + v8::Handle uncaughtException() const; + void saveException(); + void restoreException(); + #ifdef QML_GLOBAL_HANDLE_DEBUGGING // Used for handle debugging static void registerHandle(void *); @@ -290,9 +392,77 @@ public: inline Deletable *extensionData(int) const; void setExtensionData(int, Deletable *); -private: + inline v8::Handle makeJSValue(bool value); + inline v8::Local makeJSValue(int value); + inline v8::Local makeJSValue(uint value); + inline v8::Local makeJSValue(double value); + inline v8::Handle makeJSValue(QJSValue::SpecialValue value); + inline v8::Local makeJSValue(const QString &value); + + inline QScriptPassPointer evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); + QScriptPassPointer evaluate(v8::Handle script, v8::TryCatch& tryCatch); + + QScriptPassPointer newArray(uint length); + v8::Local newVariant(const QVariant &variant); + QScriptPassPointer newVariant(QJSValuePrivate* value, const QVariant &variant); + + v8::Local variantListToJS(const QVariantList &lst); + QVariantList variantListFromJS(v8::Handle jsArray); + + v8::Local variantMapToJS(const QVariantMap &vmap); + QVariantMap variantMapFromJS(v8::Handle jsObject); + + v8::Handle variantToJS(const QVariant &value); + QVariant variantFromJS(v8::Handle value); + + v8::Handle metaTypeToJS(int type, const void *data); + bool metaTypeFromJS(v8::Handle value, int type, void *data); + + bool convertToNativeQObject(v8::Handle value, + const QByteArray &targetType, + void **result); + + QVariant &variantValue(v8::Handle value); + + QJSValue scriptValueFromInternal(v8::Handle) const; + + 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 value); + QSet visitedConversionObjects; + + static QDateTime qtDateTimeFromJsDate(double jsDate); + + void addRelationshipForGC(QObject *object, v8::Persistent handle); + void addRelationshipForGC(QObject *object, QObject *other); + + struct ThreadData { + ThreadData(); + ~ThreadData(); + v8::Isolate* isolate; + bool gcPrologueCallbackRegistered; + QIntrusiveList gcCallbackNodes; + }; + + static bool hasThreadData(); + static ThreadData* threadData(); + static void ensurePerThreadIsolate(); + + v8::Persistent m_strongReferencer; + +protected: + QJSEngine* q; QDeclarativeEngine *m_engine; + bool m_ownsV8Context; v8::Persistent m_context; + QScriptOriginalGlobalObject m_originalGlobalObject; QV8StringWrapper m_stringWrapper; QV8ContextWrapper m_contextWrapper; @@ -301,6 +471,7 @@ private: QV8ListWrapper m_listWrapper; QV8VariantWrapper m_variantWrapper; QV8ValueTypeWrapper m_valueTypeWrapper; + QV8SequenceWrapper m_sequenceWrapper; v8::Persistent m_getOwnPropertyNames; v8::Persistent m_freezeObject; @@ -311,39 +482,30 @@ private: QVector m_extensionData; Deletable *m_listModelData; - QSet m_illegalNames; + QStringHash m_illegalNames; + + Exception m_exception; + + QElapsedTimer m_time; + QHash m_startedTimers; + + QHash m_consoleCount; QVariant toBasicVariant(v8::Handle); void initializeGlobal(v8::Handle); - static v8::Handle gc(const v8::Arguments &args); - static v8::Handle print(const v8::Arguments &args); - static v8::Handle isQtObject(const v8::Arguments &args); - static v8::Handle rgba(const v8::Arguments &args); - static v8::Handle hsla(const v8::Arguments &args); - static v8::Handle rect(const v8::Arguments &args); - static v8::Handle point(const v8::Arguments &args); - static v8::Handle size(const v8::Arguments &args); - static v8::Handle vector3d(const v8::Arguments &args); - static v8::Handle lighter(const v8::Arguments &args); - static v8::Handle darker(const v8::Arguments &args); - static v8::Handle tint(const v8::Arguments &args); - static v8::Handle formatDate(const v8::Arguments &args); - static v8::Handle formatTime(const v8::Arguments &args); - static v8::Handle formatDateTime(const v8::Arguments &args); - static v8::Handle openUrlExternally(const v8::Arguments &args); - static v8::Handle fontFamilies(const v8::Arguments &args); - static v8::Handle md5(const v8::Arguments &args); - static v8::Handle btoa(const v8::Arguments &args); - static v8::Handle atob(const v8::Arguments &args); - static v8::Handle quit(const v8::Arguments &args); - static v8::Handle resolvedUrl(const v8::Arguments &args); - static v8::Handle createQmlObject(const v8::Arguments &args); - static v8::Handle createComponent(const v8::Arguments &args); - double qtDateTimeToJsDate(const QDateTime &dt); - QDateTime qtDateTimeFromJsDate(double jsDate); + +private: + static v8::Persistent *findOwnerAndStrength(QObject *object, bool *shouldBeStrong); + + typedef QScriptIntrusiveList ValueList; + ValueList m_values; + typedef QScriptIntrusiveList ValueIteratorList; + ValueIteratorList m_valueIterators; + + Q_DISABLE_COPY(QV8Engine) }; // Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated @@ -417,6 +579,20 @@ v8::Handle QV8Engine::newQObject(QObject *object) return m_qobjectWrapper.newQObject(object); } +v8::Handle QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership) +{ + if (!object) + return v8::Null(); + + v8::Handle result = newQObject(object); + QDeclarativeData *ddata = QDeclarativeData::get(object, true); + if (ownership == JavaScriptOwnership && ddata) { + ddata->indestructible = false; + ddata->explicitIndestructibleSet = true; + } + return result; +} + v8::Local QV8Engine::toString(const QString &string) { return m_stringWrapper.toString(string); @@ -432,6 +608,11 @@ v8::Handle QV8Engine::newValueType(const QVariant &value, QDeclarativ return m_valueTypeWrapper.newValueType(value, type); } +v8::Handle 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 string)