Doc: Enabling Qt QML linking to Qt Quick.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
index 6729960..d7b6f70 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtQml module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** GNU Lesser General Public License Usage
-** 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.
+** 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.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** 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.
-**
-**
-**
-**
+** 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.
 **
 **
 ** $QT_END_LICENSE$
@@ -69,6 +69,7 @@
 #include <private/qdebugmessageservice_p.h>
 #include "qqmlincubator.h"
 #include <private/qv8profilerservice_p.h>
+#include <private/qqmlboundsignal_p.h>
 
 #include <QtCore/qstandardpaths.h>
 #include <QtCore/qsettings.h>
 #include <QtCore/qmetaobject.h>
 #include <QNetworkAccessManager>
 #include <QDebug>
-#include <QMetaObject>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qdir.h>
 #include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <private/qthread_p.h>
 #include <QtNetwork/qnetworkconfigmanager.h>
 
 #include <private/qobject_p.h>
+#include <private/qmetaobject_p.h>
 
 #include <private/qqmllocale_p.h>
 
+#include "qqmlbind_p.h"
+#include "qqmlconnections_p.h"
+#include "qqmltimer_p.h"
+
 #ifdef Q_OS_WIN // for %APPDATA%
 #include <qt_windows.h>
 #include <qlibrary.h>
@@ -101,22 +108,24 @@ QT_BEGIN_NAMESPACE
 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
 {
     QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
-    QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
+    QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
+    QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
 }
 
 /*!
-  \qmlclass QtObject QObject
+  \qmltype QtObject
+    \instantiates QObject
+  \inqmlmodule QtQuick 2
   \ingroup qml-utility-elements
-  \since 4.7
-  \brief The QtObject element is the most basic element in QML.
+  \brief A basic QML type
 
-  The QtObject element is a non-visual element which contains only the
+  The QtObject type is a non-visual element which contains only the
   objectName property.
 
   It can be useful to create a QtObject if you need an extremely
-  lightweight element to enclose a set of custom properties:
+  lightweight type to enclose a set of custom properties:
 
-  \snippet doc/src/snippets/qml/qtobject.qml 0
+  \snippet qml/qtobject.qml 0
 
   It can also be useful for C++ integration, as it is just a plain
   QObject. See the QObject documentation for further details.
@@ -160,20 +169,46 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
 */
 
 bool QQmlEnginePrivate::qml_debugging_enabled = false;
+bool QQmlEnginePrivate::s_designerMode = false;
 
+// these types are part of the QML language
 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
 {
     qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
-    qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
-    qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
-    qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
+    qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
+    qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
+    qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
+    qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
+}
+
+
+// These QtQuick types' implementation resides in the QtQml module
+void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
+{
+    qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
+    qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
+    qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
+}
+
+void QQmlEnginePrivate::defineQtQuick2Module()
+{
+    // register the base types into the QtQuick namespace
+    registerBaseTypes("QtQuick",2,0);
+
+    // register the QtQuick2 types which are implemented in the QtQml module.
+    registerQtQuick2Types("QtQuick",2,0);
+    qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
 }
 
-void QQmlEnginePrivate::defineModule()
+bool QQmlEnginePrivate::designerMode()
 {
-    registerBaseTypes("QtQuick", 2, 0);
-    qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
+    return s_designerMode;
+}
+
+void QQmlEnginePrivate::activateDesignerMode()
+{
+    s_designerMode = true;
 }
 
 
@@ -181,6 +216,7 @@ void QQmlEnginePrivate::defineModule()
     \class QQmlImageProviderBase
     \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
     \mainclass
+    \inmodule QtQml
 
     Image providers must be registered with the QML engine.  The only information the QML
     engine knows about image providers is the type of image data they provide.  To use an
@@ -200,7 +236,18 @@ void QQmlEnginePrivate::defineModule()
     \value Pixmap The Image Provider provides QPixmap images.
         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
     \value Texture The Image Provider provides QSGTextureProvider based images.
-        The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
+        The QQuickImageProvider::requestTexture() method will be called for all image requests.
+    \omitvalue Invalid
+*/
+
+/*!
+    \enum QQmlImageProviderBase::Flag
+
+    Defines specific requirements or features of this image provider.
+
+    \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
+        run in a separate thread, which allows the provider to spend as much time as needed
+        on producing the image without blocking the main thread.
 */
 
 /*! \internal */
