Add support for more sequence types
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qv8qobjectwrapper.cpp
index d1bf0e3..40cb021 100644 (file)
@@ -7,29 +7,29 @@
 ** 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.
 **
 **
 **
 #include <private/qdeclarativeengine_p.h>
 #include <private/qdeclarativevmemetaobject_p.h>
 #include <private/qdeclarativebinding_p.h>
+#include <private/qjsvalue_p.h>
+#include <private/qscript_impl_p.h>
 
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
 #include <QtCore/qvarlengtharray.h>
 #include <QtCore/qtimer.h>
 #include <QtCore/qatomic.h>
 
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QJSValue);
 Q_DECLARE_METATYPE(QDeclarativeV8Handle);
 
+QT_BEGIN_NAMESPACE
+
 #if defined(__GNUC__)
 # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
 // The code in this file does not violate strict aliasing, but GCC thinks it does
@@ -107,7 +109,28 @@ public:
     QV8QObjectWrapper *wrapper;
 };
 
+class QV8SignalHandlerResource : public QV8ObjectResource
+{
+    V8_RESOURCE_TYPE(SignalHandlerType)
+public:
+    QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index);
+
+    QDeclarativeGuard<QObject> object;
+    int index;
+};
+
 namespace {
+
+template<typename A, typename B, typename C, typename D, typename E>
+class MaxSizeOf5 {
+    template<typename Z, typename X>
+    struct SMax {
+        static const size_t Size = sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X);
+    };
+public:
+    static const size_t Size = SMax<A, SMax<B, SMax<C, SMax<D, E> > > >::Size;
+};
+
 struct MetaCallArgument {
     inline MetaCallArgument();
     inline ~MetaCallArgument();
@@ -122,9 +145,31 @@ private:
 
     inline void cleanup();
 
-    char data[4 * sizeof(void *)];
+    union {
+        float floatValue;
+        double doubleValue;
+        quint32 intValue;
+        bool boolValue;
+        QObject *qobjectPtr;
+
+        char allocData[MaxSizeOf5<QVariant,
+                                QString,
+                                QList<QObject *>,
+                                QJSValue,
+                                QDeclarativeV8Handle>::Size];
+        qint64 q_for_alignment;
+    };
+
+    // Pointers to allocData
+    union {
+        QString *qstringPtr;
+        QVariant *qvariantPtr;
+        QList<QObject *> *qlistPtr;
+        QJSValue *qjsValuePtr;
+        QDeclarativeV8Handle *handlePtr;
+    };
+
     int type;
-    bool isObjectType;
 };
 }
 
@@ -133,6 +178,11 @@ QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object)
 {
 }
 
+QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index)
+: QV8ObjectResource(engine), object(object), index(index)
+{
+}
+
 static QAtomicInt objectIdCounter(1);
 
 QV8QObjectWrapper::QV8QObjectWrapper()
@@ -158,6 +208,7 @@ void QV8QObjectWrapper::destroy()
     qPersistentDispose(m_hiddenObject);
     qPersistentDispose(m_destroySymbol);
     qPersistentDispose(m_toStringSymbol);
+    qPersistentDispose(m_signalHandlerConstructor);
     qPersistentDispose(m_methodConstructor);
     qPersistentDispose(m_constructor);
 }
@@ -166,16 +217,16 @@ void QV8QObjectWrapper::destroy()
 static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) \
 { \
     v8::Handle<v8::Object> This = info.This(); \
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(This); \
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
  \
-    if (!resource || resource->object.isNull()) return v8::Undefined(); \
+    if (resource->object.isNull()) return v8::Undefined(); \
  \
     QObject *object = resource->object; \
  \
     uint32_t data = info.Data()->Uint32Value(); \
     int index = data & 0x7FFF; \
-    int notify = (data & 0x7FFF0000) >> 16; \
-    if (notify == 0x7FFF) notify = -1; \
+    int notify = (data & 0x0FFF0000) >> 16; \
+    if (notify == 0x0FFF) notify = -1; \
  \
     QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
     if (ep && notify /* 0 means constant */ && ep->captureProperties) { \
@@ -188,6 +239,32 @@ static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8
     QMetaObject::metacall(object, QMetaObject::ReadProperty, index, args); \
  \
     return constructor(value); \
+} \
+static v8::Handle<v8::Value> name ## ValueGetterDirect(v8::Local<v8::String>, const v8::AccessorInfo &info) \
+{ \
+    v8::Handle<v8::Object> This = info.This(); \
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
+ \
+    if (resource->object.isNull()) return v8::Undefined(); \
+ \
+    QObject *object = resource->object; \
+ \
+    uint32_t data = info.Data()->Uint32Value(); \
+    int index = data & 0x7FFF; \
+    int notify = (data & 0x0FFF0000) >> 16; \
+    if (notify == 0x0FFF) notify = -1; \
+ \
+    QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
+    if (ep && notify /* 0 means constant */ && ep->captureProperties) { \
+        typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty; \
+        ep->capturedProperties << CapturedProperty(object, index, notify); \
+    } \
+ \
+    cpptype value = defaultvalue; \
+    void *args[] = { &value, 0 }; \
+    object->qt_metacall(QMetaObject::ReadProperty, index, args); \
+ \
+    return constructor(value); \
 } 
 
 #define CREATE_FUNCTION \
@@ -199,6 +276,10 @@ static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8
         "});"\
     "})"
 
+
+static quint32 toStringHash = -1;
+static quint32 destroyHash = -1;
+
 void QV8QObjectWrapper::init(QV8Engine *engine)
 {
     m_engine = engine;
@@ -207,6 +288,12 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
     m_destroySymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("destroy"));
     m_hiddenObject = qPersistentNew<v8::Object>(v8::Object::New());
 
+    m_toStringString = QHashedV8String(m_toStringSymbol);
+    m_destroyString = QHashedV8String(m_destroySymbol);
+
+    toStringHash = m_toStringString.hash();
+    destroyHash = m_destroyString.hash();
+
     {
     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
     ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator);
@@ -223,10 +310,21 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
     m_methodConstructor = qPersistentNew<v8::Function>(createFn);
     }
 
