Convert QQmlPropertyCache to use QV4::persistentValue instead of the v8 version
authorLars Knoll <lars.knoll@digia.com>
Mon, 6 May 2013 10:43:39 +0000 (12:43 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 6 May 2013 13:53:54 +0000 (15:53 +0200)
The V4 persistent values are safer to use, as the v8 ones never
implemented proper semantics when the engine gets deleted.

Change-Id: I787f8c01c70828f22ac60f0ac25201cdfa5a617f
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/qqmlpropertycache.cpp
src/qml/qml/qqmlpropertycache_p.h
src/qml/qml/v4/qv4functionobject.cpp
src/qml/qml/v4/qv4functionobject_p.h
src/qml/qml/v4/qv4mm.cpp
src/qml/qml/v4/qv4value_p.h
src/qml/qml/v8/qv8qobjectwrapper.cpp

index dee534d..c2ad069 100644 (file)
@@ -290,8 +290,8 @@ QQmlPropertyCache::~QQmlPropertyCache()
 
 void QQmlPropertyCache::destroy()
 {
-    Q_ASSERT(engine || constructor.IsEmpty());
-    if (constructor.IsEmpty())
+    Q_ASSERT(engine || constructor->isDeleted());
+    if (constructor->isDeleted())
         delete this;
     else
         QQmlEnginePrivate::deleteInEngineThread(engine, this);
@@ -301,7 +301,6 @@ void QQmlPropertyCache::destroy()
 // that are tied to the specific QQmlEngine.
 void QQmlPropertyCache::clear()
 {
-    qPersistentDispose(constructor);
     engine = 0;
 }
 
@@ -599,7 +598,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
                                        QQmlPropertyData::Flag signalFlags)
 {
     Q_UNUSED(revision);
-    Q_ASSERT(constructor.IsEmpty()); // We should not be appending to an in-use property cache
+    Q_ASSERT(constructor->isDeleted()); // We should not be appending to an in-use property cache
 
     _metaObject = metaObject;
 
index 960f3e5..c1c7cc2 100644 (file)
@@ -62,6 +62,8 @@
 #include <QtCore/qvarlengtharray.h>
 #include <QtCore/qvector.h>
 
+#include <private/qv4value_p.h>
+
 QT_BEGIN_NAMESPACE
 
 class QV8Engine;
@@ -390,7 +392,7 @@ private:
     IndexCache signalHandlerIndexCache;
     StringCache stringCache;
     AllowedRevisionCache allowedRevisionCache;
-    v8::Persistent<v8::Function> constructor;
+    QV4::PersistentValue constructor;
 
     bool _hasPropertyOverrides : 1;
     bool _ownMetaObject : 1;
index 7e889a3..38284a3 100644 (file)
@@ -111,6 +111,11 @@ FunctionObject::FunctionObject(ExecutionContext *scope, String *name)
          defineReadonlyProperty(scope->engine->id_name, Value::fromString(name));
 }
 
+Value FunctionObject::newInstance()
+{
+    return construct(internalClass->engine->current, 0, 0);
+}
+
 bool FunctionObject::hasInstance(Managed *that, ExecutionContext *ctx, const Value &value)
 {
     FunctionObject *f = static_cast<FunctionObject *>(that);
index 50382a3..315f3dc 100644 (file)
@@ -157,6 +157,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
 
     FunctionObject(ExecutionContext *scope, String *name = 0);
 
+    Value newInstance();
+
     static Value construct(Managed *that, ExecutionContext *context, Value *args, int argc);
     static Value call(Managed *that, ExecutionContext *, const Value &, Value *, int);
     inline Value construct(ExecutionContext *context, Value *args, int argc) {
index b59100d..f71f7a8 100644 (file)
@@ -399,8 +399,7 @@ MemoryManager::~MemoryManager()
 {
     PersistentValuePrivate *persistent = m_persistentValues;
     while (persistent) {
-        if (Managed *m = persistent->value.asManaged())
-            persistent->value = Value::deletedValue();
+        persistent->value = Value::deletedValue();
         PersistentValuePrivate *n = persistent->next;
         persistent->next = 0;
         persistent = n;
index fb63935..29fc68b 100644 (file)
@@ -552,7 +552,7 @@ inline Value Managed::call(ExecutionContext *context, const Value &thisObject, V
 struct PersistentValuePrivate
 {
     PersistentValuePrivate()
-        : value(Value::undefinedValue())
+        : value(Value::deletedValue())
         , refcount(1)
         , next(0)
     {}
index e863747..e7f87ad 100644 (file)
@@ -53,6 +53,8 @@
 #include <private/qqmlexpression_p.h>
 #include <private/qqmlglobal_p.h>
 
+#include <private/qv4functionobject_p.h>
+
 #include <QtQml/qjsvalue.h>
 #include <QtCore/qjsonarray.h>
 #include <QtCore/qjsonobject.h>
@@ -959,7 +961,7 @@ v8::Local<v8::Object> QQmlPropertyCache::newQObject(QObject *object, QV8Engine *
     Q_ASSERT(QQmlData::get(object, false)->propertyCache == this);
 
     // Setup constructor
-    if (constructor.IsEmpty()) {
+    if (constructor->isDeleted()) {
         v8::Local<v8::FunctionTemplate> ft;
 
         const QHashedString toString(QStringLiteral("toString"));
@@ -1034,7 +1036,7 @@ v8::Local<v8::Object> QQmlPropertyCache::newQObject(QObject *object, QV8Engine *
         }
 
         if (ft.IsEmpty()) {
-            constructor = qPersistentNew<v8::Function>(engine->qobjectWrapper()->m_constructor);
+            constructor = engine->qobjectWrapper()->m_constructor->v4Value();
         } else {
             ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, 
                                                                QV8QObjectWrapper::Setter,
@@ -1042,13 +1044,13 @@ v8::Local<v8::Object> QQmlPropertyCache::newQObject(QObject *object, QV8Engine *
                                                                0,
                                                                QV8QObjectWrapper::Enumerator);
             ft->InstanceTemplate()->SetHasExternalResource(true);
-            constructor = qPersistentNew<v8::Function>(ft->GetFunction());
+            constructor = ft->GetFunction()->v4Value();
         }
 
         QQmlCleanup::addToEngine(this->engine);
     }
 
-    v8::Local<v8::Object> result = constructor->NewInstance();
+    v8::Local<v8::Object> result = v8::Local<v8::Object>::New(constructor->asFunctionObject()->newInstance());
     QV8QObjectResource *r = new QV8QObjectResource(engine, object);
     result->SetExternalResource(r);
     return result;