Implement strict mode for qmldir modules
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
45
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
48 #include "qqml.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
73
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
76
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
79 #include <QDebug>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
86
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
89
90 #include <private/qqmllocale_p.h>
91
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
94 #include <qlibrary.h>
95 #include <windows.h>
96
97 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
98 #endif
99
100 Q_DECLARE_METATYPE(QQmlProperty)
101
102 QT_BEGIN_NAMESPACE
103
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
105 {
106     QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107     QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
108     QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
109 }
110
111 /*!
112   \qmltype QtObject
113     \instantiates QObject
114   \inqmlmodule QtQuick 2
115   \ingroup qml-utility-elements
116   \since 4.7
117   \brief A basic QML type
118
119   The QtObject type is a non-visual element which contains only the
120   objectName property.
121
122   It can be useful to create a QtObject if you need an extremely
123   lightweight type to enclose a set of custom properties:
124
125   \snippet qml/qtobject.qml 0
126
127   It can also be useful for C++ integration, as it is just a plain
128   QObject. See the QObject documentation for further details.
129 */
130 /*!
131   \qmlproperty string QtObject::objectName
132   This property holds the QObject::objectName for this specific object instance.
133
134   This allows a C++ application to locate an item within a QML component
135   using the QObject::findChild() method. For example, the following C++
136   application locates the child \l Rectangle item and dynamically changes its
137   \c color value:
138
139     \qml
140     // MyRect.qml
141
142     import QtQuick 2.0
143
144     Item {
145         width: 200; height: 200
146
147         Rectangle {
148             anchors.fill: parent
149             color: "red"
150             objectName: "myRect"
151         }
152     }
153     \endqml
154
155     \code
156     // main.cpp
157
158     QQuickView view;
159     view.setSource(QUrl::fromLocalFile("MyRect.qml"));
160     view.show();
161
162     QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
163     if (item)
164         item->setProperty("color", QColor(Qt::yellow));
165     \endcode
166 */
167
168 bool QQmlEnginePrivate::qml_debugging_enabled = false;
169
170 // these types are part of the QML language
171 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
172 {
173     qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
174     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
175 }
176
177
178 // These QtQuick types' implementation resides in the QtQml module
179 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
180 {
181     qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
182     qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
183     qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
184 }
185
186 void QQmlEnginePrivate::defineQtQuick2Module()
187 {
188     // register the base types into the QtQuick namespace
189     registerBaseTypes("QtQuick",2,0);
190
191     // register the QtQuick2 types which are implemented in the QtQml module.
192     registerQtQuick2Types("QtQuick",2,0);
193     qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
194 }
195
196
197 /*!
198     \class QQmlImageProviderBase
199     \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
200     \mainclass
201
202     Image providers must be registered with the QML engine.  The only information the QML
203     engine knows about image providers is the type of image data they provide.  To use an
204     image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
205     to a QQuickImageProvider pointer.
206
207     \sa QQuickImageProvider, QQuickTextureFactory
208 */
209
210 /*!
211     \enum QQmlImageProviderBase::ImageType
212
213     Defines the type of image supported by this image provider.
214
215     \value Image The Image Provider provides QImage images.
216         The QQuickImageProvider::requestImage() method will be called for all image requests.
217     \value Pixmap The Image Provider provides QPixmap images.
218         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
219     \value Texture The Image Provider provides QSGTextureProvider based images.
220         The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
221 */
222
223 /*!
224     \enum QQmlImageProviderBase::Flag
225
226     Defines specific requirements or features of this image provider.
227
228     \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
229         run in a separate thread, which allows the provider to spend as much time as needed
230         on producing the image without blocking the main thread.
231 */
232
233 /*! \internal */
234 QQmlImageProviderBase::QQmlImageProviderBase()
235 {
236 }
237
238 /*! \internal */
239 QQmlImageProviderBase::~QQmlImageProviderBase()
240 {
241 }
242
243
244 /*!
245 \qmltype Qt
246     \instantiates QQmlEnginePrivate
247   \ingroup qml-utility-elements
248 \brief The QML global Qt object provides useful enums and functions from Qt.
249
250 \keyword QmlGlobalQtObject
251
252 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
253
254 The \c Qt object is a global object with utility functions, properties and enums.
255
256 It is not instantiable; to use it, call the members of the global \c Qt object directly.
257 For example:
258
259 \qml
260 import QtQuick 2.0
261
262 Text {
263     color: Qt.rgba(1, 0, 0, 1)
264     text: Qt.md5("hello, world")
265 }
266 \endqml
267
268
269 \section1 Enums
270
271 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
272 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
273
274
275 \section1 Types
276
277 The Qt object also contains helper functions for creating objects of specific
278 data types. This is primarily useful when setting the properties of an item
279 when the property has one of the following types:
280 \list
281 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
282 \li \c point - use \l{Qt::point()}{Qt.point()}
283 \li \c size - use \l{Qt::size()}{Qt.size()}
284 \endlist
285
286 If the QtQuick module has been imported, the following helper functions for
287 creating objects of specific data types are also available for clients to use:
288 \list
289 \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()}
290 \li \c font - use \l{Qt::font()}{Qt.font()}
291 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
292 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
293 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
294 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
295 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
296 \endlist
297
298 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
299
300 \section1 Date/Time Formatters
301
302 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
303
304 \list
305     \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
306     \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
307     \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
308 \endlist
309
310 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
311
312
313 \section1 Dynamic Object Creation
314 The following functions on the global object allow you to dynamically create QML
315 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
316 of their use.
317
318 \list
319     \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
320     \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
321 \endlist
322
323
324 \section1 Other Functions
325
326 The following functions are also on the Qt object.
327
328 \list
329     \li \l{Qt::quit()}{Qt.quit()}
330     \li \l{Qt::md5()}{Qt.md5(string)}
331     \li \l{Qt::btoa()}{string Qt.btoa(string)}
332     \li \l{Qt::atob()}{string Qt.atob(string)}
333     \li \l{Qt::binding()}{object Qt.binding(function)}
334     \li \l{Qt::locale()}{object Qt.locale()}
335     \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
336     \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
337     \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
338 \endlist
339 */
340
341 /*!
342     \qmlproperty object Qt::application
343     \since QtQuick 1.1
344
345     The \c application object provides access to global application state
346     properties shared by many QML components.
347
348     Its properties are:
349
350     \table
351     \row
352     \li \c application.active
353     \li
354     This read-only property indicates whether the application is the top-most and focused
355     application, and the user is able to interact with the application. The property
356     is false when the application is in the background, the device keylock or screen
357     saver is active, the screen backlight is turned off, or the global system dialog
358     is being displayed on top of the application. It can be used for stopping and
359     pausing animations, timers and active processing of data in order to save device
360     battery power and free device memory and processor load when the application is not
361     active.
362
363     \row
364     \li \c application.layoutDirection
365     \li
366     This read-only property can be used to query the default layout direction of the
367     application. On system start-up, the default layout direction depends on the
368     application's language. The property has a value of \c Qt.RightToLeft in locales
369     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
370     where the reading direction flows from left to right. You can bind to this
371     property to customize your application layouts to support both layout directions.
372
373     Possible values are:
374
375     \list
376     \li Qt.LeftToRight - Text and graphics elements should be positioned
377                         from left to right.
378     \li Qt.RightToLeft - Text and graphics elements should be positioned
379                         from right to left.
380     \endlist
381
382     \endtable
383
384     The following example uses the \c application object to indicate
385     whether the application is currently active:
386
387     \snippet qml/application.qml document
388 */
389
390 /*!
391     \qmlproperty object Qt::inputMethod
392     \since QtQuick 2.0
393
394     The \c inputMethod object allows access to application's QInputMethod object
395     and all its properties and slots. See the QInputMethod documentation for
396     further details.
397 */
398
399
400 /*!
401 \qmlmethod object Qt::include(string url, jsobject callback)
402
403 Includes another JavaScript file. This method can only be used from within JavaScript files,
404 and not regular QML files.
405
406 This imports all functions from \a url into the current script's namespace.
407
408 Qt.include() returns an object that describes the status of the operation.  The object has
409 a single property, \c {status}, that is set to one of the following values:
410
411 \table
412 \header \li Symbol \li Value \li Description
413 \row \li result.OK \li 0 \li The include completed successfully.
414 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
415 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
416 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
417 An additional \c exception property will be set in this case.
418 \endtable
419
420 The \c status property will be updated as the operation progresses.
421
422 If provided, \a callback is invoked when the operation completes.  The callback is passed
423 the same object as is returned from the Qt.include() call.
424 */
425 // Qt.include() is implemented in qv8include.cpp
426
427
428 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
429 : propertyCapture(0), rootContext(0), isDebugging(false),
430   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
431   cleanup(0), erroredBindings(0), inProgressCreations(0),
432   workerScriptEngine(0), activeVME(0),
433   networkAccessManager(0), networkAccessManagerFactory(0),
434   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
435   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
436 {
437 }
438
439 QQmlEnginePrivate::~QQmlEnginePrivate()
440 {
441     if (inProgressCreations)
442         qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
443
444     while (cleanup) {
445         QQmlCleanup *c = cleanup;
446         cleanup = c->next;
447         if (cleanup) cleanup->prev = &cleanup;
448         c->next = 0;
449         c->prev = 0;
450         c->clear();
451     }
452
453     doDeleteInEngineThread();
454
455     if (incubationController) incubationController->d = 0;
456     incubationController = 0;
457
458     delete rootContext;
459     rootContext = 0;
460
461     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
462         (*iter)->release();
463     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
464         (*iter)->release();
465     for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
466         delete (*iter)->qobjectApi;
467         delete *iter;
468     }
469     for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
470         iter.value()->isRegisteredWithEngine = false;
471 }
472
473 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
474 {
475     QObjectPrivate *p = QObjectPrivate::get(o);
476     if (p->declarativeData) {
477         QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
478         if (d->ownContext && d->context) {
479             d->context->destroy();
480             d->context = 0;
481         }
482
483         // Mark this object as in the process of deletion to
484         // prevent it resolving in bindings
485         QQmlData::markAsDeleted(o);
486     }
487 }
488
489 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
490 {
491     static_cast<QQmlData *>(d)->destroyed(o);
492 }
493
494 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
495 {
496     static_cast<QQmlData *>(d)->parentChanged(o, p);
497 }
498
499 class QQmlThreadNotifierProxyObject : public QObject
500 {
501 public:
502     QPointer<QObject> target;
503
504     virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
505         if (!target)
506             return -1;
507
508         QMetaMethod method = target->metaObject()->method(methodIndex);
509         Q_ASSERT(method.methodType() == QMetaMethod::Signal);
510         int signalIndex = QMetaObjectPrivate::signalIndex(method);
511         QQmlData *ddata = QQmlData::get(target, false);
512         QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
513         if (ep) QQmlNotifier::emitNotify(ep, a);
514
515         delete this;
516
517         return -1;
518     }
519 };
520
521 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
522 {
523     QQmlData *ddata = QQmlData::get(object, false);
524     if (!ddata) return; // Probably being deleted
525
526     // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
527     // that they're exposed to.  However, to make writing "worker objects" that calculate data
528     // in a separate thread easier, QML allows a QObject that lives in the same thread as the
529     // QQmlEngine to emit signals from a different thread.  These signals are then automatically
530     // marshalled back onto the QObject's thread and handled by QML from there.  This is tested
531     // by the qqmlecmascript::threadSignal() autotest.
532     if (ddata->notifyList &&
533         QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
534
535         if (!QObjectPrivate::get(object)->threadData->thread)
536             return;
537
538         QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
539         QList<QByteArray> parameterTypes = m.parameterTypes();
540
541         int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
542         void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
543
544         types[0] = 0; // return type
545         args[0] = 0; // return value
546
547         for (int ii = 0; ii < parameterTypes.count(); ++ii) {
548             const QByteArray &typeName = parameterTypes.at(ii);
549             if (typeName.endsWith('*'))
550                 types[ii + 1] = QMetaType::VoidStar;
551             else
552                 types[ii + 1] = QMetaType::type(typeName);
553
554             if (!types[ii + 1]) {
555                 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
556                          "(Make sure '%s' is registered using qRegisterMetaType().)",
557                          typeName.constData(), typeName.constData());
558                 free(types);
559                 free(args);
560                 return;
561             }
562
563             args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
564         }
565
566         QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
567                                                 parameterTypes.count() + 1, types, args);
568
569         QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
570         mpo->target = object;
571         mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
572         QCoreApplication::postEvent(mpo, ev);
573
574     } else {
575         QQmlNotifierEndpoint *ep = ddata->notify(index);
576         if (ep) QQmlNotifier::emitNotify(ep, a);
577     }
578 }
579
580 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
581 {
582     return static_cast<QQmlData *>(d)->endpointCount(index);
583 }
584
585 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
586 {
587     return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
588 }
589
590 int QQmlData::endpointCount(int index)
591 {
592     int count = 0;
593     QQmlNotifierEndpoint *ep = notify(index);
594     if (!ep)
595         return count;
596     ++count;
597     while (ep->next) {
598         ++count;
599         ep = ep->next;
600     }
601     return count;
602 }
603
604 void QQmlData::markAsDeleted(QObject *o)
605 {
606     QQmlData::setQueuedForDeletion(o);
607
608     QObjectPrivate *p = QObjectPrivate::get(o);
609     for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
610         QQmlData::markAsDeleted(*it);
611     }
612 }
613
614 void QQmlData::setQueuedForDeletion(QObject *object)
615 {
616     if (object) {
617         if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
618             if (!priv->wasDeleted && priv->declarativeData) {
619                 QQmlData *ddata = QQmlData::get(object, false);
620                 if (ddata->ownContext && ddata->context)
621                     ddata->context->emitDestruction();
622                 ddata->isQueuedForDeletion = true;
623             }
624         }
625     }
626 }
627
628 void QQmlEnginePrivate::init()
629 {
630     Q_Q(QQmlEngine);
631
632     static bool firstTime = true;
633     if (firstTime) {
634         qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
635         registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
636
637         QQmlData::init();
638         firstTime = false;
639     }
640
641     qRegisterMetaType<QVariant>("QVariant");
642     qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
643     qRegisterMetaType<QJSValue>("QJSValue");
644     qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
645     qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
646     qRegisterMetaType<QList<int> >("QList<int>");
647     qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
648
649     v8engine()->setEngine(q);
650
651     rootContext = new QQmlContext(q,true);
652
653     if (QCoreApplication::instance()->thread() == q->thread() &&
654         QQmlEngineDebugService::isDebuggingEnabled()) {
655         isDebugging = true;
656         QQmlEngineDebugService::instance()->addEngine(q);
657         QV8DebugService::initialize(v8engine());
658         QV8ProfilerService::initialize();
659         QQmlProfilerService::initialize();
660         QDebugMessageService::instance();
661     }
662
663     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
664     if (!dataLocation.isEmpty())
665         offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
666                            + QDir::separator() + QLatin1String("QML")
667                            + QDir::separator() + QLatin1String("OfflineStorage");
668 }
669
670 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
671 {
672     Q_Q(QQmlEngine);
673     if (!workerScriptEngine)
674         workerScriptEngine = new QQuickWorkerScriptEngine(q);
675     return workerScriptEngine;
676 }
677
678 /*!
679   \class QQmlEngine
680   \since 5.0
681   \inmodule QtQml
682   \brief The QQmlEngine class provides an environment for instantiating QML components.
683   \mainclass
684
685   Each QML component is instantiated in a QQmlContext.
686   QQmlContext's are essential for passing data to QML
687   components.  In QML, contexts are arranged hierarchically and this
688   hierarchy is managed by the QQmlEngine.
689
690   Prior to creating any QML components, an application must have
691   created a QQmlEngine to gain access to a QML context.  The
692   following example shows how to create a simple Text item.
693
694   \code
695   QQmlEngine engine;
696   QQmlComponent component(&engine);
697   component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
698   QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
699
700   //add item to view, etc
701   ...
702   \endcode
703
704   In this case, the Text item will be created in the engine's
705   \l {QQmlEngine::rootContext()}{root context}.
706
707   Note that the QtQuick 1 version is called QDeclarativeEngine.
708
709   \sa QQmlComponent, QQmlContext
710 */
711
712 /*!
713   Create a new QQmlEngine with the given \a parent.
714 */
715 QQmlEngine::QQmlEngine(QObject *parent)
716 : QJSEngine(*new QQmlEnginePrivate(this), parent)
717 {
718     Q_D(QQmlEngine);
719     d->init();
720 }
721
722 /*!
723   Destroys the QQmlEngine.
724
725   Any QQmlContext's created on this engine will be
726   invalidated, but not destroyed (unless they are parented to the
727   QQmlEngine object).
728 */
729 QQmlEngine::~QQmlEngine()
730 {
731     Q_D(QQmlEngine);
732     if (d->isDebugging) {
733         QQmlEngineDebugService::instance()->remEngine(this);
734     }
735
736     // Emit onDestruction signals for the root context before
737     // we destroy the contexts, engine, Module APIs etc. that
738     // may be required to handle the destruction signal.
739     QQmlContextData::get(rootContext())->emitDestruction();
740
741     // if we are the parent of any of the qobject module api instances,
742     // we need to remove them from our internal list, in order to prevent
743     // a segfault in engine private dtor.
744     QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
745     QObject *currQObjectApi = 0;
746     QQmlMetaType::ModuleApiInstance *currInstance = 0;
747     foreach (const QQmlMetaType::ModuleApi &key, keys) {
748         currInstance = d->moduleApiInstances.value(key);
749         currQObjectApi = currInstance->qobjectApi;
750         if (this->children().contains(currQObjectApi)) {
751             delete currQObjectApi;
752             delete currInstance;
753             d->moduleApiInstances.remove(key);
754         }
755     }
756
757     if (d->incubationController)
758         d->incubationController->d = 0;
759 }
760
761 /*! \fn void QQmlEngine::quit()
762     This signal is emitted when the QML loaded by the engine would like to quit.
763  */
764
765 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
766     This signal is emitted when \a warnings messages are generated by QML.
767  */
768
769 /*!
770   Clears the engine's internal component cache.
771
772   This function causes the property metadata of all components previously
773   loaded by the engine to be destroyed.  All previously loaded components and
774   the property bindings for all extant objects created from those components will
775   cease to function.
776
777   This function returns the engine to a state where it does not contain any loaded
778   component data.  This may be useful in order to reload a smaller subset of the
779   previous component set, or to load a new version of a previously loaded component.
780
781   Once the component cache has been cleared, components must be loaded before
782   any new objects can be created.
783
784   \sa trimComponentCache()
785  */
786 void QQmlEngine::clearComponentCache()
787 {
788     Q_D(QQmlEngine);
789     d->typeLoader.clearCache();
790 }
791
792 /*!
793   Trims the engine's internal component cache.
794
795   This function causes the property metadata of any loaded components which are
796   not currently in use to be destroyed.
797
798   A component is considered to be in use if there are any extant instances of
799   the component itself, any instances of other components that use the component,
800   or any objects instantiated by any of those components.
801
802   \sa clearComponentCache()
803  */
804 void QQmlEngine::trimComponentCache()
805 {
806     Q_D(QQmlEngine);
807     d->typeLoader.trimCache();
808 }
809
810 /*!
811   Returns the engine's root context.
812
813   The root context is automatically created by the QQmlEngine.
814   Data that should be available to all QML component instances
815   instantiated by the engine should be put in the root context.
816
817   Additional data that should only be available to a subset of
818   component instances should be added to sub-contexts parented to the
819   root context.
820 */
821 QQmlContext *QQmlEngine::rootContext() const
822 {
823     Q_D(const QQmlEngine);
824     return d->rootContext;
825 }
826
827 /*!
828   Sets the \a factory to use for creating QNetworkAccessManager(s).
829
830   QNetworkAccessManager is used for all network access by QML.  By
831   implementing a factory it is possible to create custom
832   QNetworkAccessManager with specialized caching, proxy and cookie
833   support.
834
835   The factory must be set before executing the engine.
836 */
837 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
838 {
839     Q_D(QQmlEngine);
840     QMutexLocker locker(&d->mutex);
841     d->networkAccessManagerFactory = factory;
842 }
843
844 /*!
845   Returns the current QQmlNetworkAccessManagerFactory.
846
847   \sa setNetworkAccessManagerFactory()
848 */
849 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
850 {
851     Q_D(const QQmlEngine);
852     return d->networkAccessManagerFactory;
853 }
854
855 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
856 {
857     if (activeVME) {
858         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
859     } else {
860         void *args[] = { 0 };
861         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
862     }
863 }
864
865 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
866 {
867     QMutexLocker locker(&mutex);
868     QNetworkAccessManager *nam;
869     if (networkAccessManagerFactory) {
870         nam = networkAccessManagerFactory->create(parent);
871     } else {
872         nam = new QNetworkAccessManager(parent);
873     }
874
875     return nam;
876 }
877
878 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
879 {
880     Q_Q(const QQmlEngine);
881     if (!networkAccessManager)
882         networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
883     return networkAccessManager;
884 }
885
886 /*!
887   Returns a common QNetworkAccessManager which can be used by any QML
888   type instantiated by this engine.
889
890   If a QQmlNetworkAccessManagerFactory has been set and a
891   QNetworkAccessManager has not yet been created, the
892   QQmlNetworkAccessManagerFactory will be used to create the
893   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
894   will have no proxy or cache set.
895
896   \sa setNetworkAccessManagerFactory()
897 */
898 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
899 {
900     Q_D(const QQmlEngine);
901     return d->getNetworkAccessManager();
902 }
903
904 /*!
905
906   Sets the \a provider to use for images requested via the \e
907   image: url scheme, with host \a providerId. The QQmlEngine
908   takes ownership of \a provider.
909
910   Image providers enable support for pixmap and threaded image
911   requests. See the QQuickImageProvider documentation for details on
912   implementing and using image providers.
913
914   All required image providers should be added to the engine before any
915   QML sources files are loaded.
916
917   \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
918 */
919 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
920 {
921     Q_D(QQmlEngine);
922     QMutexLocker locker(&d->mutex);
923     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
924 }
925
926 /*!
927   Returns the image provider set for \a providerId.
928
929   Returns the provider if it was found; otherwise returns 0.
930
931   \sa QQuickImageProvider
932 */
933 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
934 {
935     Q_D(const QQmlEngine);
936     QMutexLocker locker(&d->mutex);
937     return d->imageProviders.value(providerId).data();
938 }
939
940 /*!
941   Removes the image provider for \a providerId.
942
943   \sa addImageProvider(), QQuickImageProvider
944 */
945 void QQmlEngine::removeImageProvider(const QString &providerId)
946 {
947     Q_D(QQmlEngine);
948     QMutexLocker locker(&d->mutex);
949     d->imageProviders.take(providerId);
950 }
951
952 /*!
953   Return the base URL for this engine.  The base URL is only used to
954   resolve components when a relative URL is passed to the
955   QQmlComponent constructor.
956
957   If a base URL has not been explicitly set, this method returns the
958   application's current working directory.
959
960   \sa setBaseUrl()
961 */
962 QUrl QQmlEngine::baseUrl() const
963 {
964     Q_D(const QQmlEngine);
965     if (d->baseUrl.isEmpty()) {
966         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
967     } else {
968         return d->baseUrl;
969     }
970 }
971
972 /*!
973   Set the  base URL for this engine to \a url.
974
975   \sa baseUrl()
976 */
977 void QQmlEngine::setBaseUrl(const QUrl &url)
978 {
979     Q_D(QQmlEngine);
980     d->baseUrl = url;
981 }
982
983 /*!
984   Returns true if warning messages will be output to stderr in addition
985   to being emitted by the warnings() signal, otherwise false.
986
987   The default value is true.
988 */
989 bool QQmlEngine::outputWarningsToStandardError() const
990 {
991     Q_D(const QQmlEngine);
992     return d->outputWarningsToStdErr;
993 }
994
995 /*!
996   Set whether warning messages will be output to stderr to \a enabled.
997
998   If \a enabled is true, any warning messages generated by QML will be
999   output to stderr and emitted by the warnings() signal.  If \a enabled
1000   is false, on the warnings() signal will be emitted.  This allows
1001   applications to handle warning output themselves.
1002
1003   The default value is true.
1004 */
1005 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1006 {
1007     Q_D(QQmlEngine);
1008     d->outputWarningsToStdErr = enabled;
1009 }
1010
1011 /*!
1012   Returns the QQmlContext for the \a object, or 0 if no
1013   context has been set.
1014
1015   When the QQmlEngine instantiates a QObject, the context is
1016   set automatically.
1017   */
1018 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1019 {
1020     if(!object)
1021         return 0;
1022
1023     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1024
1025     QQmlData *data =
1026         static_cast<QQmlData *>(priv->declarativeData);
1027
1028     if (!data)
1029         return 0;
1030     else if (data->outerContext)
1031         return data->outerContext->asQQmlContext();
1032     else
1033         return 0;
1034 }
1035
1036 /*!
1037   Sets the QQmlContext for the \a object to \a context.
1038   If the \a object already has a context, a warning is
1039   output, but the context is not changed.
1040
1041   When the QQmlEngine instantiates a QObject, the context is
1042   set automatically.
1043  */
1044 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1045 {
1046     if (!object || !context)
1047         return;
1048
1049     QQmlData *data = QQmlData::get(object, true);
1050     if (data->context) {
1051         qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1052         return;
1053     }
1054
1055     QQmlContextData *contextData = QQmlContextData::get(context);
1056     contextData->addObject(object);
1057 }
1058
1059 /*!
1060   \enum QQmlEngine::ObjectOwnership
1061
1062   Ownership controls whether or not QML automatically destroys the
1063   QObject when the object is garbage collected by the JavaScript
1064   engine.  The two ownership options are:
1065
1066   \value CppOwnership The object is owned by C++ code, and will
1067   never be deleted by QML.  The JavaScript destroy() method cannot be
1068   used on objects with CppOwnership.  This option is similar to
1069   QScriptEngine::QtOwnership.
1070
1071   \value JavaScriptOwnership The object is owned by JavaScript.
1072   When the object is returned to QML as the return value of a method
1073   call or property access, QML will track it, and delete the object
1074   if there are no remaining JavaScript references to it and it has no
1075   QObject::parent().  An object tracked by one QQmlEngine
1076   will be deleted during that QQmlEngine's destructor, and thus
1077   JavaScript references between objects with JavaScriptOwnership from
1078   two different engines will not be valid after the deletion of one of
1079   those engines.  This option is similar to QScriptEngine::ScriptOwnership.
1080
1081   Generally an application doesn't need to set an object's ownership
1082   explicitly.  QML uses a heuristic to set the default object
1083   ownership.  By default, an object that is created by QML has
1084   JavaScriptOwnership.  The exception to this are the root objects
1085   created by calling QQmlComponent::create() or
1086   QQmlComponent::beginCreate() which have CppOwnership by
1087   default.  The ownership of these root-level objects is considered to
1088   have been transferred to the C++ caller.
1089
1090   Objects not-created by QML have CppOwnership by default.  The
1091   exception to this is objects returned from a C++ method call.  The
1092   ownership of these objects is passed to JavaScript.
1093
1094   Calling setObjectOwnership() overrides the default ownership
1095   heuristic used by QML.
1096 */
1097
1098 /*!
1099   Sets the \a ownership of \a object.
1100 */
1101 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1102 {
1103     if (!object)
1104         return;
1105
1106     QQmlData *ddata = QQmlData::get(object, true);
1107     if (!ddata)
1108         return;
1109
1110     ddata->indestructible = (ownership == CppOwnership)?true:false;
1111     ddata->explicitIndestructibleSet = true;
1112 }
1113
1114 /*!
1115   Returns the ownership of \a object.
1116 */
1117 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1118 {
1119     if (!object)
1120         return CppOwnership;
1121
1122     QQmlData *ddata = QQmlData::get(object, false);
1123     if (!ddata)
1124         return CppOwnership;
1125     else
1126         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1127 }
1128
1129 bool QQmlEngine::event(QEvent *e)
1130 {
1131     Q_D(QQmlEngine);
1132     if (e->type() == QEvent::User)
1133         d->doDeleteInEngineThread();
1134
1135     return QJSEngine::event(e);
1136 }
1137
1138 void QQmlEnginePrivate::doDeleteInEngineThread()
1139 {
1140     QFieldList<Deletable, &Deletable::next> list;
1141     mutex.lock();
1142     list.copyAndClear(toDeleteInEngineThread);
1143     mutex.unlock();
1144
1145     while (Deletable *d = list.takeFirst())
1146         delete d;
1147 }
1148
1149 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1150 {
1151     QQmlData *data = QQmlData::get(object);
1152
1153     if (data && data->compiledData && data->deferredIdx) {
1154         QQmlObjectCreatingProfiler prof;
1155         if (prof.enabled) {
1156             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1157             prof.setTypeName(type ? type->qmlTypeName()
1158                                   : QString::fromUtf8(object->metaObject()->className()));
1159             if (data->outerContext)
1160                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1161         }
1162         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1163
1164         QQmlComponentPrivate::ConstructionState state;
1165         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1166
1167         // Release the reference for the deferral action (we still have one from construction)
1168         data->compiledData->release();
1169         data->compiledData = 0;
1170
1171         QQmlComponentPrivate::complete(ep, &state);
1172     }
1173 }
1174
1175 QQmlContext *qmlContext(const QObject *obj)
1176 {
1177     return QQmlEngine::contextForObject(obj);
1178 }
1179
1180 QQmlEngine *qmlEngine(const QObject *obj)
1181 {
1182     QQmlData *data = QQmlData::get(obj, false);
1183     if (!data || !data->context)
1184         return 0;
1185     return data->context->engine;
1186 }
1187
1188 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1189 {
1190     QQmlData *data = QQmlData::get(object);
1191     if (!data)
1192         return 0; // Attached properties are only on objects created by QML
1193
1194     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1195     if (rv || !create)
1196         return rv;
1197
1198     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1199     if (!pf)
1200         return 0;
1201
1202     rv = pf(const_cast<QObject *>(object));
1203
1204     if (rv)
1205         data->attachedProperties()->insert(id, rv);
1206
1207     return rv;
1208 }
1209
1210 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1211                                      const QMetaObject *attachedMetaObject, bool create)
1212 {
1213     if (*idCache == -1)
1214         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1215
1216     if (*idCache == -1 || !object)
1217         return 0;
1218
1219     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1220 }
1221
1222 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1223 {
1224 #ifndef QQML_NO_DEBUG_PROTOCOL
1225     if (!QQmlEnginePrivate::qml_debugging_enabled
1226             && printWarning) {
1227         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1228     }
1229     QQmlEnginePrivate::qml_debugging_enabled = true;
1230 #endif
1231 }
1232
1233
1234 class QQmlDataExtended {
1235 public:
1236     QQmlDataExtended();
1237     ~QQmlDataExtended();
1238
1239     QHash<int, QObject *> attachedProperties;
1240 };
1241
1242 QQmlDataExtended::QQmlDataExtended()
1243 {
1244 }
1245
1246 QQmlDataExtended::~QQmlDataExtended()
1247 {
1248 }
1249
1250 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1251 {
1252     if (endpoint->next)
1253         layout(endpoint->next);
1254
1255     int index = endpoint->sourceSignal;
1256     index = qMin(index, 0xFFFF - 1);
1257
1258     endpoint->next = notifies[index];
1259     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1260     endpoint->prev = &notifies[index];
1261     notifies[index] = endpoint;
1262 }
1263
1264 void QQmlData::NotifyList::layout()
1265 {
1266     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1267
1268     if (todo) {
1269         QQmlNotifierEndpoint **old = notifies;
1270         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1271         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1272         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1273                                sizeof(QQmlNotifierEndpoint*);
1274         memset(notifies + notifiesSize, 0, memsetSize);
1275
1276         if (notifies != old) {
1277             for (int ii = 0; ii < notifiesSize; ++ii)
1278                 if (notifies[ii])
1279                     notifies[ii]->prev = &notifies[ii];
1280         }
1281
1282         notifiesSize = maximumTodoIndex + 1;
1283
1284         layout(todo);
1285     }
1286
1287     maximumTodoIndex = 0;
1288     todo = 0;
1289 }
1290
1291 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1292 {
1293     if (!notifyList) {
1294         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1295         notifyList->connectionMask = 0;
1296         notifyList->maximumTodoIndex = 0;
1297         notifyList->notifiesSize = 0;
1298         notifyList->todo = 0;
1299         notifyList->notifies = 0;
1300     }
1301
1302     Q_ASSERT(!endpoint->isConnected());
1303
1304     index = qMin(index, 0xFFFF - 1);
1305     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1306
1307     if (index < notifyList->notifiesSize) {
1308
1309         endpoint->next = notifyList->notifies[index];
1310         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1311         endpoint->prev = &notifyList->notifies[index];
1312         notifyList->notifies[index] = endpoint;
1313
1314     } else {
1315         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1316
1317         endpoint->next = notifyList->todo;
1318         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1319         endpoint->prev = &notifyList->todo;
1320         notifyList->todo = endpoint;
1321     }
1322 }
1323
1324 /*
1325     index MUST in the range returned by QObjectPrivate::signalIndex()
1326     This is different than the index returned by QMetaMethod::methodIndex()
1327 */
1328 bool QQmlData::signalHasEndpoint(int index)
1329 {
1330     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1331 }
1332
1333 QHash<int, QObject *> *QQmlData::attachedProperties() const
1334 {
1335     if (!extendedData) extendedData = new QQmlDataExtended;
1336     return &extendedData->attachedProperties;
1337 }
1338
1339 void QQmlData::destroyed(QObject *object)
1340 {
1341     if (nextContextObject)
1342         nextContextObject->prevContextObject = prevContextObject;
1343     if (prevContextObject)
1344         *prevContextObject = nextContextObject;
1345
1346     QQmlAbstractBinding *binding = bindings;
1347     while (binding) {
1348         QQmlAbstractBinding *next = binding->nextBinding();
1349         binding->setAddedToObject(false);
1350         binding->setNextBinding(0);
1351         binding->destroy();
1352         binding = next;
1353     }
1354
1355     if (compiledData) {
1356         compiledData->release();
1357         compiledData = 0;
1358     }
1359
1360     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1361     while (signalHandler) {
1362         if (signalHandler->isEvaluating()) {
1363             // The object is being deleted during signal handler evaluation.
1364             // This will cause a crash due to invalid memory access when the
1365             // evaluation has completed.
1366             // Abort with a friendly message instead.
1367             QString locationString;
1368             QQmlBoundSignalExpression *expr = signalHandler->expression();
1369             if (expr) {
1370                 QString fileName = expr->sourceFile();
1371                 if (fileName.isEmpty())
1372                     fileName = QStringLiteral("<Unknown File>");
1373                 locationString.append(fileName);
1374                 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1375                 QString source = expr->expression();
1376                 if (source.size() > 100) {
1377                     source.truncate(96);
1378                     source.append(QStringLiteral(" ..."));
1379                 }
1380                 locationString.append(source);
1381             } else {
1382                 locationString = QStringLiteral("<Unknown Location>");
1383             }
1384             qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1385                    "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1386                    "instead), or the application is running a nested event loop.\n"
1387                    "This behavior is NOT supported!\n"
1388                    "%s", object, qPrintable(locationString));
1389         }
1390
1391         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1392         signalHandler->m_prevSignal = 0;
1393         signalHandler->m_nextSignal = 0;
1394         delete signalHandler;
1395         signalHandler = next;
1396     }
1397
1398     if (bindingBits)
1399         free(bindingBits);
1400
1401     if (propertyCache)
1402         propertyCache->release();
1403
1404     if (ownContext && context)
1405         context->destroy();
1406
1407     while (guards) {
1408         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1409         *guard = (QObject *)0;
1410         guard->objectDestroyed(object);
1411     }
1412
1413     if (notifyList) {
1414         while (notifyList->todo)
1415             notifyList->todo->disconnect();
1416         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1417             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1418                 ep->disconnect();
1419         }
1420         free(notifyList->notifies);
1421         free(notifyList);
1422         notifyList = 0;
1423     }
1424
1425     if (extendedData)
1426         delete extendedData;
1427
1428     // Dispose the handle.
1429     // We don't simply clear it (and wait for next gc cycle to dispose
1430     // via the weak qobject reference callback) as this affects the
1431     // outcomes of v8's gc statistical analysis heuristics, which can
1432     // cause unnecessary growth of the old pointer space js heap area.
1433     qPersistentDispose(v8object);
1434
1435     if (ownMemory)
1436         delete this;
1437 }
1438
1439 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1440
1441 void QQmlData::parentChanged(QObject *object, QObject *parent)
1442 {
1443     if (parentTest()) {
1444         if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1445             QString on;
1446             QString pn;
1447
1448             { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1449             { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1450
1451             qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1452                    "User code is attempting to change it to %s.\n"
1453                    "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1454         }
1455     }
1456 }
1457
1458 bool QQmlData::hasBindingBit(int bit) const
1459 {
1460     if (bindingBitsSize > bit)
1461         return bindingBits[bit / 32] & (1 << (bit % 32));
1462     else
1463         return false;
1464 }
1465
1466 void QQmlData::clearBindingBit(int bit)
1467 {
1468     if (bindingBitsSize > bit)
1469         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1470 }
1471
1472 void QQmlData::setBindingBit(QObject *obj, int bit)
1473 {
1474     if (bindingBitsSize <= bit) {
1475         int props = QQmlMetaObject(obj).propertyCount();
1476         Q_ASSERT(bit < props);
1477
1478         int arraySize = (props + 31) / 32;
1479         int oldArraySize = bindingBitsSize / 32;
1480
1481         bindingBits = (quint32 *)realloc(bindingBits,
1482                                          arraySize * sizeof(quint32));
1483
1484         memset(bindingBits + oldArraySize,
1485                0x00,
1486                sizeof(quint32) * (arraySize - oldArraySize));
1487
1488         bindingBitsSize = arraySize * 32;
1489     }
1490
1491     bindingBits[bit / 32] |= (1 << (bit % 32));
1492 }
1493
1494 void QQmlEnginePrivate::sendQuit()
1495 {
1496     Q_Q(QQmlEngine);
1497     emit q->quit();
1498     if (q->receivers(SIGNAL(quit())) == 0) {
1499         qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1500     }
1501 }
1502
1503 static void dumpwarning(const QQmlError &error)
1504 {
1505     QMessageLogger(error.url().toString().toLatin1().constData(),
1506                    error.line(), 0).warning().nospace()
1507             << qPrintable(error.toString());
1508 }
1509
1510 static void dumpwarning(const QList<QQmlError> &errors)
1511 {
1512     for (int ii = 0; ii < errors.count(); ++ii)
1513         dumpwarning(errors.at(ii));
1514 }
1515
1516 void QQmlEnginePrivate::warning(const QQmlError &error)
1517 {
1518     Q_Q(QQmlEngine);
1519     q->warnings(QList<QQmlError>() << error);
1520     if (outputWarningsToStdErr)
1521         dumpwarning(error);
1522 }
1523
1524 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1525 {
1526     Q_Q(QQmlEngine);
1527     q->warnings(errors);
1528     if (outputWarningsToStdErr)
1529         dumpwarning(errors);
1530 }
1531
1532 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1533 {
1534     Q_Q(QQmlEngine);
1535     warning(error->error(q));
1536 }
1537
1538 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1539 {
1540     if (engine)
1541         QQmlEnginePrivate::get(engine)->warning(error);
1542     else
1543         dumpwarning(error);
1544 }
1545
1546 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1547 {
1548     if (engine)
1549         QQmlEnginePrivate::get(engine)->warning(error);
1550     else
1551         dumpwarning(error);
1552 }
1553
1554 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1555 {
1556     if (engine)
1557         QQmlEnginePrivate::get(engine)->warning(error);
1558     else
1559         dumpwarning(error->error(0));
1560 }
1561
1562 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1563 {
1564     if (engine)
1565         engine->warning(error);
1566     else
1567         dumpwarning(error);
1568 }
1569
1570 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1571 {
1572     if (engine)
1573         engine->warning(error);
1574     else
1575         dumpwarning(error);
1576 }
1577
1578 /*
1579    This function should be called prior to evaluation of any js expression,
1580    so that scarce resources are not freed prematurely (eg, if there is a
1581    nested javascript expression).
1582  */
1583 void QQmlEnginePrivate::referenceScarceResources()
1584 {
1585     scarceResourcesRefCount += 1;
1586 }
1587
1588 /*
1589    This function should be called after evaluation of the js expression is
1590    complete, and so the scarce resources may be freed safely.
1591  */
1592 void QQmlEnginePrivate::dereferenceScarceResources()
1593 {
1594     Q_ASSERT(scarceResourcesRefCount > 0);
1595     scarceResourcesRefCount -= 1;
1596
1597     // if the refcount is zero, then evaluation of the "top level"
1598     // expression must have completed.  We can safely release the
1599     // scarce resources.
1600     if (scarceResourcesRefCount == 0) {
1601         // iterate through the list and release them all.
1602         // note that the actual SRD is owned by the JS engine,
1603         // so we cannot delete the SRD; but we can free the
1604         // memory used by the variant in the SRD.
1605         while (ScarceResourceData *sr = scarceResources.first()) {
1606             sr->data = QVariant();
1607             scarceResources.remove(sr);
1608         }
1609     }
1610 }
1611
1612 /*!
1613   Adds \a path as a directory where the engine searches for
1614   installed modules in a URL-based directory structure.
1615
1616   The \a path may be a local filesystem directory, a
1617   \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1618   \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1619
1620   The \a path will be converted into canonical form before it
1621   is added to the import path list.
1622
1623   The newly added \a path will be first in the importPathList().
1624
1625   \sa setImportPathList(), {QML Modules}
1626 */
1627 void QQmlEngine::addImportPath(const QString& path)
1628 {
1629     Q_D(QQmlEngine);
1630     d->importDatabase.addImportPath(path);
1631 }
1632
1633 /*!
1634   Returns the list of directories where the engine searches for
1635   installed modules in a URL-based directory structure.
1636
1637   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1638   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1639   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1640   provided by that module. A \c qmldir file is required for defining the
1641   type version mapping and possibly QML extensions plugins.
1642
1643   By default, the list contains the directory of the application executable,
1644   paths specified in the \c QML_IMPORT_PATH environment variable,
1645   and the builtin \c ImportsPath from QLibraryInfo.
1646
1647   \sa addImportPath(), setImportPathList()
1648 */
1649 QStringList QQmlEngine::importPathList() const
1650 {
1651     Q_D(const QQmlEngine);
1652     return d->importDatabase.importPathList();
1653 }
1654
1655 /*!
1656   Sets \a paths as the list of directories where the engine searches for
1657   installed modules in a URL-based directory structure.
1658
1659   By default, the list contains the directory of the application executable,
1660   paths specified in the \c QML_IMPORT_PATH environment variable,
1661   and the builtin \c ImportsPath from QLibraryInfo.
1662
1663   \sa importPathList(), addImportPath()
1664   */
1665 void QQmlEngine::setImportPathList(const QStringList &paths)
1666 {
1667     Q_D(QQmlEngine);
1668     d->importDatabase.setImportPathList(paths);
1669 }
1670
1671
1672 /*!
1673   Adds \a path as a directory where the engine searches for
1674   native plugins for imported modules (referenced in the \c qmldir file).
1675
1676   By default, the list contains only \c .,  i.e. the engine searches
1677   in the directory of the \c qmldir file itself.
1678
1679   The newly added \a path will be first in the pluginPathList().
1680
1681   \sa setPluginPathList()
1682 */
1683 void QQmlEngine::addPluginPath(const QString& path)
1684 {
1685     Q_D(QQmlEngine);
1686     d->importDatabase.addPluginPath(path);
1687 }
1688
1689
1690 /*!
1691   Returns the list of directories where the engine searches for
1692   native plugins for imported modules (referenced in the \c qmldir file).
1693
1694   By default, the list contains only \c .,  i.e. the engine searches
1695   in the directory of the \c qmldir file itself.
1696
1697   \sa addPluginPath(), setPluginPathList()
1698 */
1699 QStringList QQmlEngine::pluginPathList() const
1700 {
1701     Q_D(const QQmlEngine);
1702     return d->importDatabase.pluginPathList();
1703 }
1704
1705 /*!
1706   Sets the list of directories where the engine searches for
1707   native plugins for imported modules (referenced in the \c qmldir file)
1708   to \a paths.
1709
1710   By default, the list contains only \c .,  i.e. the engine searches
1711   in the directory of the \c qmldir file itself.
1712
1713   \sa pluginPathList(), addPluginPath()
1714   */
1715 void QQmlEngine::setPluginPathList(const QStringList &paths)
1716 {
1717     Q_D(QQmlEngine);
1718     d->importDatabase.setPluginPathList(paths);
1719 }
1720
1721 /*!
1722   Imports the plugin named \a filePath with the \a uri provided.
1723   Returns true if the plugin was successfully imported; otherwise returns false.
1724
1725   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1726
1727   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1728 */
1729 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1730 {
1731     Q_D(QQmlEngine);
1732     return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1733 }
1734
1735 /*!
1736   \property QQmlEngine::offlineStoragePath
1737   \brief the directory for storing offline user data
1738
1739   Returns the directory where SQL and other offline
1740   storage is placed.
1741
1742   QQuickWebView and the SQL databases created with openDatabase()
1743   are stored here.
1744
1745   The default is QML/OfflineStorage in the platform-standard
1746   user application data directory.
1747
1748   Note that the path may not currently exist on the filesystem, so
1749   callers wanting to \e create new files at this location should create
1750   it first - see QDir::mkpath().
1751 */
1752 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1753 {
1754     Q_D(QQmlEngine);
1755     d->offlineStoragePath = dir;
1756 }
1757
1758 QString QQmlEngine::offlineStoragePath() const
1759 {
1760     Q_D(const QQmlEngine);
1761     return d->offlineStoragePath;
1762 }
1763
1764 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1765 {
1766     Q_Q(QQmlEngine);
1767
1768     if (!mo->superClass()) {
1769         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1770         propertyCache.insert(mo, rv);
1771         return rv;
1772     } else {
1773         QQmlPropertyCache *super = cache(mo->superClass());
1774         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1775         propertyCache.insert(mo, rv);
1776         return rv;
1777     }
1778 }
1779
1780 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1781                                                                   QQmlError &error)
1782 {
1783     QList<QQmlType *> types;
1784
1785     int maxMinorVersion = 0;
1786
1787     const QMetaObject *metaObject = type->metaObject();
1788
1789     while (metaObject) {
1790         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1791                                                             type->majorVersion(), minorVersion);
1792         if (t) {
1793             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1794             types << t;
1795         } else {
1796             types << 0;
1797         }
1798
1799         metaObject = metaObject->superClass();
1800     }
1801
1802     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1803         c->addref();
1804         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1805         return c;
1806     }
1807
1808     QQmlPropertyCache *raw = cache(type->metaObject());
1809
1810     bool hasCopied = false;
1811
1812     for (int ii = 0; ii < types.count(); ++ii) {
1813         QQmlType *currentType = types.at(ii);
1814         if (!currentType)
1815             continue;
1816
1817         int rev = currentType->metaObjectRevision();
1818         int moIndex = types.count() - 1 - ii;
1819
1820         if (raw->allowedRevisionCache[moIndex] != rev) {
1821             if (!hasCopied) {
1822                 raw = raw->copy();
1823                 hasCopied = true;
1824             }
1825             raw->allowedRevisionCache[moIndex] = rev;
1826         }
1827     }
1828
1829     // Test revision compatibility - the basic rule is:
1830     //    * Anything that is excluded, cannot overload something that is not excluded *
1831
1832     // Signals override:
1833     //    * other signals and methods of the same name.
1834     //    * properties named on<Signal Name>
1835     //    * automatic <property name>Changed notify signals
1836
1837     // Methods override:
1838     //    * other methods of the same name
1839
1840     // Properties override:
1841     //    * other elements of the same name
1842
1843     bool overloadError = false;
1844     QString overloadName;
1845
1846 #if 0
1847     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1848          !overloadError && iter != raw->stringCache.end();
1849          ++iter) {
1850
1851         QQmlPropertyData *d = *iter;
1852         if (raw->isAllowedInRevision(d))
1853             continue; // Not excluded - no problems
1854
1855         // check that a regular "name" overload isn't happening
1856         QQmlPropertyData *current = d;
1857         while (!overloadError && current) {
1858             current = d->overrideData(current);
1859             if (current && raw->isAllowedInRevision(current))
1860                 overloadError = true;
1861         }
1862     }
1863 #endif
1864
1865     if (overloadError) {
1866         if (hasCopied) raw->release();
1867
1868         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."));
1869         return 0;
1870     }
1871
1872     if (!hasCopied) raw->addref();
1873     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1874
1875     if (minorVersion != maxMinorVersion) {
1876         raw->addref();
1877         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1878     }
1879
1880     return raw;
1881 }
1882
1883 QQmlMetaType::ModuleApiInstance *
1884 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1885 {
1886     Locker locker(this);
1887
1888     QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1889     if (!a) {
1890         a = new QQmlMetaType::ModuleApiInstance;
1891         a->scriptCallback = module.script;
1892         a->qobjectCallback = module.qobject;
1893         a->instanceMetaObject = module.instanceMetaObject;
1894         moduleApiInstances.insert(module, a);
1895     }
1896
1897     return a;
1898 }
1899
1900 bool QQmlEnginePrivate::isQObject(int t)
1901 {
1902     Locker locker(this);
1903     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1904 }
1905
1906 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1907 {
1908     Locker locker(this);
1909     int t = v.userType();
1910     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1911         if (ok) *ok = true;
1912         return *(QObject **)(v.constData());
1913     } else {
1914         return QQmlMetaType::toQObject(v, ok);
1915     }
1916 }
1917
1918 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1919 {
1920     Locker locker(this);
1921     if (m_compositeTypes.contains(t))
1922         return QQmlMetaType::Object;
1923     else if (m_qmlLists.contains(t))
1924         return QQmlMetaType::List;
1925     else
1926         return QQmlMetaType::typeCategory(t);
1927 }
1928
1929 bool QQmlEnginePrivate::isList(int t) const
1930 {
1931     Locker locker(this);
1932     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1933 }
1934
1935 int QQmlEnginePrivate::listType(int t) const
1936 {
1937     Locker locker(this);
1938     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1939     if (iter != m_qmlLists.end())
1940         return *iter;
1941     else
1942         return QQmlMetaType::listType(t);
1943 }
1944
1945 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1946 {
1947     Locker locker(this);
1948     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1949     if (iter != m_compositeTypes.end()) {
1950         return QQmlMetaObject((*iter)->rootPropertyCache);
1951     } else {
1952         QQmlType *type = QQmlMetaType::qmlType(t);
1953         return QQmlMetaObject(type?type->baseMetaObject():0);
1954     }
1955 }
1956
1957 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1958 {
1959     Locker locker(this);
1960     QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1961     if (iter != m_compositeTypes.end()) {
1962         return QQmlMetaObject((*iter)->rootPropertyCache);
1963     } else {
1964         QQmlType *type = QQmlMetaType::qmlType(t);
1965         return QQmlMetaObject(type?type->metaObject():0);
1966     }
1967 }
1968
1969 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1970 {
1971     Locker locker(this);
1972     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1973     if (iter != m_compositeTypes.end()) {
1974         return (*iter)->rootPropertyCache;
1975     } else {
1976         QQmlType *type = QQmlMetaType::qmlType(t);
1977         locker.unlock();
1978         return type?cache(type->metaObject()):0;
1979     }
1980 }
1981
1982 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1983 {
1984     Locker locker(this);
1985     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1986     if (iter != m_compositeTypes.end()) {
1987         return (*iter)->rootPropertyCache;
1988     } else {
1989         QQmlType *type = QQmlMetaType::qmlType(t);
1990         locker.unlock();
1991         return type?cache(type->baseMetaObject()):0;
1992     }
1993 }
1994
1995 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1996 {
1997     QByteArray name = data->rootPropertyCache->className();
1998
1999     QByteArray ptr = name + '*';
2000     QByteArray lst = "QQmlListProperty<" + name + '>';
2001
2002     int ptr_type = QMetaType::registerNormalizedType(ptr,
2003                                                      qMetaTypeDeleteHelper<QObject*>,
2004                                                      qMetaTypeCreateHelper<QObject*>,
2005                                                      qMetaTypeDestructHelper<QObject*>,
2006                                                      qMetaTypeConstructHelper<QObject*>,
2007                                                      sizeof(QObject*),
2008                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2009                                                      0);
2010     int lst_type = QMetaType::registerNormalizedType(lst,
2011                                                      qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
2012                                                      qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
2013                                                      qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
2014                                                      qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
2015                                                      sizeof(QQmlListProperty<QObject>),
2016                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2017                                                      static_cast<QMetaObject*>(0));
2018
2019     data->metaTypeId = ptr_type;
2020     data->listMetaTypeId = lst_type;
2021     data->isRegisteredWithEngine = true;
2022
2023     Locker locker(this);
2024     m_qmlLists.insert(lst_type, ptr_type);
2025     // The QQmlCompiledData is not referenced here, but it is removed from this
2026     // hash in the QQmlCompiledData destructor
2027     m_compositeTypes.insert(ptr_type, data);
2028 }
2029
2030 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2031 {
2032     int ptr_type = data->metaTypeId;
2033     int lst_type = data->listMetaTypeId;
2034
2035     Locker locker(this);
2036     m_qmlLists.remove(lst_type);
2037     m_compositeTypes.remove(ptr_type);
2038 }
2039
2040 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2041 {
2042     return typeLoader.isTypeLoaded(url);
2043 }
2044
2045 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2046 {
2047     return typeLoader.isScriptLoaded(url);
2048 }
2049
2050 bool QQml_isFileCaseCorrect(const QString &fileName)
2051 {
2052 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2053     QFileInfo info(fileName);
2054     const QString absolute = info.absoluteFilePath();
2055
2056 #if defined(Q_OS_MAC)
2057     const QString canonical = info.canonicalFilePath();
2058 #elif defined(Q_OS_WIN)
2059     wchar_t buffer[1024];
2060
2061     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2062     if (rv == 0 || rv >= 1024) return true;
2063     rv = ::GetLongPathName(buffer, buffer, 1024);
2064     if (rv == 0 || rv >= 1024) return true;
2065
2066     const QString canonical = QString::fromWCharArray(buffer);
2067 #endif
2068
2069     const int absoluteLength = absolute.length();
2070     const int canonicalLength = canonical.length();
2071
2072     const int length = qMin(absoluteLength, canonicalLength);
2073     for (int ii = 0; ii < length; ++ii) {
2074         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2075         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2076
2077         if (a.toLower() != c.toLower())
2078             return true;
2079         if (a != c)
2080             return false;
2081     }
2082 #else
2083     Q_UNUSED(fileName)
2084 #endif
2085     return true;
2086 }
2087
2088 /*!
2089     \fn QQmlEngine *qmlEngine(const QObject *object)
2090     \relates QQmlEngine
2091
2092     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
2093     QQmlEngine::contextForObject(object)->engine(), but more efficient.
2094 */
2095
2096 /*!
2097     \fn QQmlContext *qmlContext(const QObject *object)
2098     \relates QQmlEngine
2099
2100     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
2101     QQmlEngine::contextForObject(object).
2102 */
2103
2104 QT_END_NAMESPACE