+    v8::Local<v8::Function> connect = V8FUNCTION(Connect, engine);
+    v8::Local<v8::Function> disconnect = V8FUNCTION(Disconnect, engine);
+
+    {
+    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+    ft->InstanceTemplate()->SetHasExternalResource(true);
+    ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum);
+    ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
+    m_signalHandlerConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
+    }
+
     {
     v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
-    prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine));
-    prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine));
+    prototype->Set(v8::String::New("connect"), connect, v8::DontEnum);
+    prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
     }
 }
 
@@ -242,7 +340,7 @@ QObject *QV8QObjectWrapper::toQObject(v8::Handle<v8::Object> obj)
 }
 
 // r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType)
-QObject *QV8QObjectWrapper::QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
+QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
 {
     Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType);
     return static_cast<QV8QObjectResource *>(r)->object;
@@ -250,7 +348,7 @@ QObject *QV8QObjectWrapper::QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
 
 // Load value properties
 static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object, 
-                                          const QDeclarativePropertyCache::Data &property)
+                                          const QDeclarativePropertyData &property)
 {
     Q_ASSERT(!property.isFunction());
 
@@ -270,7 +368,7 @@ static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
     } else if (property.isQList()) {
         return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
     } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
-    else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Number::New)
+    else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
     else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
     else PROPERTY_LOAD(QString, QString, engine->toString)
     else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
@@ -280,21 +378,81 @@ static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
         QDeclarativeV8Handle handle;
         void *args[] = { &handle, 0 };
         QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); 
-        return reinterpret_cast<v8::Handle<v8::Value> &>(handle);
-    } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+        return handle.toHandle();
+    } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)
+               && engine->engine()) {
         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
         QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
         if (valueType)
             return engine->newValueType(object, property.coreIndex, valueType);
-    } 
+    } else {
+        // see if it's a sequence type
+        bool succeeded = false;
+        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &succeeded);
+        if (succeeded)
+            return retn;
+    }
 
     QVariant var = object->metaObject()->property(property.coreIndex).read(object);
     return engine->fromVariant(var);
+
+#undef PROPERTY_LOAD
+}
+
+static v8::Handle<v8::Value> LoadPropertyDirect(QV8Engine *engine, QObject *object, 
+                                                const QDeclarativePropertyData &property)
+{
+    Q_ASSERT(!property.isFunction());
+
+#define PROPERTY_LOAD(metatype, cpptype, constructor) \
+    if (property.propType == QMetaType:: metatype) { \
+        cpptype type = cpptype(); \
+        void *args[] = { &type, 0 }; \
+        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); \
+        return constructor(type); \
+    }
+
+    if (property.isQObject()) {
+        QObject *rv = 0;
+        void *args[] = { &rv, 0 };
+        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+        return engine->newQObject(rv);
+    } else if (property.isQList()) {
+        return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
+    } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
+    else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
+    else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
+    else PROPERTY_LOAD(QString, QString, engine->toString)
+    else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
+    else PROPERTY_LOAD(Float, float, v8::Number::New)
+    else PROPERTY_LOAD(Double, double, v8::Number::New)
+    else if(property.isV8Handle()) {
+        QDeclarativeV8Handle handle;
+        void *args[] = { &handle, 0 };
+        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); 
+        return handle.toHandle();
+    } else if (engine->engine() && QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+        QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
+        if (valueType)
+            return engine->newValueType(object, property.coreIndex, valueType);
+    } else {
+        // see if it's a sequence type
+        bool success = false;
+        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &success);
+        if (success)
+            return retn;
+    }
+
+    QVariant var = object->metaObject()->property(property.coreIndex).read(object);
+    return engine->fromVariant(var);
+
+#undef PROPERTY_LOAD
 }
 
 v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, 
                                                      v8::Handle<v8::Value> *objectHandle, 
-                                                     v8::Handle<v8::String> property,
+                                                     const QHashedV8String &property,
                                                      QV8QObjectWrapper::RevisionMode revisionMode)
 {
     // XXX More recent versions of V8 introduced "Callable" objects.  It is possible that these
@@ -321,21 +479,29 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
        }
     };
 
-    if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property)) {
-        return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
-    } else if (engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property)) {
-        return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+    {
+        // Comparing the hash first actually makes a measurable difference here, at least on x86
+        quint32 hash = property.hash();
+        if (hash == toStringHash && engine->qobjectWrapper()->m_toStringString == property) {
+            return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
+        } else if (hash == destroyHash && engine->qobjectWrapper()->m_destroyString == property) {
+            return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+        }
     }
 
-    QDeclarativePropertyCache::Data local;
-    QDeclarativePropertyCache::Data *result = 0;
-    result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+    QDeclarativePropertyData local;
+    QDeclarativePropertyData *result = 0;
+    {
+        QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+        if (ddata && ddata->propertyCache)
+            result = ddata->propertyCache->property(property);
+        else
+            result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+    }
 
     if (!result)
         return v8::Handle<v8::Value>();
 
-    QDeclarativeEnginePrivate *ep = engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
-
     if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
         QDeclarativeData *ddata = QDeclarativeData::get(object);
         if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
@@ -345,15 +511,21 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
     typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
 
     if (result->isFunction()) {
-        if (result->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
+        if (result->isVMEFunction()) {
             return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
-        } else if (result->flags & QDeclarativePropertyCache::Data::IsV8Function) {
+        } else if (result->isV8Function()) {
             return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
+        } else if (result->isSignalHandler()) {
+            v8::Local<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance();
+            QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex);
+            handler->SetExternalResource(r);
+            return handler;
         } else {
             return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
         }
     }
 
+    QDeclarativeEnginePrivate *ep = engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
     if (ep && ep->captureProperties && !result->isConstant()) {
         if (result->coreIndex == 0)
             ep->capturedProperties << CapturedProperty(QDeclarativeData::get(object, true)->objectNameNotifier());
@@ -361,11 +533,18 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
             ep->capturedProperties << CapturedProperty(object, result->coreIndex, result->notifyIndex);
     }
 
-    return LoadProperty(engine, object, *result);
+    if (result->isVMEProperty())
+        return static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject*>(object->metaObject()))->vmeProperty(result->coreIndex);
+
+    if (result->isDirect())  {
+        return LoadPropertyDirect(engine, object, *result);
+    } else {
+        return LoadProperty(engine, object, *result);
+    }
 }
 
 // Setter for writable properties.  Shared between the interceptor and fast property accessor
