2f224ea1f150cce96cc88fbd6206c66e5ac33ff2
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecomponent.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativecomponent.h"
43 #include "qdeclarativecomponent_p.h"
44 #include "qdeclarativecomponentattached_p.h"
45
46 #include "qdeclarativecompiler_p.h"
47 #include "qdeclarativecontext_p.h"
48 #include "qdeclarativeengine_p.h"
49 #include "qdeclarativevme_p.h"
50 #include "qdeclarative.h"
51 #include "qdeclarativeengine.h"
52 #include "qdeclarativebinding_p.h"
53 #include "qdeclarativebinding_p_p.h"
54 #include "qdeclarativeglobal_p.h"
55 #include "qdeclarativescript_p.h"
56 #include <private/qdeclarativedebugtrace_p.h>
57 #include <private/qdeclarativeenginedebugservice_p.h>
58 #include "qdeclarativeincubator.h"
59 #include "qdeclarativeincubator_p.h"
60
61 #include <private/qv8engine_p.h>
62 #include <private/qv8include_p.h>
63
64 #include <QStack>
65 #include <QStringList>
66 #include <QtCore/qdebug.h>
67 #include <qdeclarativeinfo.h>
68
69 QT_BEGIN_NAMESPACE
70
71 class QDeclarativeComponentExtension : public QV8Engine::Deletable
72 {
73 public:
74     QDeclarativeComponentExtension(QV8Engine *);
75     virtual ~QDeclarativeComponentExtension();
76
77     v8::Persistent<v8::Function> incubationConstructor;
78     v8::Persistent<v8::Script> initialProperties;
79     v8::Persistent<v8::Function> forceCompletion;
80 };
81 static V8_DEFINE_EXTENSION(QDeclarativeComponentExtension, componentExtension);
82
83 /*
84     Try to do what's necessary for a reasonable display of the type
85     name, but no more (just enough for the client to do more extensive cleanup).
86
87     Should only be called when debugging is enabled.
88 */
89 static inline QString buildTypeNameForDebug(const QMetaObject *metaObject)
90 {
91     static const QString qmlMarker(QLatin1String("_QML"));
92     static const QChar underscore(QLatin1Char('_'));
93     static const QChar asterisk(QLatin1Char('*'));
94     QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaObject);
95     QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(metaObject->className());
96     if (!type) {
97         //### optimize further?
98         int marker = typeName.indexOf(qmlMarker);
99         if (marker != -1 && marker < typeName.count() - 1) {
100             if (typeName[marker + 1] == underscore) {
101                 const QString className = typeName.left(marker) + asterisk;
102                 type = QDeclarativeMetaType::qmlType(QMetaType::type(className.toUtf8()));
103                 if (type)
104                     typeName = type->qmlTypeName();
105             }
106         }
107     }
108     return typeName;
109 }
110
111 /*!
112     \class QDeclarativeComponent
113     \since 4.7
114     \brief The QDeclarativeComponent class encapsulates a QML component definition.
115     \mainclass
116
117     Components are reusable, encapsulated QML elements with well-defined interfaces.
118     They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
119
120     A QDeclarativeComponent instance can be created from a QML file.
121     For example, if there is a \c main.qml file like this:
122
123     \qml
124     import QtQuick 1.0
125
126     Item {
127         width: 200
128         height: 200
129     }
130     \endqml
131
132     The following code loads this QML file as a component, creates an instance of
133     this component using create(), and then queries the \l Item's \l {Item::}{width}
134     value:
135
136     \code
137     QDeclarativeEngine *engine = new QDeclarativeEngine;
138     QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
139
140     QObject *myObject = component.create();
141     QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
142     int width = item->width();  // width = 200
143     \endcode
144
145
146     \section2 Network Components
147
148     If the URL passed to QDeclarativeComponent is a network resource, or if the QML document references a
149     network resource, the QDeclarativeComponent has to fetch the network data before it is able to create
150     objects.  In this case, the QDeclarativeComponent will have a \l {QDeclarativeComponent::Loading}{Loading}
151     \l {QDeclarativeComponent::status()}{status}.  An application will have to wait until the component
152     is \l {QDeclarativeComponent::Ready}{Ready} before calling \l {QDeclarativeComponent::create()}.
153
154     The following example shows how to load a QML file from a network resource.  After creating
155     the QDeclarativeComponent, it tests whether the component is loading.  If it is, it connects to the
156     QDeclarativeComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method
157     directly. Note that QDeclarativeComponent::isLoading() may be false for a network component if the
158     component has been cached and is ready immediately.
159
160     \code
161     MyApplication::MyApplication()
162     {
163         // ...
164         component = new QDeclarativeComponent(engine, QUrl("http://www.example.com/main.qml"));
165         if (component->isLoading())
166             QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
167                              this, SLOT(continueLoading()));
168         else
169             continueLoading();
170     }
171
172     void MyApplication::continueLoading()
173     {
174         if (component->isError()) {
175             qWarning() << component->errors();
176         } else {
177             QObject *myObject = component->create();
178         }
179     }
180     \endcode
181
182     \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code}
183 */
184
185 /*!
186     \qmlclass Component QDeclarativeComponent
187     \ingroup qml-utility-elements
188     \since 4.7
189     \brief The Component element encapsulates a QML component definition.
190
191     Components are reusable, encapsulated QML elements with well-defined interfaces.
192
193     Components are often defined by \l {qdeclarativedocuments.html}{component files} -
194     that is, \c .qml files. The \e Component element essentially allows QML components
195     to be defined inline, within a \l {QML Document}{QML document}, rather than as a separate QML file.
196     This may be useful for reusing a small component within a QML file, or for defining
197     a component that logically belongs with other QML components within a file.
198
199     For example, here is a component that is used by multiple \l Loader objects.
200     It contains a single item, a \l Rectangle:
201
202     \snippet doc/src/snippets/declarative/component.qml 0
203
204     Notice that while a \l Rectangle by itself would be automatically 
205     rendered and displayed, this is not the case for the above rectangle
206     because it is defined inside a \c Component. The component encapsulates the
207     QML elements within, as if they were defined in a separate QML
208     file, and is not loaded until requested (in this case, by the
209     two \l Loader objects).
210
211     Defining a \c Component is similar to defining a \l {QML Document}{QML document}.
212     A QML document has a single top-level item that defines the behaviors and
213     properties of that component, and cannot define properties or behaviors outside
214     of that top-level item. In the same way, a \c Component definition contains a single
215     top level item (which in the above example is a \l Rectangle) and cannot define any
216     data outside of this item, with the exception of an \e id (which in the above example
217     is \e redSquare).
218
219     The \c Component element is commonly used to provide graphical components
220     for views. For example, the ListView::delegate property requires a \c Component
221     to specify how each list item is to be displayed.
222
223     \c Component objects can also be created dynamically using
224     \l{QML:Qt::createComponent()}{Qt.createComponent()}.
225 */
226
227 /*!
228     \qmlattachedsignal Component::onCompleted()
229
230     Emitted after component "startup" has completed.  This can be used to
231     execute script code at startup, once the full QML environment has been
232     established.
233
234     The \c {Component::onCompleted} attached property can be applied to
235     any element.  The order of running the \c onCompleted scripts is
236     undefined.
237
238     \qml
239     Rectangle {
240         Component.onCompleted: console.log("Completed Running!")
241         Rectangle {
242             Component.onCompleted: console.log("Nested Completed Running!")
243         }
244     }
245     \endqml
246 */
247
248 /*!
249     \qmlattachedsignal Component::onDestruction()
250
251     Emitted as the component begins destruction.  This can be used to undo
252     work done in the onCompleted signal, or other imperative code in your
253     application.
254
255     The \c {Component::onDestruction} attached property can be applied to
256     any element.  However, it applies to the destruction of the component as
257     a whole, and not the destruction of the specific object.  The order of
258     running the \c onDestruction scripts is undefined.
259
260     \qml
261     Rectangle {
262         Component.onDestruction: console.log("Destruction Beginning!")
263         Rectangle {
264             Component.onDestruction: console.log("Nested Destruction Beginning!")
265         }
266     }
267     \endqml
268
269     \sa QtDeclarative
270 */
271
272 /*!
273     \enum QDeclarativeComponent::Status
274     
275     Specifies the loading status of the QDeclarativeComponent.
276
277     \value Null This QDeclarativeComponent has no data.  Call loadUrl() or setData() to add QML content.
278     \value Ready This QDeclarativeComponent is ready and create() may be called.
279     \value Loading This QDeclarativeComponent is loading network data.
280     \value Error An error has occurred.  Call errors() to retrieve a list of \{QDeclarativeError}{errors}.
281 */
282
283 void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *)
284 {
285     Q_Q(QDeclarativeComponent);
286
287     Q_ASSERT(typeData);
288
289     fromTypeData(typeData);
290     typeData = 0;
291
292     emit q->statusChanged(q->status());
293 }
294
295 void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p)
296 {
297     Q_Q(QDeclarativeComponent);
298
299     progress = p;
300
301     emit q->progressChanged(p);
302 }
303
304 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data)
305 {
306     url = data->finalUrl();
307     QDeclarativeCompiledData *c = data->compiledData();
308
309     if (!c) {
310         Q_ASSERT(data->isError());
311         state.errors = data->errors();
312     } else {
313         cc = c;
314     }
315
316     data->release();
317 }
318
319 void QDeclarativeComponentPrivate::clear()
320 {
321     if (typeData) {
322         typeData->unregisterCallback(this);
323         typeData->release();
324         typeData = 0;
325     }
326         
327     if (cc) { 
328         cc->release();
329         cc = 0;
330     }
331 }
332
333 /*!
334     \internal
335 */
336 QDeclarativeComponent::QDeclarativeComponent(QObject *parent)
337     : QObject(*(new QDeclarativeComponentPrivate), parent)
338 {
339 }
340
341 /*!
342     Destruct the QDeclarativeComponent.
343 */
344 QDeclarativeComponent::~QDeclarativeComponent()
345 {
346     Q_D(QDeclarativeComponent);
347
348     if (d->state.completePending) {
349         qWarning("QDeclarativeComponent: Component destroyed while completion pending");
350         d->completeCreate();
351     }
352
353     if (d->typeData) {
354         d->typeData->unregisterCallback(d);
355         d->typeData->release();
356     }
357     if (d->cc)
358         d->cc->release();
359 }
360
361 /*!
362     \qmlproperty enumeration Component::status
363     This property holds the status of component loading.  It can be one of:
364     \list
365     \o Component.Null - no data is available for the component
366     \o Component.Ready - the component has been loaded, and can be used to create instances.
367     \o Component.Loading - the component is currently being loaded
368     \o Component.Error - an error occurred while loading the component.
369                Calling errorString() will provide a human-readable description of any errors.
370     \endlist
371  */
372
373 /*!
374     \property QDeclarativeComponent::status
375     The component's current \l{QDeclarativeComponent::Status} {status}.
376  */
377 QDeclarativeComponent::Status QDeclarativeComponent::status() const
378 {
379     Q_D(const QDeclarativeComponent);
380
381     if (d->typeData)
382         return Loading;
383     else if (!d->state.errors.isEmpty())
384         return Error;
385     else if (d->engine && d->cc)
386         return Ready;
387     else
388         return Null;
389 }
390
391 /*!
392     Returns true if status() == QDeclarativeComponent::Null.
393 */
394 bool QDeclarativeComponent::isNull() const
395 {
396     return status() == Null;
397 }
398
399 /*!
400     Returns true if status() == QDeclarativeComponent::Ready.
401 */
402 bool QDeclarativeComponent::isReady() const
403 {
404     return status() == Ready;
405 }
406
407 /*!
408     Returns true if status() == QDeclarativeComponent::Error.
409 */
410 bool QDeclarativeComponent::isError() const
411 {
412     return status() == Error;
413 }
414
415 /*!
416     Returns true if status() == QDeclarativeComponent::Loading.
417 */
418 bool QDeclarativeComponent::isLoading() const
419 {
420     return status() == Loading;
421 }
422
423 /*!
424     \qmlproperty real Component::progress
425     The progress of loading the component, from 0.0 (nothing loaded)
426     to 1.0 (finished).
427 */
428
429 /*!
430     \property QDeclarativeComponent::progress
431     The progress of loading the component, from 0.0 (nothing loaded)
432     to 1.0 (finished).
433 */
434 qreal QDeclarativeComponent::progress() const
435 {
436     Q_D(const QDeclarativeComponent);
437     return d->progress;
438 }
439
440 /*!
441     \fn void QDeclarativeComponent::progressChanged(qreal progress)
442
443     Emitted whenever the component's loading progress changes.  \a progress will be the
444     current progress between 0.0 (nothing loaded) and 1.0 (finished).
445 */
446
447 /*!
448     \fn void QDeclarativeComponent::statusChanged(QDeclarativeComponent::Status status)
449
450     Emitted whenever the component's status changes.  \a status will be the
451     new status.
452 */
453
454 /*!
455     Create a QDeclarativeComponent with no data and give it the specified
456     \a engine and \a parent. Set the data with setData().
457 */
458 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QObject *parent)
459     : QObject(*(new QDeclarativeComponentPrivate), parent)
460 {
461     Q_D(QDeclarativeComponent);
462     d->engine = engine;
463 }
464
465 /*!
466     Create a QDeclarativeComponent from the given \a url and give it the
467     specified \a parent and \a engine.
468
469     Ensure that the URL provided is full and correct, in particular, use
470     \l QUrl::fromLocalFile() when loading a file from the local filesystem.
471
472     \sa loadUrl()
473 */
474 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QUrl &url, QObject *parent)
475 : QObject(*(new QDeclarativeComponentPrivate), parent)
476 {
477     Q_D(QDeclarativeComponent);
478     d->engine = engine;
479     loadUrl(url);
480 }
481
482 /*!
483     Create a QDeclarativeComponent from the given \a fileName and give it the specified 
484     \a parent and \a engine.
485
486     \sa loadUrl()
487 */
488 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QString &fileName, 
489                            QObject *parent)
490 : QObject(*(new QDeclarativeComponentPrivate), parent)
491 {
492     Q_D(QDeclarativeComponent);
493     d->engine = engine;
494     loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
495 }
496
497 /*!
498     \internal
499 */
500 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, QObject *parent)
501     : QObject(*(new QDeclarativeComponentPrivate), parent)
502 {
503     Q_D(QDeclarativeComponent);
504     d->engine = engine;
505     d->cc = cc;
506     cc->addref();
507     d->start = start;
508     d->url = cc->url;
509     d->progress = 1.0;
510 }
511
512 /*!
513     Sets the QDeclarativeComponent to use the given QML \a data.  If \a url
514     is provided, it is used to set the component name and to provide
515     a base path for items resolved by this component.
516 */
517 void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url)
518 {
519     Q_D(QDeclarativeComponent);
520
521     d->clear();
522
523     d->url = url;
524
525     QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url);
526     
527     if (typeData->isCompleteOrError()) {
528         d->fromTypeData(typeData);
529     } else {
530         d->typeData = typeData;
531         d->typeData->registerCallback(d);
532     }
533
534     d->progress = 1.0;
535     emit statusChanged(status());
536     emit progressChanged(d->progress);
537 }
538
539 /*!
540 Returns the QDeclarativeContext the component was created in.  This is only
541 valid for components created directly from QML.
542 */
543 QDeclarativeContext *QDeclarativeComponent::creationContext() const
544 {
545     Q_D(const QDeclarativeComponent);
546     if(d->creationContext)
547         return d->creationContext->asQDeclarativeContext();
548
549     return qmlContext(this);
550 }
551
552 /*!
553     Load the QDeclarativeComponent from the provided \a url.
554
555     Ensure that the URL provided is full and correct, in particular, use
556     \l QUrl::fromLocalFile() when loading a file from the local filesystem.
557 */
558 void QDeclarativeComponent::loadUrl(const QUrl &url)
559 {
560     Q_D(QDeclarativeComponent);
561
562     d->clear();
563
564     if ((url.isRelative() && !url.isEmpty())
565     || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
566         d->url = d->engine->baseUrl().resolved(url);
567     else
568         d->url = url;
569
570     if (url.isEmpty()) {
571         QDeclarativeError error;
572         error.setDescription(tr("Invalid empty URL"));
573         d->state.errors << error;
574         return;
575     }
576
577     QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url);
578
579     if (data->isCompleteOrError()) {
580         d->fromTypeData(data);
581         d->progress = 1.0;
582     } else {
583         d->typeData = data;
584         d->typeData->registerCallback(d);
585         d->progress = data->progress();
586     }
587
588     emit statusChanged(status());
589     emit progressChanged(d->progress);
590 }
591
592 /*!
593     Return the list of errors that occurred during the last compile or create
594     operation.  An empty list is returned if isError() is not set.
595 */
596 QList<QDeclarativeError> QDeclarativeComponent::errors() const
597 {
598     Q_D(const QDeclarativeComponent);
599     if (isError())
600         return d->state.errors;
601     else
602         return QList<QDeclarativeError>();
603 }
604
605 /*!
606     \qmlmethod string Component::errorString()
607
608     Returns a human-readable description of any errors.
609
610     The string includes the file, location, and description of each error.
611     If multiple errors are present they are separated by a newline character.
612
613     If no errors are present, an empty string is returned.
614 */
615
616 /*!
617     \internal
618     errorString is only meant as a way to get the errors in script
619 */
620 QString QDeclarativeComponent::errorString() const
621 {
622     Q_D(const QDeclarativeComponent);
623     QString ret;
624     if(!isError())
625         return ret;
626     foreach(const QDeclarativeError &e, d->state.errors) {
627         ret += e.url().toString() + QLatin1Char(':') +
628                QString::number(e.line()) + QLatin1Char(' ') +
629                e.description() + QLatin1Char('\n');
630     }
631     return ret;
632 }
633
634 /*!
635     \qmlproperty url Component::url
636     The component URL.  This is the URL that was used to construct the component.
637 */
638
639 /*!
640     \property QDeclarativeComponent::url
641     The component URL.  This is the URL passed to either the constructor,
642     or the loadUrl() or setData() methods.
643 */
644 QUrl QDeclarativeComponent::url() const
645 {
646     Q_D(const QDeclarativeComponent);
647     return d->url;
648 }
649
650 /*!
651     \internal
652 */
653 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject *parent)
654     : QObject(dd, parent)
655 {
656 }
657
658 /*!
659     Create an object instance from this component.  Returns 0 if creation
660     failed.  \a context specifies the context within which to create the object
661     instance.  
662
663     If \a context is 0 (the default), it will create the instance in the
664     engine' s \l {QDeclarativeEngine::rootContext()}{root context}.
665 */
666 QObject *QDeclarativeComponent::create(QDeclarativeContext *context)
667 {
668     Q_D(QDeclarativeComponent);
669
670     if (!context)
671         context = d->engine->rootContext();
672
673     QObject *rv = beginCreate(context);
674     completeCreate();
675     return rv;
676 }
677
678 /*!
679     This method provides more advanced control over component instance creation.
680     In general, programmers should use QDeclarativeComponent::create() to create a 
681     component.
682
683     Create an object instance from this component.  Returns 0 if creation
684     failed.  \a publicContext specifies the context within which to create the object
685     instance.  
686
687     When QDeclarativeComponent constructs an instance, it occurs in three steps:
688     \list 1
689     \i The object hierarchy is created, and constant values are assigned.
690     \i Property bindings are evaluated for the the first time.
691     \i If applicable, QDeclarativeParserStatus::componentComplete() is called on objects.
692     \endlist 
693     QDeclarativeComponent::beginCreate() differs from QDeclarativeComponent::create() in that it
694     only performs step 1.  QDeclarativeComponent::completeCreate() must be called to 
695     complete steps 2 and 3.
696
697     This breaking point is sometimes useful when using attached properties to
698     communicate information to an instantiated component, as it allows their
699     initial values to be configured before property bindings take effect.
700 */
701 QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *publicContext)
702 {
703     Q_D(QDeclarativeComponent);
704
705     Q_ASSERT(publicContext);
706     QDeclarativeContextData *context = QDeclarativeContextData::get(publicContext);
707
708     return d->beginCreate(context);
709 }
710
711 QObject *
712 QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context)
713 {
714     Q_Q(QDeclarativeComponent);
715     if (!context) {
716         qWarning("QDeclarativeComponent: Cannot create a component in a null context");
717         return 0;
718     }
719
720     if (!context->isValid()) {
721         qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
722         return 0;
723     }
724
725     if (context->engine != engine) {
726         qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
727         return 0;
728     }
729
730     if (state.completePending) {
731         qWarning("QDeclarativeComponent: Cannot create new component instance before completing the previous");
732         return 0;
733     }
734
735     if (!q->isReady()) {
736         qWarning("QDeclarativeComponent: Component is not ready");
737         return 0;
738     }
739
740     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
741
742     bool isRoot = enginePriv->inProgressCreations == 0;
743     enginePriv->inProgressCreations++;
744     state.errors.clear();
745     state.completePending = true;
746
747     if (isRoot) 
748         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
749
750     enginePriv->referenceScarceResources();
751     state.vme.init(context, cc, start, creationContext);
752     QObject *rv = state.vme.execute(&state.errors);
753     enginePriv->dereferenceScarceResources();
754
755     if (rv) {
756         QDeclarativeData *ddata = QDeclarativeData::get(rv);
757         Q_ASSERT(ddata);
758         ddata->indestructible = true;
759     }
760
761     if (enginePriv->isDebugging && rv) {
762         if (!context->isInternal)
763             context->asQDeclarativeContextPrivate()->instances.append(rv);
764         QDeclarativeEngineDebugService::instance()->objectCreated(engine, rv);
765         if (isRoot) {
766             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, 
767                                               buildTypeNameForDebug(rv->metaObject()));
768             QDeclarativeData *data = QDeclarativeData::get(rv);
769             Q_ASSERT(data);
770             QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, 
771                                                   cc->url, data->lineNumber, data->columnNumber);
772         }
773     }
774
775     return rv;
776 }
777
778 void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *enginePriv,
779                                                  QObject *object, ConstructionState *state)
780 {
781     enginePriv->inProgressCreations++;
782     state->errors.clear();
783     state->completePending = true;
784
785     state->vme.initDeferred(object);
786     state->vme.execute(&state->errors);
787 }
788
789 void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state)
790 {
791     if (state->completePending) {
792         state->vme.complete();
793
794         state->completePending = false;
795
796         enginePriv->inProgressCreations--;
797
798         if (0 == enginePriv->inProgressCreations) {
799             while (enginePriv->erroredBindings) {
800                 enginePriv->warning(enginePriv->erroredBindings->error);
801                 enginePriv->erroredBindings->removeError();
802             }
803         }
804     }
805 }
806
807 /*!
808     This method provides more advanced control over component instance creation.
809     In general, programmers should use QDeclarativeComponent::create() to create a 
810     component.
811
812     Complete a component creation begin with QDeclarativeComponent::beginCreate().
813 */
814 void QDeclarativeComponent::completeCreate()
815 {
816     Q_D(QDeclarativeComponent);
817
818     d->completeCreate();
819 }
820
821 void QDeclarativeComponentPrivate::completeCreate()
822 {
823     if (state.completePending) {
824         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
825         complete(ep, &state);
826
827         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
828     }
829 }
830
831 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
832 : QObject(parent), prev(0), next(0)
833 {
834 }
835
836 QDeclarativeComponentAttached::~QDeclarativeComponentAttached()
837 {
838     if (prev) *prev = next;
839     if (next) next->prev = prev;
840     prev = 0;
841     next = 0;
842 }
843
844 /*!
845     \internal
846 */
847 QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObject *obj)
848 {
849     QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj);
850
851     QDeclarativeEngine *engine = qmlEngine(obj);
852     if (!engine)
853         return a;
854
855     if (QDeclarativeEnginePrivate::get(engine)->activeVME) { // XXX should only be allowed during begin
856         QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
857         a->add(&p->activeVME->componentAttached);
858     } else {
859         QDeclarativeData *d = QDeclarativeData::get(obj);
860         Q_ASSERT(d);
861         Q_ASSERT(d->context);
862         a->add(&d->context->componentAttached);
863     }
864
865     return a;
866 }
867
868 void QDeclarativeComponent::create(QDeclarativeIncubator &i, QDeclarativeContext *context,
869                                    QDeclarativeContext *forContext)
870 {
871     Q_D(QDeclarativeComponent);
872
873     if (!context) 
874         context = d->engine->rootContext();
875
876     QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
877     QDeclarativeContextData *forContextData = contextData;
878     if (forContext) forContextData = QDeclarativeContextData::get(forContext);
879
880     if (!contextData->isValid()) {
881         qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
882         return;
883     }
884
885     if (contextData->engine != d->engine) {
886         qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
887         return;
888     }
889
890     if (!isReady()) {
891         qWarning("QDeclarativeComponent: Component is not ready");
892         return;
893     }
894
895     i.clear();
896     QDeclarativeIncubatorPrivate *p = i.d;
897
898     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(d->engine);
899
900     p->component = d->cc; p->component->addref();
901     p->vme.init(contextData, d->cc, d->start, d->creationContext);
902
903     enginePriv->incubate(i, forContextData);
904 }
905
906 class QV8IncubatorResource : public QV8ObjectResource,
907                              public QDeclarativeIncubator
908 {
909 V8_RESOURCE_TYPE(IncubatorType)
910 public:
911     QV8IncubatorResource(QV8Engine *engine, IncubationMode = Asynchronous);
912
913     static v8::Handle<v8::Value> StatusChangedGetter(v8::Local<v8::String>, 
914                                                      const v8::AccessorInfo& info);
915     static v8::Handle<v8::Value> StatusGetter(v8::Local<v8::String>, 
916                                               const v8::AccessorInfo& info);
917     static v8::Handle<v8::Value> ObjectGetter(v8::Local<v8::String>, 
918                                               const v8::AccessorInfo& info);
919     static v8::Handle<v8::Value> ForceCompletionGetter(v8::Local<v8::String>, 
920                                                        const v8::AccessorInfo& info);
921     static v8::Handle<v8::Value> ForceCompletion(const v8::Arguments &args);
922
923     static void StatusChangedSetter(v8::Local<v8::String>, v8::Local<v8::Value> value, 
924                                     const v8::AccessorInfo& info);
925
926     void dispose();
927
928     v8::Persistent<v8::Object> me;
929     QDeclarativeGuard<QObject> parent;
930     v8::Persistent<v8::Value> valuemap;
931     v8::Persistent<v8::Object> qmlGlobal;
932 protected:
933     virtual void statusChanged(Status);
934     virtual void setInitialState(QObject *);
935 };
936
937 static void QDeclarativeComponent_setQmlParent(QObject *me, QObject *parent)
938 {
939     if (parent) {
940         me->setParent(parent);
941         typedef QDeclarativePrivate::AutoParentFunction APF;
942         QList<APF> functions = QDeclarativeMetaType::parentFunctions();
943
944         bool needParent = false;
945         for (int ii = 0; ii < functions.count(); ++ii) {
946             QDeclarativePrivate::AutoParentResult res = functions.at(ii)(me, parent);
947             if (res == QDeclarativePrivate::Parented) {
948                 needParent = false;
949                 break;
950             } else if (res == QDeclarativePrivate::IncompatibleParent) {
951                 needParent = true;
952             }
953         }
954         if (needParent) 
955             qWarning("QDeclarativeComponent: Created graphical object was not "
956                      "placed in the graphics scene.");
957     }
958 }
959
960 /*!
961     \qmlmethod object Component::createObject(Item parent, object properties)
962
963     Creates and returns an object instance of this component that will have
964     the given \a parent and \a properties. The \a properties argument is optional.
965     Returns null if object creation fails.
966
967     The object will be created in the same context as the one in which the component
968     was created. This function will always return null when called on components
969     which were not created in QML.
970
971     If you wish to create an object without setting a parent, specify \c null for
972     the \a parent value. Note that if the returned object is to be displayed, you 
973     must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} 
974     property, or else the object will not be visible.
975
976     If a \a parent is not provided to createObject(), a reference to the returned object must be held so that
977     it is not destroyed by the garbage collector.  This is true regardless of whether \l{Item::parent} is set afterwards,
978     since setting the Item parent does not change object ownership; only the graphical parent is changed.
979
980     As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a
981     map of initial property values for the created object. These values are applied before object
982     creation is finalized. (This is more efficient than setting property values after object creation,
983     particularly where large sets of property values are defined, and also allows property bindings
984     to be set up before the object is created.)
985
986     The \a properties argument is specified as a map of property-value items. For example, the code
987     below creates an object with initial \c x and \c y values of 100 and 200, respectively:
988
989     \js
990         var component = Qt.createComponent("Button.qml");
991         if (component.status == Component.Ready)
992             component.createObject(parent, {"x": 100, "y": 100});
993     \endjs
994
995     Dynamically created instances can be deleted with the \c destroy() method.
996     See \l {Dynamic Object Management in QML} for more information.
997 */
998 void QDeclarativeComponent::createObject(QDeclarativeV8Function *args)
999 {
1000     Q_D(QDeclarativeComponent);
1001     Q_ASSERT(d->engine);
1002     Q_ASSERT(args);
1003
1004     QObject *parent = 0;
1005     v8::Local<v8::Object> valuemap;
1006
1007     if (args->Length() >= 1) 
1008         parent = args->engine()->toQObject((*args)[0]);
1009
1010     if (args->Length() >= 2) {
1011         v8::Local<v8::Value> v = (*args)[1];
1012         if (!v->IsObject() || v->IsArray()) {
1013             qmlInfo(this) << tr("createObject: value is not an object");
1014             args->returnValue(v8::Null());
1015             return;
1016         }
1017         valuemap = v8::Local<v8::Object>::Cast(v);
1018     }
1019
1020     QV8Engine *v8engine = args->engine();
1021
1022     QDeclarativeContext *ctxt = creationContext();
1023     if (!ctxt) ctxt = d->engine->rootContext();
1024
1025     QObject *rv = beginCreate(ctxt);
1026
1027     if (!rv) {
1028         args->returnValue(v8::Null());
1029         return;
1030     }
1031
1032     QDeclarativeComponent_setQmlParent(rv, parent);
1033
1034     v8::Handle<v8::Value> ov = v8engine->newQObject(rv);
1035     Q_ASSERT(ov->IsObject());
1036     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
1037
1038     if (!valuemap.IsEmpty()) {
1039         QDeclarativeComponentExtension *e = componentExtension(v8engine);
1040         // Try catch isn't needed as the function itself is loaded with try/catch
1041         v8::Handle<v8::Value> function = e->initialProperties->Run(args->qmlGlobal());
1042         v8::Handle<v8::Value> args[] = { object, valuemap };
1043         v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
1044     }
1045
1046     d->completeCreate();
1047
1048     Q_ASSERT(QDeclarativeData::get(rv));
1049     QDeclarativeData::get(rv)->setImplicitDestructible();
1050
1051     if (!rv)
1052         args->returnValue(v8::Null());
1053     else
1054         args->returnValue(object);
1055 }
1056
1057 /*!
1058     \qmlmethod object Component::incubateObject(Item parent, object properties, enum mode)
1059
1060     Creates an incubator for instance of this component.  Incubators allow new component 
1061     instances to be instantiated asynchronously and not cause freezes in the UI.
1062
1063     The \a parent argument specifies the parent the created instance will have.  Omitting the 
1064     parameter or passing null will create anobject with no parent.  In this case, a reference
1065     to the created object must be maintained by the application of the object will eventually
1066     be garbage collected.
1067
1068     The \a properties argument is specified as a map of property-value items which will be
1069     set on the created object during its construction.  \a mode may be Qt.Synchronous or 
1070     Qt.Asynchronous and controls whether the instance is created synchronously or asynchronously. 
1071     The default is asynchronously.  In some circumstances, even if Qt.Synchronous is specified,
1072     the incubator may create the object asynchronously.  This happens if the component calling
1073     incubateObject() is itself being created asynchronously.
1074
1075     All three arguments are optional.
1076
1077     If successful, the method returns an incubator, otherwise null.  The incubator has the following
1078     properties:
1079
1080     \list
1081     \i status The status of the incubator.  Valid values are Component.Ready, Component.Loading and
1082        Component.Error.
1083     \i object The created object instance.  Will only be available once the incubator is in the 
1084        Ready status.
1085     \i onStatusChanged Specifies a callback function to be invoked when the status changes.  The
1086        status is passed as a parameter to the callback.
1087     \i forceCompletion() Call to complete incubation synchronously.
1088     \endlist
1089
1090     The following example demonstrates how to use an incubator:
1091
1092     \js
1093         var component = Qt.createComponent("Button.qml");
1094
1095         var incubator = component.incubateObject(parent, { x: 10, y: 10 });
1096         if (incubator.status != Component.Ready) {
1097             incubator.onStatusChanged = function(status) {
1098                 if (status == Component.Ready) {
1099                     print ("Object", incubator.object, "is now ready!");
1100                 }
1101             }
1102         } else {
1103             print ("Object", incubator.object, "is ready immediately!");
1104         }
1105     \endjs
1106 */
1107
1108 void QDeclarativeComponent::incubateObject(QDeclarativeV8Function *args)
1109 {
1110     Q_D(QDeclarativeComponent);
1111     Q_ASSERT(d->engine);
1112     Q_UNUSED(d);
1113     Q_ASSERT(args);
1114
1115     QObject *parent = 0;
1116     v8::Local<v8::Object> valuemap;
1117     QDeclarativeIncubator::IncubationMode mode = QDeclarativeIncubator::Asynchronous;
1118
1119     if (args->Length() >= 1) 
1120         parent = args->engine()->toQObject((*args)[0]);
1121
1122     if (args->Length() >= 2) {
1123         v8::Local<v8::Value> v = (*args)[1];
1124         if (v->IsNull()) {
1125         } else if (!v->IsObject() || v->IsArray()) {
1126             qmlInfo(this) << tr("createObject: value is not an object");
1127             args->returnValue(v8::Null());
1128             return;
1129         } else {
1130             valuemap = v8::Local<v8::Object>::Cast(v);
1131         }
1132     }
1133
1134     if (args->Length() >= 3) {
1135         quint32 v = (*args)[2]->Uint32Value();
1136         if (v == 0)
1137             mode = QDeclarativeIncubator::Asynchronous;
1138         else if (v == 1)
1139             mode = QDeclarativeIncubator::AsynchronousIfNested;
1140     }
1141
1142     QDeclarativeComponentExtension *e = componentExtension(args->engine());
1143     
1144     QV8IncubatorResource *r = new QV8IncubatorResource(args->engine(), mode);
1145     v8::Local<v8::Object> o = e->incubationConstructor->NewInstance();
1146     o->SetExternalResource(r);
1147
1148     if (!valuemap.IsEmpty()) {
1149         r->valuemap = qPersistentNew(valuemap);
1150         r->qmlGlobal = qPersistentNew(args->qmlGlobal());
1151     }
1152     r->parent = parent;
1153     r->me = qPersistentNew(o);
1154
1155     create(*r, creationContext());
1156
1157     if (r->status() == QDeclarativeIncubator::Null) {
1158         r->dispose();
1159         args->returnValue(v8::Null());
1160     } else {
1161         args->returnValue(o);
1162     }
1163 }
1164
1165 // XXX used by QSGLoader
1166 void QDeclarativeComponentPrivate::initializeObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *toCreate)
1167 {
1168     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1169     QV8Engine *v8engine = ep->v8engine();
1170
1171     v8::HandleScope handle_scope;
1172     v8::Context::Scope scope(v8engine->context());
1173     v8::Handle<v8::Value> ov = v8engine->newQObject(toCreate);
1174     Q_ASSERT(ov->IsObject());
1175     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
1176
1177     if (!valuemap.IsEmpty()) {
1178         QDeclarativeComponentExtension *e = componentExtension(v8engine);
1179         // Try catch isn't needed as the function itself is loaded with try/catch
1180         v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
1181         v8::Handle<v8::Value> args[] = { object, valuemap };
1182         v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
1183     }
1184
1185     QDeclarativeData *ddata = QDeclarativeData::get(toCreate);
1186     Q_ASSERT(ddata);
1187     ddata->setImplicitDestructible();
1188 }
1189
1190
1191 QDeclarativeComponentExtension::QDeclarativeComponentExtension(QV8Engine *engine)
1192 {
1193     v8::HandleScope handle_scope;
1194     v8::Context::Scope scope(engine->context());
1195
1196     forceCompletion = qPersistentNew(V8FUNCTION(QV8IncubatorResource::ForceCompletion, engine));
1197
1198     {
1199     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
1200     ft->InstanceTemplate()->SetHasExternalResource(true);
1201     ft->InstanceTemplate()->SetInternalFieldCount(1);
1202     ft->InstanceTemplate()->SetAccessor(v8::String::New("onStatusChanged"), 
1203                                         QV8IncubatorResource::StatusChangedGetter, 
1204                                         QV8IncubatorResource::StatusChangedSetter);
1205     ft->InstanceTemplate()->SetAccessor(v8::String::New("status"),
1206                                         QV8IncubatorResource::StatusGetter);
1207     ft->InstanceTemplate()->SetAccessor(v8::String::New("object"), 
1208                                         QV8IncubatorResource::ObjectGetter); 
1209     ft->InstanceTemplate()->SetAccessor(v8::String::New("forceCompletion"), 
1210                                         QV8IncubatorResource::ForceCompletionGetter); 
1211     incubationConstructor = qPersistentNew(ft->GetFunction());
1212     }
1213
1214     {
1215 #define INITIALPROPERTIES_SOURCE \
1216         "(function(object, values) {"\
1217             "try {"\
1218                 "for(var property in values) {" \
1219                     "try {"\
1220                         "var properties = property.split(\".\");"\
1221                         "var o = object;"\
1222                         "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
1223                             "o = o[properties[ii]];"\
1224                         "}"\
1225                         "o[properties[properties.length - 1]] = values[property];"\
1226                     "} catch(e) {}"\
1227                 "}"\
1228             "} catch(e) {}"\
1229         "})"
1230     initialProperties = qPersistentNew(engine->qmlModeCompile(QLatin1String(INITIALPROPERTIES_SOURCE)));
1231 #undef INITIALPROPERTIES_SOURCE
1232     }
1233 }
1234
1235 v8::Handle<v8::Value> QV8IncubatorResource::ObjectGetter(v8::Local<v8::String>, 
1236                                                           const v8::AccessorInfo& info)
1237 {
1238     QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
1239     return r->engine->newQObject(r->object());
1240 }
1241
1242 v8::Handle<v8::Value> QV8IncubatorResource::ForceCompletionGetter(v8::Local<v8::String>, 
1243                                                                   const v8::AccessorInfo& info)
1244 {
1245     QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
1246     return componentExtension(r->engine)->forceCompletion;
1247 }
1248
1249 v8::Handle<v8::Value> QV8IncubatorResource::ForceCompletion(const v8::Arguments &args) 
1250 {
1251     QV8IncubatorResource *r = v8_resource_cast<QV8IncubatorResource>(args.This());
1252     if (!r)
1253         V8THROW_TYPE("Not an incubator object");
1254
1255     r->forceCompletion();
1256
1257     return v8::Undefined();
1258 }
1259
1260 v8::Handle<v8::Value> QV8IncubatorResource::StatusGetter(v8::Local<v8::String>, 
1261                                                          const v8::AccessorInfo& info)
1262 {
1263     QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
1264     return v8::Integer::NewFromUnsigned(r->status());
1265 }
1266
1267 v8::Handle<v8::Value> QV8IncubatorResource::StatusChangedGetter(v8::Local<v8::String>, 
1268                                                                  const v8::AccessorInfo& info)
1269 {
1270     return info.This()->GetInternalField(0);
1271 }
1272
1273 void QV8IncubatorResource::StatusChangedSetter(v8::Local<v8::String>, v8::Local<v8::Value> value, 
1274                                                 const v8::AccessorInfo& info)
1275 {
1276     info.This()->SetInternalField(0, value);
1277 }
1278
1279 QDeclarativeComponentExtension::~QDeclarativeComponentExtension()
1280 {
1281     qPersistentDispose(incubationConstructor);
1282     qPersistentDispose(initialProperties);
1283     qPersistentDispose(forceCompletion);
1284 }
1285
1286 QV8IncubatorResource::QV8IncubatorResource(QV8Engine *engine, IncubationMode m)
1287 : QV8ObjectResource(engine), QDeclarativeIncubator(m)
1288 {
1289 }
1290
1291 void QV8IncubatorResource::setInitialState(QObject *o)
1292 {
1293     QDeclarativeComponent_setQmlParent(o, parent);
1294
1295     if (!valuemap.IsEmpty()) {
1296         QDeclarativeComponentExtension *e = componentExtension(engine);
1297
1298         v8::HandleScope handle_scope;
1299         v8::Context::Scope scope(engine->context());
1300
1301         v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
1302         v8::Handle<v8::Value> args[] = { engine->newQObject(o), valuemap };
1303         v8::Handle<v8::Function>::Cast(function)->Call(engine->global(), 2, args);
1304
1305         qPersistentDispose(valuemap);
1306         qPersistentDispose(qmlGlobal);
1307     }
1308 }
1309     
1310 void QV8IncubatorResource::dispose()
1311 {
1312     qPersistentDispose(valuemap);
1313     qPersistentDispose(qmlGlobal);
1314     // No further status changes are forthcoming, so we no long need a self reference
1315     qPersistentDispose(me);
1316 }
1317
1318 void QV8IncubatorResource::statusChanged(Status s)
1319 {
1320     if (s == Ready) {
1321         Q_ASSERT(QDeclarativeData::get(object()));
1322         QDeclarativeData::get(object())->setImplicitDestructible();
1323     }
1324
1325     if (!me.IsEmpty()) { // Will be false in synchronous mode
1326         v8::HandleScope scope;
1327         v8::Local<v8::Value> callback = me->GetInternalField(0);
1328
1329         if (!callback.IsEmpty() && !callback->IsUndefined()) {
1330
1331             if (callback->IsFunction()) {
1332                 v8::Context::Scope context_scope(engine->context());
1333                 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(callback);
1334                 v8::Handle<v8::Value> args[] = { v8::Integer::NewFromUnsigned(s) };
1335                 v8::TryCatch tc;
1336                 f->Call(me, 1, args);
1337                 if (tc.HasCaught()) {
1338                     QDeclarativeError error;
1339                     QDeclarativeExpressionPrivate::exceptionToError(tc.Message(), error);
1340                     QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(engine->engine()),
1341                                                        error);
1342                 }
1343             }
1344         }
1345     }
1346
1347     if (s == Ready || s == Error) 
1348         dispose();
1349 }
1350
1351 QT_END_NAMESPACE