@@ -215,7 +262,8 @@ QQmlImageProviderBase::~QQmlImageProviderBase()
 
 
 /*!
-\qmlclass Qt QQmlEnginePrivate
+\qmltype Qt
+    \instantiates QQmlEnginePrivate
   \ingroup qml-utility-elements
 \brief The QML global Qt object provides useful enums and functions from Qt.
 
@@ -241,23 +289,33 @@ Text {
 \section1 Enums
 
 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
-the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
+the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
 
 
 \section1 Types
+
 The Qt object also contains helper functions for creating objects of specific
 data types. This is primarily useful when setting the properties of an item
 when the property has one of the following types:
-
 \list
-\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
 \li \c point - use \l{Qt::point()}{Qt.point()}
 \li \c size - use \l{Qt::size()}{Qt.size()}
+\endlist
+
+If the QtQuick module has been imported, the following helper functions for
+creating objects of specific data types are also available for clients to use:
+\list
+\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
+\li \c font - use \l{Qt::font()}{Qt.font()}
+\li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
+\li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
+\li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
+\li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
 \endlist
 
-There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
+There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
 
 \section1 Date/Time Formatters
 
@@ -274,16 +332,32 @@ The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTim
 
 \section1 Dynamic Object Creation
 The following functions on the global object allow you to dynamically create QML
-items from files or strings. See \l{Dynamic Object Management in QML} for an overview
+items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
 of their use.
 
 \list
     \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
     \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
 \endlist
-*/
 
 
+\section1 Other Functions
+
+The following functions are also on the Qt object.
+
+\list
+    \li \l{Qt::quit()}{Qt.quit()}
+    \li \l{Qt::md5()}{Qt.md5(string)}
+    \li \l{Qt::btoa()}{string Qt.btoa(string)}
+    \li \l{Qt::atob()}{string Qt.atob(string)}
+    \li \l{Qt::binding()}{object Qt.binding(function)}
+    \li \l{Qt::locale()}{object Qt.locale()}
+    \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
+    \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
+    \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
+\endlist
+*/
+
 /*!
     \qmlproperty object Qt::application
     \since QtQuick 1.1
@@ -325,19 +399,15 @@ of their use.
                         from right to left.
     \endlist
 
-    \row
-    \li \c application.inputPanel
-    \li
-    This read-only property allows access to application's QInputPanel object
-    and all its properties and slots. See the QInputPanel documentation for
-    further details. Deprecated in favor of Qt.InputMethod
     \endtable
 
     The following example uses the \c application object to indicate
     whether the application is currently active:
 
-    \snippet doc/src/snippets/qml/application.qml document
+    \snippet qml/application.qml document
+*/
 