-static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyCache::Data *property,
+static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyData *property,
                                  v8::Handle<v8::Value> value)
 {
     QDeclarativeBinding *newBinding = 0;
@@ -381,10 +560,9 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativ
         int lineNumber = frame->GetLineNumber();
         QString url = engine->toString(frame->GetScriptName());
 
-        QDeclarativePropertyCache::ValueTypeData valueTypeData;
         newBinding = new QDeclarativeBinding(&function, object, context);
         newBinding->setSourceLocation(url, lineNumber);
-        newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, valueTypeData, object, context));
+        newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, object, context));
         newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
     }
 
@@ -424,6 +602,8 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativ
         PROPERTY_STORE(double, double(value->ToNumber()->Value()));
     } else if (property->propType == QMetaType::QString && value->IsString()) {
         PROPERTY_STORE(QString, engine->toString(value->ToString()));
+    } else if (property->isVMEProperty()) {
+        static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(object->metaObject()))->setVMEProperty(property->coreIndex, value);
     } else {
         QVariant v;
         if (property->isQList()) 
@@ -432,7 +612,6 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativ
             v = engine->toVariant(value, property->propType);
 
         QDeclarativeContextData *context = engine->callingContext();
-
         if (!QDeclarativePropertyPrivate::write(object, *property, v, context)) {
             const char *valueType = 0;
             if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -447,15 +626,15 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativ
     }
 }
 
-bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Handle<v8::String> property,
+bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV8String &property,
                                     v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode)
 {
-    if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property) ||
-        engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property))
+    if (engine->qobjectWrapper()->m_toStringString == property ||
+        engine->qobjectWrapper()->m_destroyString == property)
         return true;
 
-    QDeclarativePropertyCache::Data local;
-    QDeclarativePropertyCache::Data *result = 0;
+    QDeclarativePropertyData local;
+    QDeclarativePropertyData *result = 0;
     result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
 
     if (!result)
@@ -469,7 +648,7 @@ bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Hand
 
     if (!result->isWritable() && !result->isQList()) {
         QString error = QLatin1String("Cannot assign to read-only property \"") +
-                        engine->toString(property) + QLatin1Char('\"');
+                        engine->toString(property.string()) + QLatin1Char('\"');
         v8::ThrowException(v8::Exception::Error(engine->toString(error)));
         return true;
     }
@@ -482,48 +661,61 @@ bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Hand
 v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property, 
                                                 const v8::AccessorInfo &info)
 {
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
-    v8::Handle<v8::Value> This = info.This();
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 
-    if (!resource || resource->object.isNull()) return v8::Undefined();
+    if (resource->object.isNull()) 
+        return v8::Handle<v8::Value>();
 
     QObject *object = resource->object;
 
+    QHashedV8String propertystring(property);
+
     QV8Engine *v8engine = resource->engine;
-    v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, property, QV8QObjectWrapper::IgnoreRevision);
+    v8::Handle<v8::Value> This = info.This();
+    v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, propertystring, 
+                                               QV8QObjectWrapper::IgnoreRevision);
     if (!result.IsEmpty())
         return result;
 
     if (QV8Engine::startsWithUpper(property)) {
         // Check for attached properties
         QDeclarativeContextData *context = v8engine->callingContext();
-        QDeclarativeTypeNameCache::Data *data = context && (context->imports)?context->imports->data(property):0;
 
-        if (data) {
-            if (data->type) {
-                return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums);
-            } else if (data->typeNamespace) {
-                return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums);
+        if (context && context->imports) {
+            QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring);
+
+            if (r.isValid()) {
+                if (r.scriptIndex != -1) {
+                    return v8::Undefined();
+                } else if (r.type) {
+                    return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums);
+                } else if (r.importNamespace) {
+                    return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, 
+                                                              QV8TypeWrapper::ExcludeEnums);
+                }
+                Q_ASSERT(!"Unreachable");
             }
         }
     } 
 