+/*!
     \qmlproperty object Qt::inputMethod
     \since QtQuick 2.0
 
@@ -378,7 +448,7 @@ the same object as is returned from the Qt.include() call.
 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
 : propertyCapture(0), rootContext(0), isDebugging(false),
   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
-  cleanup(0), erroredBindings(0), inProgressCreations(0), 
+  cleanup(0), erroredBindings(0), inProgressCreations(0),
   workerScriptEngine(0), activeVME(0),
   networkAccessManager(0), networkAccessManagerFactory(0),
   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
@@ -408,16 +478,12 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
     delete rootContext;
     rootContext = 0;
 
-    for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
-        (*iter)->release();
     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
         (*iter)->release();
     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
         (*iter)->release();
-    for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
-        delete (*iter)->qobjectApi;
-        delete *iter;
-    }
+    for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
+        iter.value()->isRegisteredWithEngine = false;
 }
 
 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
@@ -429,6 +495,15 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
             d->context->destroy();
             d->context = 0;
         }
+
+        // Mark this object as in the process of deletion to
+        // prevent it resolving in bindings
+        QQmlData::markAsDeleted(o);
+
+        // Disconnect the notifiers now - during object destruction this would be too late, since
+        // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
+        // get the metaobject anymore.
+        d->disconnectNotifiers();
     }
 }
 
@@ -442,18 +517,149 @@ void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p
     static_cast<QQmlData *>(d)->parentChanged(o, p);
 }
 
-void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
+class QQmlThreadNotifierProxyObject : public QObject
 {
-    static_cast<QQmlData *>(d)->objectNameChanged(o);
-}
+public:
+    QPointer<QObject> target;
+
+    virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
+        if (!target)
+            return -1;
+
+        QMetaMethod method = target->metaObject()->method(methodIndex);
+        Q_ASSERT(method.methodType() == QMetaMethod::Signal);
+        int signalIndex = QMetaObjectPrivate::signalIndex(method);
+        QQmlData *ddata = QQmlData::get(target, false);
+        QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
+        if (ep) QQmlNotifier::emitNotify(ep, a);
 
-void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
+        delete this;
+
+        return -1;
+    }
+};
+
+void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
 {
     QQmlData *ddata = QQmlData::get(object, false);
     if (!ddata) return; // Probably being deleted
 
-    QQmlNotifierEndpoint *ep = ddata->notify(index);
-    if (ep) QQmlNotifier::emitNotify(ep);
+    // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
+    // that they're exposed to.  However, to make writing "worker objects" that calculate data
+    // in a separate thread easier, QML allows a QObject that lives in the same thread as the
+    // QQmlEngine to emit signals from a different thread.  These signals are then automatically
+    // marshalled back onto the QObject's thread and handled by QML from there.  This is tested
+    // by the qqmlecmascript::threadSignal() autotest.
+    if (ddata->notifyList &&
+        QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
+
+        if (!QObjectPrivate::get(object)->threadData->thread)
+            return;
+
+        QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
+        QList<QByteArray> parameterTypes = m.parameterTypes();
+
+        int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
+        void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
+
+        types[0] = 0; // return type
+        args[0] = 0; // return value
+
+        for (int ii = 0; ii < parameterTypes.count(); ++ii) {
+            const QByteArray &typeName = parameterTypes.at(ii);
+            if (typeName.endsWith('*'))
+                types[ii + 1] = QMetaType::VoidStar;
+            else
+                types[ii + 1] = QMetaType::type(typeName);
+
+            if (!types[ii + 1]) {
+                qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
+                         "(Make sure '%s' is registered using qRegisterMetaType().)",
+                         typeName.constData(), typeName.constData());
+                free(types);
+                free(args);
+                return;
+            }
+
+            args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
+        }
+
+        QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
+                                                parameterTypes.count() + 1, types, args);
+
+        QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
+        mpo->target = object;
+        mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
+        QCoreApplication::postEvent(mpo, ev);
+
+    } else {
+        QQmlNotifierEndpoint *ep = ddata->notify(index);
+        if (ep) QQmlNotifier::emitNotify(ep, a);
+    }
+}
+
+int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
+{
+    return static_cast<QQmlData *>(d)->endpointCount(index);
+}
+
+bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
+{
+    return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
+}
+
+int QQmlData::endpointCount(int index)
+{
+    int count = 0;
+    QQmlNotifierEndpoint *ep = notify(index);
+    if (!ep)
+        return count;
+    ++count;
+    while (ep->next) {
+        ++count;
+        ep = ep->next;
+    }
+    return count;
+}
+
+void QQmlData::markAsDeleted(QObject *o)
+{
+    QQmlData::setQueuedForDeletion(o);
+
+    QObjectPrivate *p = QObjectPrivate::get(o);
+    for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
+        QQmlData::markAsDeleted(*it);
+    }
+}
+
+void QQmlData::setQueuedForDeletion(QObject *object)
+{
+    if (object) {
+        if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
+            if (!priv->wasDeleted && priv->declarativeData) {
+                QQmlData *ddata = QQmlData::get(object, false);
+                if (ddata->ownContext && ddata->context)
+                    ddata->context->emitDestruction();
+                ddata->isQueuedForDeletion = true;
+            }
+        }
+    }
+}
+
+void QQmlData::flushPendingBindingImpl(int coreIndex)
+{
+    clearPendingBindingBit(coreIndex);
+
+    // Find the binding
+    QQmlAbstractBinding *b = bindings;
+    while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
+        b = b->nextBinding();
+
+    if (b) {
+        b->m_mePtr = 0;
+        b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+                            QQmlPropertyPrivate::DontRemoveBinding);
+    }
 }
 
 void QQmlEnginePrivate::init()
@@ -462,20 +668,20 @@ void QQmlEnginePrivate::init()
 
     static bool firstTime = true;
     if (firstTime) {
-        qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
+        qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
+        registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
 
+        QQmlData::init();
         firstTime = false;
     }
 
-    qRegisterMetaType<QVariant>("QVariant");
-    qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
-    qRegisterMetaType<QJSValue>("QJSValue");
-    qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
-    qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
-    qRegisterMetaType<QList<int> >("QList<int>");
-    qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
-
-    QQmlData::init();
+    qRegisterMetaType<QVariant>();
+    qRegisterMetaType<QQmlScriptString>();
+    qRegisterMetaType<QJSValue>();
+    qRegisterMetaType<QQmlComponent::Status>();
+    qRegisterMetaType<QList<QObject*> >();
+    qRegisterMetaType<QList<int> >();
+    qRegisterMetaType<QQmlV8Handle>();
 
     v8engine()->setEngine(q);
 
@@ -492,9 +698,10 @@ void QQmlEnginePrivate::init()
     }
 
     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
-    offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
-                         QDir::separator() + QLatin1String("QML") +
-                         QDir::separator() + QLatin1String("OfflineStorage");
+    if (!dataLocation.isEmpty())
+        offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
+                           + QDir::separator() + QLatin1String("QML")
+                           + QDir::separator() + QLatin1String("OfflineStorage");
 }
 
 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
@@ -507,7 +714,8 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
 
 /*!
   \class QQmlEngine
-  \since 4.7
+  \since 5.0
+  \inmodule QtQml
   \brief The QQmlEngine class provides an environment for instantiating QML components.
   \mainclass
 
@@ -533,7 +741,9 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
   In this case, the Text item will be created in the engine's
   \l {QQmlEngine::rootContext()}{root context}.
 
-  \sa QQmlComponent QQmlContext
+  Note that the QtQuick 1 version is called QDeclarativeEngine.
+
+  \sa QQmlComponent, QQmlContext
 */
 
 /*!
@@ -560,24 +770,18 @@ QQmlEngine::~QQmlEngine()
         QQmlEngineDebugService::instance()->remEngine(this);
     }
 
-    // if we are the parent of any of the qobject module api instances,
-    // we need to remove them from our internal list, in order to prevent
-    // a segfault in engine private dtor.
-    QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
-    QObject *currQObjectApi = 0;
-    QQmlMetaType::ModuleApiInstance *currInstance = 0;
-    foreach (const QQmlMetaType::ModuleApi &key, keys) {
-        currInstance = d->moduleApiInstances.value(key);
-        currQObjectApi = currInstance->qobjectApi;
-        if (this->children().contains(currQObjectApi)) {
-            delete currQObjectApi;
-            delete currInstance;
-            d->moduleApiInstances.remove(key);
-        }
-    }
+    // Emit onDestruction signals for the root context before
+    // we destroy the contexts, engine, Singleton Types etc. that
+    // may be required to handle the destruction signal.
+    QQmlContextData::get(rootContext())->emitDestruction();
 
-    // ensure we clean up QObjects with JS ownership
-    d->v8engine()->gc();
+    // clean up all singleton type instances which we own.
+    // we do this here and not in the private dtor since otherwise a crash can
+    // occur (if we are the QObject parent of the QObject singleton instance)
+    // XXX TODO: performance -- store list of singleton types separately?
+    QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
+    foreach (QQmlType *currType, singletonTypes)
+        currType->singletonInstanceInfo()->destroy(this);
 
     if (d->incubationController)
         d->incubationController->d = 0;
@@ -594,9 +798,19 @@ QQmlEngine::~QQmlEngine()
 /*!
   Clears the engine's internal component cache.
 
-  Normally the QQmlEngine caches components loaded from qml
-  files.  This method clears this cache and forces the component to be
-  reloaded.
+  This function causes the property metadata of all components previously
+  loaded by the engine to be destroyed.  All previously loaded components and
+  the property bindings for all extant objects created from those components will
+  cease to function.
+
+  This function returns the engine to a state where it does not contain any loaded
+  component data.  This may be useful in order to reload a smaller subset of the
+  previous component set, or to load a new version of a previously loaded component.
+
+  Once the component cache has been cleared, components must be loaded before
+  any new objects can be created.
+
+  \sa trimComponentCache()
  */
 void QQmlEngine::clearComponentCache()
 {
@@ -605,6 +819,24 @@ void QQmlEngine::clearComponentCache()
 }
 
 /*!
+  Trims the engine's internal component cache.
+
+  This function causes the property metadata of any loaded components which are
+  not currently in use to be destroyed.
+
+  A component is considered to be in use if there are any extant instances of
+  the component itself, any instances of other components that use the component,
+  or any objects instantiated by any of those components.
+
+  \sa clearComponentCache()
+ */
+void QQmlEngine::trimComponentCache()
+{
+    Q_D(QQmlEngine);
+    d->typeLoader.trimCache();
+}
+
+/*!
   Returns the engine's root context.
 
   The root context is automatically created by the QQmlEngine.
@@ -649,7 +881,7 @@ QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
     return d->networkAccessManagerFactory;
 }
 
-void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) 
+void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
 {
     if (activeVME) {
         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
@@ -682,7 +914,7 @@ QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
 
 /*!
   Returns a common QNetworkAccessManager which can be used by any QML
-  element instantiated by this engine.
+  type instantiated by this engine.
 
   If a QQmlNetworkAccessManagerFactory has been set and a
   QNetworkAccessManager has not yet been created, the
@@ -806,14 +1038,6 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
 }
 
 /*!
-  Attempt to free unused memory.
-*/
-void QQmlEngine::collectGarbage()
-{
-    QV8Engine::gc();
-}
-
-/*!
   Returns the QQmlContext for the \a object, or 0 if no
   context has been set.
 
@@ -875,10 +1099,13 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
 
   \value JavaScriptOwnership The object is owned by JavaScript.
   When the object is returned to QML as the return value of a method
-  call or property access, QML will delete the object if there are no
-  remaining JavaScript references to it and it has no
-  QObject::parent().  This option is similar to
-  QScriptEngine::ScriptOwnership.
+  call or property access, QML will track it, and delete the object
+  if there are no remaining JavaScript references to it and it has no
+  QObject::parent().  An object tracked by one QQmlEngine
+  will be deleted during that QQmlEngine's destructor, and thus
+  JavaScript references between objects with JavaScriptOwnership from
+  two different engines will not be valid after the deletion of one of
+  those engines.  This option is similar to QScriptEngine::ScriptOwnership.
 
   Generally an application doesn't need to set an object's ownership
   explicitly.  QML uses a heuristic to set the default object
@@ -890,8 +1117,10 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
   have been transferred to the C++ caller.
 
   Objects not-created by QML have CppOwnership by default.  The
-  exception to this is objects returned from a C++ method call.  The
-  ownership of these objects is passed to JavaScript.
+  exception to this is objects returned from C++ method calls; in these cases,
+  the ownership of the returned objects will be set to JavaScriptOwnerShip.
+  Note this applies only to explicit invocations of Q_INVOKABLE methods or slots,
+  and not to property getter invocations.
 
   Calling setObjectOwnership() overrides the default ownership
   heuristic used by QML.
@@ -931,7 +1160,7 @@ QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
 bool QQmlEngine::event(QEvent *e)
 {
     Q_D(QQmlEngine);
-    if (e->type() == QEvent::User) 
+    if (e->type() == QEvent::User)
         d->doDeleteInEngineThread();
 
     return QJSEngine::event(e);
@@ -952,7 +1181,7 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
 {
     QQmlData *data = QQmlData::get(object);
 
-    if (data && data->deferredComponent) {
+    if (data && data->compiledData && data->deferredIdx) {
         QQmlObjectCreatingProfiler prof;
         if (prof.enabled) {
             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
@@ -966,8 +1195,9 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
         QQmlComponentPrivate::ConstructionState state;
         QQmlComponentPrivate::beginDeferred(ep, object, &state);
 
-        data->deferredComponent->release();
-        data->deferredComponent = 0;
+        // Release the reference for the deferral action (we still have one from construction)
+        data->compiledData->release();
+        data->compiledData = 0;
 
         QQmlComponentPrivate::complete(ep, &state);
     }
@@ -1020,10 +1250,11 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
     return qmlAttachedPropertiesObjectById(*idCache, object, create);
 }
 
-QQmlDebuggingEnabler::QQmlDebuggingEnabler()
+QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
 {
 #ifndef QQML_NO_DEBUG_PROTOCOL
-    if (!QQmlEnginePrivate::qml_debugging_enabled) {
+    if (!QQmlEnginePrivate::qml_debugging_enabled
+            && printWarning) {
         qDebug("QML debugging is enabled. Only use this in a safe environment.");
     }
     QQmlEnginePrivate::qml_debugging_enabled = true;
@@ -1037,7 +1268,6 @@ public:
     ~QQmlDataExtended();
 
     QHash<int, QObject *> attachedProperties;
-    QQmlNotifier objectNameNotifier;
 };
 
 QQmlDataExtended::QQmlDataExtended()
@@ -1070,13 +1300,13 @@ void QQmlData::NotifyList::layout()
         QQmlNotifierEndpoint **old = notifies;
         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
-        const int memsetSize = (maximumTodoIndex - notifiesSize + 1) * 
+        const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
                                sizeof(QQmlNotifierEndpoint*);
         memset(notifies + notifiesSize, 0, memsetSize);
 
         if (notifies != old) {
             for (int ii = 0; ii < notifiesSize; ++ii)
-                if (notifies[ii]) 
+                if (notifies[ii])
                     notifies[ii]->prev = &notifies[ii];
         }
 
@@ -1122,10 +1352,28 @@ void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
     }
 }
 
-QQmlNotifier *QQmlData::objectNameNotifier() const
+/*
+    index MUST in the range returned by QObjectPrivate::signalIndex()
+    This is different than the index returned by QMetaMethod::methodIndex()
+*/
+bool QQmlData::signalHasEndpoint(int index)
+{
+    return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
+}
+
+void QQmlData::disconnectNotifiers()
 {
-    if (!extendedData) extendedData = new QQmlDataExtended;
-    return &extendedData->objectNameNotifier;
+    if (notifyList) {
+        while (notifyList->todo)
+            notifyList->todo->disconnect();
+        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
+            while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
+                ep->disconnect();
+        }
+        free(notifyList->notifies);
+        free(notifyList);
+        notifyList = 0;
+    }
 }
 
 QHash<int, QObject *> *QQmlData::attachedProperties() const
@@ -1136,9 +1384,6 @@ QHash<int, QObject *> *QQmlData::attachedProperties() const
 
 void QQmlData::destroyed(QObject *object)
 {
-    if (deferredComponent)
-        deferredComponent->release();
-
     if (nextContextObject)
         nextContextObject->prevContextObject = prevContextObject;
     if (prevContextObject)
@@ -1146,13 +1391,56 @@ void QQmlData::destroyed(QObject *object)
 
     QQmlAbstractBinding *binding = bindings;
     while (binding) {
-        QQmlAbstractBinding *next = binding->m_nextBinding;
-        binding->m_prevBinding = 0;
-        binding->m_nextBinding = 0;
+        QQmlAbstractBinding *next = binding->nextBinding();
+        binding->setAddedToObject(false);
+        binding->setNextBinding(0);
         binding->destroy();
         binding = next;
     }
 
+    if (compiledData) {
+        compiledData->release();
+        compiledData = 0;
+    }
+
+    QQmlAbstractBoundSignal *signalHandler = signalHandlers;
+    while (signalHandler) {
+        if (signalHandler->isEvaluating()) {
+            // The object is being deleted during signal handler evaluation.
+            // This will cause a crash due to invalid memory access when the
+            // evaluation has completed.
+            // Abort with a friendly message instead.
+            QString locationString;
+            QQmlBoundSignalExpression *expr = signalHandler->expression();
+            if (expr) {
+                QString fileName = expr->sourceFile();
+                if (fileName.isEmpty())
+                    fileName = QStringLiteral("<Unknown File>");
+                locationString.append(fileName);
+                locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
+                QString source = expr->expression();
+                if (source.size() > 100) {
+                    source.truncate(96);
+                    source.append(QStringLiteral(" ..."));
+                }
+                locationString.append(source);
+            } else {
+                locationString = QStringLiteral("<Unknown Location>");
+            }
+            qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
+                   "Most likely the object was deleted synchronously (use QObject::deleteLater() "
+                   "instead), or the application is running a nested event loop.\n"
+                   "This behavior is NOT supported!\n"
+                   "%s", object, qPrintable(locationString));
+        }
+
+        QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
+        signalHandler->m_prevSignal = 0;
+        signalHandler->m_nextSignal = 0;
+        delete signalHandler;
+        signalHandler = next;
+    }
+
     if (bindingBits)
         free(bindingBits);
 