-    return v8::Undefined();
+    return v8::Handle<v8::Value>();
 }
 
 v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property, 
                                                 v8::Local<v8::Value> value,
                                                 const v8::AccessorInfo &info)
 {
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 
-    if (!resource || resource->object.isNull()) 
+    if (resource->object.isNull()) 
         return value;
 
     QObject *object = resource->object;
 
+    QHashedV8String propertystring(property);
+
     QV8Engine *v8engine = resource->engine;
-    bool result = SetProperty(v8engine, object, property, value, QV8QObjectWrapper::IgnoreRevision);
+    bool result = SetProperty(v8engine, object, propertystring, value, QV8QObjectWrapper::IgnoreRevision);
 
     if (!result) {
         QString error = QLatin1String("Cannot assign to non-existent property \"") +
@@ -538,17 +730,19 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
 v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
                                                  const v8::AccessorInfo &info)
 {
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 
-    if (!resource || resource->object.isNull()) 
+    if (resource->object.isNull()) 
         return v8::Handle<v8::Integer>();
 
     QV8Engine *engine = resource->engine;
     QObject *object = resource->object;
 
-    QDeclarativePropertyCache::Data local;
-    QDeclarativePropertyCache::Data *result = 0;
-    result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+    QHashedV8String propertystring(property);
+
+    QDeclarativePropertyData local;
+    QDeclarativePropertyData *result = 0;
+    result = QDeclarativePropertyCache::property(engine->engine(), object, propertystring, local);
 
     if (!result)
         return v8::Handle<v8::Integer>();
@@ -560,16 +754,18 @@ v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
 
 v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info)
 {
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 
-    if (!resource || resource->object.isNull()) 
+    if (resource->object.isNull()) 
         return v8::Array::New();
 
     QObject *object = resource->object;
 
     QStringList result;
 
-    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine());
+    QDeclarativeEnginePrivate *ep = resource->engine->engine()
+            ? QDeclarativeEnginePrivate::get(resource->engine->engine())
+            : 0;
 
     QDeclarativePropertyCache *cache = 0;
     QDeclarativeData *ddata = QDeclarativeData::get(object);
@@ -577,7 +773,7 @@ v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info
         cache = ddata->propertyCache;
 
     if (!cache) {
-        cache = ep->cache(object);
+        cache = ep ? ep->cache(object) : 0;
         if (cache) {
             if (ddata) { cache->addref(); ddata->propertyCache = cache; }
         } else {
@@ -611,9 +807,9 @@ FAST_VALUE_GETTER(Double, double, 0, v8::Number::New);
 static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
                             const v8::AccessorInfo& info)
 {
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 
-    if (!resource || resource->object.isNull()) 
+    if (resource->object.isNull()) 
         return; 
 
     QObject *object = resource->object;
@@ -625,7 +821,7 @@ static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
     Q_ASSERT(ddata);
     Q_ASSERT(ddata->propertyCache);
 
-    QDeclarativePropertyCache::Data *pdata = ddata->propertyCache->property(index);
+    QDeclarativePropertyData *pdata = ddata->propertyCache->property(index);
     Q_ASSERT(pdata);
 
     Q_ASSERT(pdata->isWritable() || pdata->isQList());
@@ -633,11 +829,26 @@ static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
     StoreProperty(resource->engine, object, pdata, value);
 }
 
+static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8::Value>,
+                                    const v8::AccessorInfo& info)
+{
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
+
+    if (resource->object.isNull()) 
+        return; 
+
+    QV8Engine *v8engine = resource->engine;
+
+    QString error = QLatin1String("Cannot assign to read-only property \"") +
+                    v8engine->toString(property) + QLatin1Char('\"');
+    v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
+}
+
 static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *)
 {
     Q_ASSERT(handle->IsObject());
     
-    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(handle->ToObject());
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(handle->ToObject());
 
     Q_ASSERT(resource);
 
@@ -664,6 +875,7 @@ static void WeakQObjectInstanceCallback(v8::Persistent<v8::Value> handle, void *
 v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8Engine *engine)
 {
     Q_ASSERT(object);
+    Q_ASSERT(this->engine);
 
     Q_ASSERT(QDeclarativeData::get(object, false));
     Q_ASSERT(QDeclarativeData::get(object, false)->propertyCache == this);
@@ -679,34 +891,37 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
         // performance, but the  cost of setting up this structure hasn't been measured so 
         // its not guarenteed that this is a win overall.  We need to try and measure the cost.
         for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
-            Data *property = *iter;
-            if (property->isFunction() || !property->isWritable() ||
-                property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x7FFF || 
+            QDeclarativePropertyData *property = *iter;
+            if (property->isFunction() || 
+                property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x0FFF || 
                 property->coreIndex == 0)
                 continue;
 
             v8::AccessorGetter fastgetter = 0;
+            v8::AccessorSetter fastsetter = FastValueSetter;
+            if (!property->isWritable())
+                fastsetter = FastValueSetterReadOnly;
 
             if (property->isQObject()) 
-                fastgetter = QObjectValueGetter;
+                fastgetter = property->isDirect()?QObjectValueGetterDirect:QObjectValueGetter;
             else if (property->propType == QMetaType::Int || property->isEnum()) 
-                fastgetter = IntValueGetter;
+                fastgetter = property->isDirect()?IntValueGetterDirect:IntValueGetter;
             else if (property->propType == QMetaType::Bool)
-                fastgetter = BoolValueGetter;
+                fastgetter = property->isDirect()?BoolValueGetterDirect:BoolValueGetter;
             else if (property->propType == QMetaType::QString)
-                fastgetter = QStringValueGetter;
+                fastgetter = property->isDirect()?QStringValueGetterDirect:QStringValueGetter;
             else if (property->propType == QMetaType::UInt)
-                fastgetter = UIntValueGetter;
+                fastgetter = property->isDirect()?UIntValueGetterDirect:UIntValueGetter;
             else if (property->propType == QMetaType::Float) 
-                fastgetter = FloatValueGetter;
+                fastgetter = property->isDirect()?FloatValueGetterDirect:FloatValueGetter;
             else if (property->propType == QMetaType::Double) 
-                fastgetter = DoubleValueGetter;
+                fastgetter = property->isDirect()?DoubleValueGetterDirect:DoubleValueGetter;
 
             if (fastgetter) {
                 int notifyIndex = property->notifyIndex;
                 if (property->isConstant()) notifyIndex = 0;
-                else if (notifyIndex == -1) notifyIndex = 0x7FFF;
-                uint32_t data = (property->notifyIndex & 0x7FFF) << 16 | property->coreIndex;
+                else if (notifyIndex == -1) notifyIndex = 0x0FFF;
+                uint32_t data = (notifyIndex & 0x0FFF) << 16 | property->coreIndex;
 
                 QString name = iter.key();
                 if (name == toString || name == destroy)
@@ -722,7 +937,7 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
                     ft->InstanceTemplate()->SetHasExternalResource(true);
                 }
 
-                ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, FastValueSetter,
+                ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, fastsetter,
                                                     v8::Integer::NewFromUnsigned(data));
             }
         }
@@ -738,6 +953,8 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
             ft->InstanceTemplate()->SetHasExternalResource(true);
             constructor = qPersistentNew<v8::Function>(ft->GetFunction());
         }
+
+        QDeclarativeCleanup::addToEngine(this->engine);
     }
 
     v8::Local<v8::Object> result = constructor->NewInstance();
@@ -755,7 +972,7 @@ v8::Local<v8::Object> QV8QObjectWrapper::newQObject(QObject *object, QDeclarativ
         if (ddata->propertyCache) ddata->propertyCache->addref();
     }
 
-    if (ddata->propertyCache) {
+    if (ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine->engine()) {
         rv = ddata->propertyCache->newQObject(object, engine);
     } else {
         // XXX NewInstance() should be optimized
@@ -846,6 +1063,17 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
     }
 }
 
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
+{
+    if (object->IsFunction())
+        return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object));
+
+    if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object))
+        return qMakePair(resource->object.data(), resource->index);
+
+    return qMakePair((QObject *)0, -1);
+}
+
 QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
 {
     v8::ScriptOrigin origin = function->GetScriptOrigin();
@@ -866,8 +1094,9 @@ QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::
     return qMakePair((QObject *)0, -1);
 }
 
-struct QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
+class QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
 {
+public:
     QV8QObjectConnectionList(QObject *object, QV8Engine *engine);
     ~QV8QObjectConnectionList();
 
@@ -954,20 +1183,17 @@ int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, v
 
         QList<Connection> connections = connectionList;
 
-        QMetaMethod method = data()->metaObject()->method(index);
-        Q_ASSERT(method.methodType() == QMetaMethod::Signal);
-        // XXX TODO: We should figure out a way to cache the parameter types to avoid resolving
-        // them each time.
-        QList<QByteArray> params = method.parameterTypes();
+        QVarLengthArray<int, 9> dummy;
+        int *argsTypes = QDeclarativePropertyCache::methodParameterTypes(data(), index, dummy, 0);
 
         v8::HandleScope handle_scope;
         v8::Context::Scope scope(engine->context());
 
-        QVarLengthArray<v8::Handle<v8::Value> > args(params.count());
-        int argCount = params.count();
+        int argCount = argsTypes?argsTypes[0]:0;
+        QVarLengthArray<v8::Handle<v8::Value>, 9> args(argCount);
 
         for (int ii = 0; ii < argCount; ++ii) {
-            int type = QMetaType::type(params.at(ii).constData());
+            int type = argsTypes[ii + 1];
             if (type == qMetaTypeId<QVariant>()) {
                 args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
             } else {
@@ -1014,10 +1240,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args)
 
     QV8Engine *engine = V8ENGINE();
 
-    if (!args.This()->IsFunction())
-        V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
-
-    QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+    QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
     QObject *signalObject = signalInfo.first;
     int signalIndex = signalInfo.second;
 
@@ -1076,10 +1299,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
 
     QV8Engine *engine = V8ENGINE();
 
-    if (!args.This()->IsFunction())
-        V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
-
-    QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+    QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
     QObject *signalObject = signalInfo.first;
     int signalIndex = signalInfo.second;
 
@@ -1169,17 +1389,16 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
 }
 
 /*!
+    \fn v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode)
+
     Get the \a property of \a object.  Returns an empty handle if the property doesn't exist.
 
     Only searches for real properties of \a object (including methods), not attached properties etc.
 */
-v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, v8::Handle<v8::String> property,
-                                                     QV8QObjectWrapper::RevisionMode revisionMode)
-{
-    return GetProperty(m_engine, object, 0, property, revisionMode);
-}
 
 /*
+    \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle<v8::Value> value, RevisionMode revisionMode)
+
     Set the \a property of \a object to \a value.
 
     Returns true if the property was "set" - even if this results in an exception being thrown -
@@ -1187,11 +1406,6 @@ v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, v8::Handle
 
     Only searches for real properties of \a object (including methods), not attached properties etc.
 */
-bool QV8QObjectWrapper::setProperty(QObject *object, v8::Handle<v8::String> property, 
-                                    v8::Handle<v8::Value> value, RevisionMode revisionMode)
-{
-    return SetProperty(m_engine, object, property, value, revisionMode);
-}
 
 namespace {
 struct CallArgs
@@ -1245,34 +1459,13 @@ static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnTy
     }
 }
 
-static int EnumType(const QMetaObject *meta, const QString &strname)
-{
-    QByteArray str = strname.toUtf8();
-    QByteArray scope;
-    QByteArray name;
-    int scopeIdx = str.lastIndexOf("::");
-    if (scopeIdx != -1) {
-        scope = str.left(scopeIdx);
-        name = str.mid(scopeIdx + 2);
-    } else { 
-        name = str;
-    }
-    for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
-        QMetaEnum m = meta->enumerator(i);
-        if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
-            return QVariant::Int;
-    }
-    return QVariant::Invalid;
-}
-
 /*!
     Returns the match score for converting \a actual to be of type \a conversionType.  A 
     zero score means "perfect match" whereas a higher score is worse.
 
     The conversion table is copied out of the QtScript callQtMethod() function.
 */