@@ -1168,109 +1456,87 @@ void QQmlData::destroyed(QObject *object)
         guard->objectDestroyed(object);
     }
 
-    if (notifyList) {
-        while (notifyList->todo)
-            notifyList->todo->disconnect();
-        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
-            while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
-                ep->disconnect();
-        }
-        free(notifyList->notifies);
-        free(notifyList);
-    }
+    disconnectNotifiers();
 
     if (extendedData)
         delete extendedData;
 
-    v8object.Clear(); // The WeakReference handler will clean the actual handle
+    // Dispose the handle.
+    // We don't simply clear it (and wait for next gc cycle to dispose
+    // via the weak qobject reference callback) as this affects the
+    // outcomes of v8's gc statistical analysis heuristics, which can
+    // cause unnecessary growth of the old pointer space js heap area.
+    qPersistentDispose(v8object);
 
     if (ownMemory)
         delete this;
 }
 
-void QQmlData::parentChanged(QObject *object, QObject *parent)
-{
-    Q_UNUSED(object);
-    Q_UNUSED(parent);
-}
+DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
 
-void QQmlData::objectNameChanged(QObject *)
+void QQmlData::parentChanged(QObject *object, QObject *parent)
 {
-    if (extendedData) objectNameNotifier()->notify();
-}
+    if (parentTest()) {
+        if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
+            QString on;
+            QString pn;
 
-bool QQmlData::hasBindingBit(int bit) const
-{
-    if (bindingBitsSize > bit)
-        return bindingBits[bit / 32] & (1 << (bit % 32));
-    else
-        return false;
-}
+            { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
+            { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
 
-void QQmlData::clearBindingBit(int bit)
-{
-    if (bindingBitsSize > bit)
-        bindingBits[bit / 32] &= ~(1 << (bit % 32));
+            qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
+                   "User code is attempting to change it to %s.\n"
+                   "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
+        }
+    }
 }
 
-void QQmlData::setBindingBit(QObject *obj, int bit)
+static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
 {
-    if (bindingBitsSize <= bit) {
-        int props = obj->metaObject()->propertyCount();
-        Q_ASSERT(bit < props);
+    if (data->bindingBitsSize <= bit) {
+        int props = QQmlMetaObject(obj).propertyCount();
+        Q_ASSERT(bit < 2 * props);
 
-        int arraySize = (props + 31) / 32;
-        int oldArraySize = bindingBitsSize / 32;
+        int arraySize = (2 * props + 31) / 32;
+        int oldArraySize = data->bindingBitsSize / 32;
 
-        bindingBits = (quint32 *)realloc(bindingBits,
-                                         arraySize * sizeof(quint32));
+        data->bindingBits = (quint32 *)realloc(data->bindingBits,
+                                               arraySize * sizeof(quint32));
 
-        memset(bindingBits + oldArraySize,
+        memset(data->bindingBits + oldArraySize,
                0x00,
                sizeof(quint32) * (arraySize - oldArraySize));
 
-        bindingBitsSize = arraySize * 32;
+        data->bindingBitsSize = arraySize * 32;
     }
 
-    bindingBits[bit / 32] |= (1 << (bit % 32));
+    data->bindingBits[bit / 32] |= (1 << (bit % 32));
 }
 
-QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
+static void QQmlData_clearBit(QQmlData *data, int bit)
 {
-    if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
-        if (url.authority().isEmpty())
-            return QLatin1Char(':') + url.path();
-        return QString();
-    }
-    return url.toLocalFile();
+    if (data->bindingBitsSize > bit)
+        data->bindingBits[bit / 32] &= ~(1 << (bit % 32));
 }
 
-
-static QString toLocalFile(const QString &url)
+void QQmlData::clearBindingBit(int coreIndex)
 {
-    if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
-        return QString();
-
-    QString file = url.mid(7);
-
-    //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
-
-    // magic for drives on windows
-    if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
-        file.remove(0, 1);
+    QQmlData_clearBit(this, coreIndex * 2);
+}
 
-    return file;
+void QQmlData::setBindingBit(QObject *obj, int coreIndex)
+{
+    QQmlData_setBit(this, obj, coreIndex * 2);
 }
 
-QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
+void QQmlData::clearPendingBindingBit(int coreIndex)
 {
-    if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
-        if (url.length() > 4)
-            return QLatin1Char(':') + url.mid(4);
-        return QString();
-    }
+    QQmlData_clearBit(this, coreIndex * 2 + 1);
+}
 
-    return toLocalFile(url);
+void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
+{
+    QQmlData_setBit(this, obj, coreIndex * 2 + 1);
 }
 
 void QQmlEnginePrivate::sendQuit()
@@ -1284,7 +1550,9 @@ void QQmlEnginePrivate::sendQuit()
 
 static void dumpwarning(const QQmlError &error)
 {
-    qWarning().nospace() << qPrintable(error.toString());
+    QMessageLogger(error.url().toString().toLatin1().constData(),
+                   error.line(), 0).warning().nospace()
+            << qPrintable(error.toString());
 }
 
 static void dumpwarning(const QList<QQmlError> &errors)
@@ -1309,6 +1577,12 @@ void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
         dumpwarning(errors);
 }
 