-static int MatchScore(v8::Handle<v8::Value> actual, int conversionType, 
-                      const QByteArray &conversionTypeName)
+static int MatchScore(v8::Handle<v8::Value> actual, int conversionType)
 {
     if (actual->IsNumber()) {
         switch (conversionType) {
@@ -1344,11 +1537,13 @@ static int MatchScore(v8::Handle<v8::Value> actual, int conversionType,
         case QMetaType::VoidStar:
         case QMetaType::QObjectStar:
             return 0;
-        default:
-            if (!conversionTypeName.endsWith('*'))
-                return 10;
-            else
+        default: {
+            const char *typeName = QMetaType::typeName(conversionType);
+            if (typeName && typeName[strlen(typeName) - 1] == '*')
                 return 0;
+            else
+                return 10;
+        }
         }
     } else if (actual->IsObject()) {
         v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
@@ -1403,33 +1598,37 @@ static QByteArray QMetaMethod_name(const QMetaMethod &m)
 /*!
 Returns the next related method, if one, or 0.
 */
-static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object, 
-                                                             const QDeclarativePropertyCache::Data *current, 
-                                                             QDeclarativePropertyCache::Data &dummy)
+static const QDeclarativePropertyData * RelatedMethod(QObject *object,
+                                                      const QDeclarativePropertyData *current,
+                                                      QDeclarativePropertyData &dummy)
 {
     QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
-    if (current->relatedIndex == -1)
+    if (!current->isOverload())
         return 0;
 
+    Q_ASSERT(!current->overrideIndexIsProperty);
+
     if (cache) {
-        return cache->method(current->relatedIndex);
+        return cache->method(current->overrideIndex);
     } else {
         const QMetaObject *mo = object->metaObject();
         int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
 
-        while (methodOffset > current->relatedIndex) {
+        while (methodOffset > current->overrideIndex) {
             mo = mo->superClass();
             methodOffset -= QMetaObject_methods(mo);
         }
 
-        QMetaMethod method = mo->method(current->relatedIndex);
+        QMetaMethod method = mo->method(current->overrideIndex);
         dummy.load(method);
         
         // Look for overloaded methods
         QByteArray methodName = QMetaMethod_name(method);
-        for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
+        for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
             if (methodName == QMetaMethod_name(mo->method(ii))) {
-                dummy.relatedIndex = ii;
+                dummy.setFlags(dummy.getFlags() | QDeclarativePropertyData::IsOverload);
+                dummy.overrideIndexIsProperty = 0;
+                dummy.overrideIndex = ii;
                 return &dummy;
             }
         }
@@ -1438,35 +1637,32 @@ static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object,
     }
 }
 
-static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyCache::Data &data, 
+static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyData &data,
                                          QV8Engine *engine, CallArgs &callArgs)
 {
-    if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
-
-        QMetaMethod m = object->metaObject()->method(data.coreIndex);
-        QList<QByteArray> argTypeNames = m.parameterTypes();
-        QVarLengthArray<int, 9> argTypes(argTypeNames.count());
-
-        // ### Cache
-        for (int ii = 0; ii < argTypeNames.count(); ++ii) {
-            argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
-            if (argTypes[ii] == QVariant::Invalid) 
-                argTypes[ii] = EnumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
-            if (argTypes[ii] == QVariant::Invalid) {
-                QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)));
-                v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-                return v8::Handle<v8::Value>();
-            }
+    if (data.hasArguments()) {
+
+        int *args = 0;
+        QVarLengthArray<int, 9> dummy;
+        QByteArray unknownTypeError;
+
+        args = QDeclarativePropertyCache::methodParameterTypes(object, data.coreIndex, dummy, 
+                                                               &unknownTypeError);
+
+        if (!args) {
+            QString typeName = QString::fromLatin1(unknownTypeError);
+            QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+            v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+            return v8::Handle<v8::Value>();
         }
 
-        if (argTypes.count() > callArgs.Length()) {
+        if (args[0] > callArgs.Length()) {
             QString error = QLatin1String("Insufficient arguments");
             v8::ThrowException(v8::Exception::Error(engine->toString(error)));
             return v8::Handle<v8::Value>();
         }
 
-        return CallMethod(object, data.coreIndex, data.propType, argTypes.count(), 
-                          argTypes.data(), engine, callArgs);
+        return CallMethod(object, data.coreIndex, data.propType, args[0], args + 1, engine, callArgs);
 
     } else {
 
@@ -1488,25 +1684,31 @@ Resolve the overloaded method to call.  The algorithm works conceptually like th
         If two or more overloads have the same match score, call the last one.  The match
         score is constructed by adding the matchScore() result for each of the parameters.
 */
-static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyCache::Data &data, 
+static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyData &data,
                                             QV8Engine *engine, CallArgs &callArgs)
 {
     int argumentCount = callArgs.Length();
 
-    const QDeclarativePropertyCache::Data *best = 0;
+    const QDeclarativePropertyData *best = 0;
     int bestParameterScore = INT_MAX;
     int bestMatchScore = INT_MAX;
 
-    QDeclarativePropertyCache::Data dummy;
-    const QDeclarativePropertyCache::Data *attempt = &data;
+    QDeclarativePropertyData dummy;
+    const QDeclarativePropertyData *attempt = &data;
 
     do {
-        QList<QByteArray> methodArgTypeNames;
-
-        if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
-            methodArgTypeNames = object->metaObject()->method(attempt->coreIndex).parameterTypes();
+        QVarLengthArray<int, 9> dummy;
+        int methodArgumentCount = 0;
+        int *methodArgTypes = 0;
+        if (attempt->hasArguments()) {
+            typedef QDeclarativePropertyCache PC;
+            int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0);
+            if (!args) // Must be an unknown argument
+                continue;
 
-        int methodArgumentCount = methodArgTypeNames.count();
+            methodArgumentCount = args[0];
+            methodArgTypes = args + 1;
+        }
 
         if (methodArgumentCount > argumentCount)
             continue; // We don't have sufficient arguments to call this method
@@ -1516,22 +1718,8 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativeP
             continue; // We already have a better option
 
         int methodMatchScore = 0;
-        QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
-
-        bool unknownArgument = false;
-        for (int ii = 0; ii < methodArgumentCount; ++ii) {
-            methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
-            if (methodArgTypes[ii] == QVariant::Invalid) 
-                methodArgTypes[ii] = EnumType(object->metaObject(), 
-                                              QString::fromLatin1(methodArgTypeNames.at(ii)));
-            if (methodArgTypes[ii] == QVariant::Invalid) {
-                unknownArgument = true;
-                break;
-            }
-            methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii], methodArgTypeNames.at(ii));
-        }
-        if (unknownArgument)
-            continue; // We don't understand all the parameters
+        for (int ii = 0; ii < methodArgumentCount; ++ii) 
+            methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]);
 
         if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
             best = attempt;
@@ -1548,7 +1736,7 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativeP
         return CallPrecise(object, *best, engine, callArgs);
     } else {
         QString error = QLatin1String("Unable to determine callable overload.  Candidates are:");
-        const QDeclarativePropertyCache::Data *candidate = &data;
+        const QDeclarativePropertyData *candidate = &data;
         while (candidate) {
             error += QLatin1String("\n    ") + 
                      QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
@@ -1644,11 +1832,11 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
         }
     }
 
-    QDeclarativePropertyCache::Data method;
+    QDeclarativePropertyData method;
 
     if (QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(object)->declarativeData)) {
         if (ddata->propertyCache) {
-            QDeclarativePropertyCache::Data *d = ddata->propertyCache->method(index);
+            QDeclarativePropertyData *d = ddata->propertyCache->method(index);
             if (!d) 
                 return v8::Undefined();
             method = *d;
@@ -1656,14 +1844,13 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
     }
 
     if (method.coreIndex == -1) {
-        QMetaMethod mm = object->metaObject()->method(index);
         method.load(object->metaObject()->method(index));
 
         if (method.coreIndex == -1)
             return v8::Undefined();
     }
 
-    if (method.flags & QDeclarativePropertyCache::Data::IsV8Function) {
+    if (method.isV8Function()) {
         v8::Handle<v8::Value> rv;
         v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
 
@@ -1680,7 +1867,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
     }
 
     CallArgs callArgs(argCount, &arguments);
-    if (method.relatedIndex == -1) {
+    if (!method.isOverload()) {
         return CallPrecise(object, method, resource->engine, callArgs);
     } else {
         return CallOverloaded(object, method, resource->engine, callArgs);
@@ -1688,7 +1875,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
 }
 
 MetaCallArgument::MetaCallArgument()
-: type(QVariant::Invalid), isObjectType(false)
+: type(QVariant::Invalid)
 {
 }
 
@@ -1700,22 +1887,22 @@ MetaCallArgument::~MetaCallArgument()
 void MetaCallArgument::cleanup()
 {
     if (type == QMetaType::QString) {
-        ((QString *)&data)->~QString();
-    } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
-        ((QVariant *)&data)->~QVariant();
-    } else if (type == qMetaTypeId<QScriptValue>()) {
-        ((QScriptValue *)&data)->~QScriptValue();
+        qstringPtr->~QString();
+    } else if (type == -1 || type == QMetaType::QVariant) {
+        qvariantPtr->~QVariant();
+    } else if (type == qMetaTypeId<QJSValue>()) {
+        qjsValuePtr->~QJSValue();
     } else if (type == qMetaTypeId<QList<QObject *> >()) {
-        ((QList<QObject *> *)&data)->~QList<QObject *>();
-    }
+        qlistPtr->~QList<QObject *>();
+    } 
 }
 
 void *MetaCallArgument::dataPtr()
 {
     if (type == -1)
-        return ((QVariant *)data)->data();
+        return qvariantPtr->data();
     else
-        return (void *)&data;
+        return (void *)&allocData;
 }
 
 void MetaCallArgument::initAsType(int callType)
@@ -1723,8 +1910,8 @@ void MetaCallArgument::initAsType(int callType)
     if (type != 0) { cleanup(); type = 0; }
     if (callType == 0) return;
 
-    if (callType == qMetaTypeId<QScriptValue>()) {
-        new (&data) QScriptValue();
+    if (callType == qMetaTypeId<QJSValue>()) {
+        qjsValuePtr = new (&allocData) QJSValue();
         type = callType;
     } else if (callType == QMetaType::Int ||
                callType == QMetaType::UInt ||
@@ -1733,23 +1920,23 @@ void MetaCallArgument::initAsType(int callType)
                callType == QMetaType::Float) {
         type = callType;
     } else if (callType == QMetaType::QObjectStar) {
-        *((QObject **)&data) = 0;
+        qobjectPtr = 0;
         type = callType;
     } else if (callType == QMetaType::QString) {
-        new (&data) QString();
+        qstringPtr = new (&allocData) QString();
         type = callType;
-    } else if (callType == qMetaTypeId<QVariant>()) {
+    } else if (callType == QMetaType::QVariant) {
         type = callType;
-        new (&data) QVariant();
+        qvariantPtr = new (&allocData) QVariant();
     } else if (callType == qMetaTypeId<QList<QObject *> >()) {
         type = callType;
-        new (&data) QList<QObject *>();
+        qlistPtr = new (&allocData) QList<QObject *>();
     } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
         type = callType;
-        new (&data) v8::Handle<v8::Value>();
+        handlePtr = new (&allocData) QDeclarativeV8Handle;
     } else {
         type = -1;
-        new (&data) QVariant(callType, (void *)0);
+        qvariantPtr = new (&allocData) QVariant(callType, (void *)0);
     }
 }
 