+void QQmlEnginePrivate::warning(QQmlDelayedError *error)
+{
+    Q_Q(QQmlEngine);
+    warning(error->error(q));
+}
+
 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
 {
     if (engine)
@@ -1325,6 +1599,14 @@ void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &erro
         dumpwarning(error);
 }
 
+void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
+{
+    if (engine)
+        QQmlEnginePrivate::get(engine)->warning(error);
+    else
+        dumpwarning(error->error(0));
+}
+
 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
 {
     if (engine)
@@ -1378,7 +1660,13 @@ void QQmlEnginePrivate::dereferenceScarceResources()
 /*!
   Adds \a path as a directory where the engine searches for
   installed modules in a URL-based directory structure.
-  The \a path may be a local filesystem directory or a URL.
+
+  The \a path may be a local filesystem directory, a
+  \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
+  \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
+
+  The \a path will be converted into canonical form before it
+  is added to the import path list.
 
   The newly added \a path will be first in the importPathList().
 
@@ -1401,10 +1689,10 @@ void QQmlEngine::addImportPath(const QString& path)
   type version mapping and possibly QML extensions plugins.
 
   By default, the list contains the directory of the application executable,
-  paths specified in the \c QML_IMPORT_PATH environment variable,
-  and the builtin \c ImportsPath from QLibraryInfo.
+  paths specified in the \c QML2_IMPORT_PATH environment variable,
+  and the builtin \c Qml2ImportsPath from QLibraryInfo.
 
-  \sa addImportPath() setImportPathList()
+  \sa addImportPath(), setImportPathList()
 */
 QStringList QQmlEngine::importPathList() const
 {
@@ -1417,10 +1705,10 @@ QStringList QQmlEngine::importPathList() const
   installed modules in a URL-based directory structure.
 
   By default, the list contains the directory of the application executable,
-  paths specified in the \c QML_IMPORT_PATH environment variable,
-  and the builtin \c ImportsPath from QLibraryInfo.
+  paths specified in the \c QML2_IMPORT_PATH environment variable,
+  and the builtin \c Qml2ImportsPath from QLibraryInfo.
 
-  \sa importPathList() addImportPath()
+  \sa importPathList(), addImportPath()
   */
 void QQmlEngine::setImportPathList(const QStringList &paths)
 {
@@ -1454,7 +1742,7 @@ void QQmlEngine::addPluginPath(const QString& path)
   By default, the list contains only \c .,  i.e. the engine searches
   in the directory of the \c qmldir file itself.
 
-  \sa addPluginPath() setPluginPathList()
+  \sa addPluginPath(), setPluginPathList()
 */
 QStringList QQmlEngine::pluginPathList() const
 {
@@ -1470,7 +1758,7 @@ QStringList QQmlEngine::pluginPathList() const
   By default, the list contains only \c .,  i.e. the engine searches
   in the directory of the \c qmldir file itself.
 
-  \sa pluginPathList() addPluginPath()
+  \sa pluginPathList(), addPluginPath()
   */
 void QQmlEngine::setPluginPathList(const QStringList &paths)
 {
@@ -1489,32 +1777,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths)
 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
 {
     Q_D(QQmlEngine);
-    return d->importDatabase.importPlugin(filePath, uri, errors);
-}
-
-/*!
-  Imports the plugin named \a filePath with the \a uri provided.
-  Returns true if the plugin was successfully imported; otherwise returns false.
-
-  On failure and if non-null, *\a errorString will be set to a message describing the failure.
-
-  The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
-*/
-bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
-{
-    Q_D(QQmlEngine);
-    QList<QQmlError> errors;
-    bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
-    if (!errors.isEmpty()) {
-        QString builtError;
-        for (int i = 0; i < errors.size(); ++i) {
-            builtError = QString(QLatin1String("%1\n        %2"))
-                    .arg(builtError)
-                    .arg(errors.at(i).toString());
-        }
-        *errorString = builtError;
-    }
-    return retn;
+    return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
 }
 
 /*!
@@ -1546,21 +1809,6 @@ QString QQmlEngine::offlineStoragePath() const
     return d->offlineStoragePath;
 }
 
-static void voidptr_destructor(void *v)
-{
-    void **ptr = (void **)v;
-    delete ptr;
-}
-
-static void *voidptr_constructor(const void *v)
-{
-    if (!v) {
-        return new void*;
-    } else {
-        return new void*(*(void **)v);
-    }
-}
-
 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
 {
     Q_Q(QQmlEngine);
@@ -1665,7 +1913,7 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
     if (overloadError) {
         if (hasCopied) raw->release();
 
-        error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
+        error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
         return 0;
     }
 
@@ -1680,22 +1928,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
     return raw;
 }
 
-QQmlMetaType::ModuleApiInstance *
-QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
-{
-    Locker locker(this);
-
-    QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
-    if (!a) {
-        a = new QQmlMetaType::ModuleApiInstance;
-        a->scriptCallback = module.script;
-        a->qobjectCallback = module.qobject;
-        moduleApiInstances.insert(module, a);
-    }
-
-    return a;
-}
-
 bool QQmlEnginePrivate::isQObject(int t)
 {
     Locker locker(this);
@@ -1741,56 +1973,118 @@ int QQmlEnginePrivate::listType(int t) const
         return QQmlMetaType::listType(t);
 }
 
-const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
+QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
+{
+    Locker locker(this);
+    QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
+    if (iter != m_compositeTypes.end()) {
+        return QQmlMetaObject((*iter)->rootPropertyCache);
+    } else {
+        QQmlType *type = QQmlMetaType::qmlType(t);
+        return QQmlMetaObject(type?type->baseMetaObject():0);
+    }
+}
+
+QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
+{
+    Locker locker(this);
+    QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
+    if (iter != m_compositeTypes.end()) {
+        return QQmlMetaObject((*iter)->rootPropertyCache);
+    } else {
+        QQmlType *type = QQmlMetaType::qmlType(t);
+        return QQmlMetaObject(type?type->metaObject():0);
+    }
+}
+
+QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
 {
     Locker locker(this);
     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
     if (iter != m_compositeTypes.end()) {
-        return (*iter)->root;
+        return (*iter)->rootPropertyCache;
     } else {
         QQmlType *type = QQmlMetaType::qmlType(t);
-        return type?type->baseMetaObject():0;
+        locker.unlock();
+        return type?cache(type->metaObject()):0;
     }
 }
 
-const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
+QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
 {
     Locker locker(this);
     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
     if (iter != m_compositeTypes.end()) {
-        return (*iter)->root;
+        return (*iter)->rootPropertyCache;
     } else {
         QQmlType *type = QQmlMetaType::qmlType(t);
-        return type?type->metaObject():0;
+        locker.unlock();
+        return type?cache(type->baseMetaObject()):0;
     }
 }
 
 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
 {
-    QByteArray name = data->root->className();
+    QByteArray name = data->rootPropertyCache->className();
 
     QByteArray ptr = name + '*';
     QByteArray lst = "QQmlListProperty<" + name + '>';
 
-    int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
-                                           voidptr_constructor);
-    int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
-                                           voidptr_constructor);
-
-    data->addref();
+    int ptr_type = QMetaType::registerNormalizedType(ptr,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Delete,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Create,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
+                                                     sizeof(QObject*),
+                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
+                                                     0);
+    int lst_type = QMetaType::registerNormalizedType(lst,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Delete,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Create,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
+                                                     sizeof(QQmlListProperty<QObject>),
+                                                     static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
+                                                     static_cast<QMetaObject*>(0));
+
+    data->metaTypeId = ptr_type;
+    data->listMetaTypeId = lst_type;
+    data->isRegisteredWithEngine = true;
 
     Locker locker(this);
     m_qmlLists.insert(lst_type, ptr_type);
+    // The QQmlCompiledData is not referenced here, but it is removed from this
+    // hash in the QQmlCompiledData destructor
     m_compositeTypes.insert(ptr_type, data);
 }
 
-bool QQml_isFileCaseCorrect(const QString &fileName)
+void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
+{
+    int ptr_type = data->metaTypeId;
+    int lst_type = data->listMetaTypeId;
+
+    Locker locker(this);
+    m_qmlLists.remove(lst_type);
+    m_compositeTypes.remove(ptr_type);
+}
+
+bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
+{
+    return typeLoader.isTypeLoaded(url);
+}
+
+bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
+{
+    return typeLoader.isScriptLoaded(url);
+}
+
+bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
 {
 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
     QFileInfo info(fileName);
     const QString absolute = info.absoluteFilePath();
 
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_MAC) || defined(Q_OS_WINCE)
     const QString canonical = info.canonicalFilePath();
 #elif defined(Q_OS_WIN)
     wchar_t buffer[1024];
@@ -1806,7 +2100,21 @@ bool QQml_isFileCaseCorrect(const QString &fileName)
     const int absoluteLength = absolute.length();
     const int canonicalLength = canonical.length();
 
-    const int length = qMin(absoluteLength, canonicalLength);
+    int length = qMin(absoluteLength, canonicalLength);
+    if (lengthIn >= 0) {
+        length = qMin(lengthIn, length);
+    } else {
+        // No length given: Limit to file name. Do not trigger
+        // on drive letters or folder names.
+        int lastSlash = absolute.lastIndexOf(QLatin1Char('/'));
+        if (lastSlash < 0)
+            lastSlash = absolute.lastIndexOf(QLatin1Char('\\'));
+        if (lastSlash >= 0) {
+            const int fileNameLength = absoluteLength - 1 - lastSlash;
+            length = qMin(length, fileNameLength);
+        }
+    }
+
     for (int ii = 0; ii < length; ++ii) {
         const QChar &a = absolute.at(absoluteLength - 1 - ii);
         const QChar &c = canonical.at(canonicalLength - 1 - ii);
@@ -1817,6 +2125,7 @@ bool QQml_isFileCaseCorrect(const QString &fileName)
             return false;
     }
 #else
+    Q_UNUSED(lengthIn)
     Q_UNUSED(fileName)
 #endif
     return true;