@@ -1757,63 +1944,63 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
 {
     if (type != 0) { cleanup(); type = 0; }
 
-    if (callType == qMetaTypeId<QScriptValue>()) {
-        new (&data) QScriptValue();
-        type = qMetaTypeId<QScriptValue>();
+    if (callType == qMetaTypeId<QJSValue>()) {
+        qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value)));
+        type = qMetaTypeId<QJSValue>();
     } else if (callType == QMetaType::Int) {
-        *((int *)&data) = int(value->Int32Value());
+        intValue = quint32(value->Int32Value());
         type = callType;
     } else if (callType == QMetaType::UInt) {
-        *((uint *)&data) = uint(value->Uint32Value());
+        intValue = quint32(value->Uint32Value());
         type = callType;
     } else if (callType == QMetaType::Bool) {
-        *((bool *)&data) = value->BooleanValue();
+        boolValue = value->BooleanValue();
         type = callType;
     } else if (callType == QMetaType::Double) {
-        *((double *)&data) = double(value->NumberValue());
+        doubleValue = double(value->NumberValue());
         type = callType;
     } else if (callType == QMetaType::Float) {
-        *((float *)&data) = float(value->NumberValue());
+        floatValue = float(value->NumberValue());
         type = callType;
     } else if (callType == QMetaType::QString) {
         if (value->IsNull() || value->IsUndefined())
-            new (&data) QString();
+            qstringPtr = new (&allocData) QString();
         else
-            new (&data) QString(engine->toString(value->ToString()));
+            qstringPtr = new (&allocData) QString(engine->toString(value->ToString()));
         type = callType;
     } else if (callType == QMetaType::QObjectStar) {
-        *((QObject **)&data) = engine->toQObject(value);
+        qobjectPtr = engine->toQObject(value);
         type = callType;
     } else if (callType == qMetaTypeId<QVariant>()) {
-        new (&data) QVariant(engine->toVariant(value, -1));
+        qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1));
         type = callType;
     } else if (callType == qMetaTypeId<QList<QObject*> >()) {
-        QList<QObject *> *list = new (&data) QList<QObject *>(); 
+        qlistPtr = new (&allocData) QList<QObject *>();
         if (value->IsArray()) {
             v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
             uint32_t length = array->Length();
             for (uint32_t ii = 0; ii < length; ++ii) 
-                list->append(engine->toQObject(array->Get(ii)));
+                qlistPtr->append(engine->toQObject(array->Get(ii)));
         } else {
-            list->append(engine->toQObject(value));
+            qlistPtr->append(engine->toQObject(value));
         }
         type = callType;
     } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
-        new (&data) v8::Handle<v8::Value>(value);
+        handlePtr = new (&allocData) QDeclarativeV8Handle(QDeclarativeV8Handle::fromHandle(value));
         type = callType;
     } else {
-        new (&data) QVariant();
+        qvariantPtr = new (&allocData) QVariant();
         type = -1;
 
-        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+        QDeclarativeEnginePrivate *ep = engine->engine() ? QDeclarativeEnginePrivate::get(engine->engine()) : 0;
         QVariant v = engine->toVariant(value, -1);
 
         if (v.userType() == callType) {
-            *((QVariant *)&data) = v;
+            *qvariantPtr = v;
         } else if (v.canConvert((QVariant::Type)callType)) {
-            *((QVariant *)&data) = v;
-            ((QVariant *)&data)->convert((QVariant::Type)callType);
-        } else if (const QMetaObject *mo = ep->rawMetaObjectForType(callType)) {
+            *qvariantPtr = v;
+            qvariantPtr->convert((QVariant::Type)callType);
+        } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) {
             QObject *obj = ep->toQObject(v);
             
             if (obj) {
@@ -1822,46 +2009,46 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
                 if (!objMo) obj = 0;
             }
 
-            *((QVariant *)&data) = QVariant(callType, &obj);
+            *qvariantPtr = QVariant(callType, &obj);
         } else {
-            *((QVariant *)&data) = QVariant(callType, (void *)0);
+            *qvariantPtr = QVariant(callType, (void *)0);
         }
     }
 }
 
 v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
 {
-    if (type == qMetaTypeId<QScriptValue>()) {
-        return v8::Undefined();
+    if (type == qMetaTypeId<QJSValue>()) {
+        return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
     } else if (type == QMetaType::Int) {
-        return v8::Integer::New(*((int *)&data));
+        return v8::Integer::New(int(intValue));
     } else if (type == QMetaType::UInt) {
-        return v8::Integer::NewFromUnsigned(*((uint *)&data));
+        return v8::Integer::NewFromUnsigned(intValue);
     } else if (type == QMetaType::Bool) {
-        return v8::Boolean::New(*((bool *)&data));
+        return v8::Boolean::New(boolValue);
     } else if (type == QMetaType::Double) {
-        return v8::Number::New(*((double *)&data));
+        return v8::Number::New(doubleValue);
     } else if (type == QMetaType::Float) {
-        return v8::Number::New(*((float *)&data));
+        return v8::Number::New(floatValue);
     } else if (type == QMetaType::QString) {
-        return engine->toString(*((QString *)&data));
+        return engine->toString(*qstringPtr);
     } else if (type == QMetaType::QObjectStar) {
-        QObject *object = *((QObject **)&data);
+        QObject *object = qobjectPtr;
         if (object)
             QDeclarativeData::get(object, true)->setImplicitDestructible();
         return engine->newQObject(object);
     } else if (type == qMetaTypeId<QList<QObject *> >()) {
         // XXX Can this be made more by using Array as a prototype and implementing
         // directly against QList<QObject*>?
-        QList<QObject *> &list = *(QList<QObject *>*)&data;
+        QList<QObject *> &list = *qlistPtr;
         v8::Local<v8::Array> array = v8::Array::New(list.count());
         for (int ii = 0; ii < list.count(); ++ii) 
             array->Set(ii, engine->newQObject(list.at(ii)));
         return array;
     } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
-        return *(v8::Handle<v8::Value>*)&data;
+        return handlePtr->toHandle();
     } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
-        QVariant value = *((QVariant *)&data);
+        QVariant value = *qvariantPtr;
         v8::Handle<v8::Value> rv = engine->fromVariant(value);
         if (QObject *object = engine->toQObject(rv)) 
             QDeclarativeData::get(object, true)->setImplicitDestructible();
@@ -1870,3 +2057,6 @@ v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
         return v8::Undefined();
     }
 }
+
+QT_END_NAMESPACE
+