Improve QJSValueIterator implementation.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecomponent.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 "private/qdeclarativecomponent_p.h"
44
45 #include "private/qdeclarativecompiler_p.h"
46 #include "private/qdeclarativecontext_p.h"
47 #include "private/qdeclarativeengine_p.h"
48 #include "private/qdeclarativevme_p.h"
49 #include "qdeclarative.h"
50 #include "qdeclarativeengine.h"
51 #include "private/qdeclarativebinding_p.h"
52 #include "private/qdeclarativebinding_p_p.h"
53 #include "private/qdeclarativeglobal_p.h"
54 #include "private/qdeclarativescriptparser_p.h"
55 #include "private/qdeclarativedebugtrace_p.h"
56 #include "private/qdeclarativeenginedebug_p.h"
57
58 #include <QStack>
59 #include <QStringList>
60 #include <QtCore/qdebug.h>
61 #include <QApplication>
62 #include <qdeclarativeinfo.h>
63
64 QT_BEGIN_NAMESPACE
65
66 class QByteArray;
67
68 /*!
69     \class QDeclarativeComponent
70     \since 4.7
71     \brief The QDeclarativeComponent class encapsulates a QML component definition.
72     \mainclass
73
74     Components are reusable, encapsulated QML elements with well-defined interfaces.
75     They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
76
77     A QDeclarativeComponent instance can be created from a QML file.
78     For example, if there is a \c main.qml file like this:
79
80     \qml
81     import QtQuick 1.0
82
83     Item {
84         width: 200
85         height: 200
86     }
87     \endqml
88
89     The following code loads this QML file as a component, creates an instance of
90     this component using create(), and then queries the \l Item's \l {Item::}{width}
91     value:
92
93     \code
94     QDeclarativeEngine *engine = new QDeclarativeEngine;
95     QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
96
97     QObject *myObject = component.create();
98     QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
99     int width = item->width();  // width = 200
100     \endcode
101
102
103     \section2 Network Components
104
105     If the URL passed to QDeclarativeComponent is a network resource, or if the QML document references a
106     network resource, the QDeclarativeComponent has to fetch the network data before it is able to create
107     objects.  In this case, the QDeclarativeComponent will have a \l {QDeclarativeComponent::Loading}{Loading}
108     \l {QDeclarativeComponent::status()}{status}.  An application will have to wait until the component
109     is \l {QDeclarativeComponent::Ready}{Ready} before calling \l {QDeclarativeComponent::create()}.
110
111     The following example shows how to load a QML file from a network resource.  After creating
112     the QDeclarativeComponent, it tests whether the component is loading.  If it is, it connects to the
113     QDeclarativeComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method
114     directly. Note that QDeclarativeComponent::isLoading() may be false for a network component if the
115     component has been cached and is ready immediately.
116
117     \code
118     MyApplication::MyApplication()
119     {
120         // ...
121         component = new QDeclarativeComponent(engine, QUrl("http://www.example.com/main.qml"));
122         if (component->isLoading())
123             QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
124                              this, SLOT(continueLoading()));
125         else
126             continueLoading();
127     }
128
129     void MyApplication::continueLoading()
130     {
131         if (component->isError()) {
132             qWarning() << component->errors();
133         } else {
134             QObject *myObject = component->create();
135         }
136     }
137     \endcode
138
139     \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code}
140 */
141
142 /*!
143     \qmlclass Component QDeclarativeComponent
144     \ingroup qml-utility-elements
145     \since 4.7
146     \brief The Component element encapsulates a QML component definition.
147
148     Components are reusable, encapsulated QML elements with well-defined interfaces.
149
150     Components are often defined by \l {qdeclarativedocuments.html}{component files} -
151     that is, \c .qml files. The \e Component element essentially allows QML components
152     to be defined inline, within a \l {QML Document}{QML document}, rather than as a separate QML file.
153     This may be useful for reusing a small component within a QML file, or for defining
154     a component that logically belongs with other QML components within a file.
155
156     For example, here is a component that is used by multiple \l Loader objects.
157     It contains a single item, a \l Rectangle:
158
159     \snippet doc/src/snippets/declarative/component.qml 0
160
161     Notice that while a \l Rectangle by itself would be automatically 
162     rendered and displayed, this is not the case for the above rectangle
163     because it is defined inside a \c Component. The component encapsulates the
164     QML elements within, as if they were defined in a separate QML
165     file, and is not loaded until requested (in this case, by the
166     two \l Loader objects).
167
168     Defining a \c Component is similar to defining a \l {QML Document}{QML document}.
169     A QML document has a single top-level item that defines the behaviors and
170     properties of that component, and cannot define properties or behaviors outside
171     of that top-level item. In the same way, a \c Component definition contains a single
172     top level item (which in the above example is a \l Rectangle) and cannot define any
173     data outside of this item, with the exception of an \e id (which in the above example
174     is \e redSquare).
175
176     The \c Component element is commonly used to provide graphical components
177     for views. For example, the ListView::delegate property requires a \c Component
178     to specify how each list item is to be displayed.
179
180     \c Component objects can also be created dynamically using
181     \l{QML:Qt::createComponent()}{Qt.createComponent()}.
182 */
183
184 /*!
185     \qmlattachedsignal Component::onCompleted()
186
187     Emitted after component "startup" has completed.  This can be used to
188     execute script code at startup, once the full QML environment has been
189     established.
190
191     The \c {Component::onCompleted} attached property can be applied to
192     any element.  The order of running the \c onCompleted scripts is
193     undefined.
194
195     \qml
196     Rectangle {
197         Component.onCompleted: console.log("Completed Running!")
198         Rectangle {
199             Component.onCompleted: console.log("Nested Completed Running!")
200         }
201     }
202     \endqml
203 */
204
205 /*!
206     \qmlattachedsignal Component::onDestruction()
207
208     Emitted as the component begins destruction.  This can be used to undo
209     work done in the onCompleted signal, or other imperative code in your
210     application.
211
212     The \c {Component::onDestruction} attached property can be applied to
213     any element.  However, it applies to the destruction of the component as
214     a whole, and not the destruction of the specific object.  The order of
215     running the \c onDestruction scripts is undefined.
216
217     \qml
218     Rectangle {
219         Component.onDestruction: console.log("Destruction Beginning!")
220         Rectangle {
221             Component.onDestruction: console.log("Nested Destruction Beginning!")
222         }
223     }
224     \endqml
225
226     \sa QtDeclarative
227 */
228
229 /*!
230     \enum QDeclarativeComponent::Status
231     
232     Specifies the loading status of the QDeclarativeComponent.
233
234     \value Null This QDeclarativeComponent has no data.  Call loadUrl() or setData() to add QML content.
235     \value Ready This QDeclarativeComponent is ready and create() may be called.
236     \value Loading This QDeclarativeComponent is loading network data.
237     \value Error An error has occurred.  Call errors() to retrieve a list of \{QDeclarativeError}{errors}.
238 */
239
240 void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *)
241 {
242     Q_Q(QDeclarativeComponent);
243
244     Q_ASSERT(typeData);
245
246     fromTypeData(typeData);
247     typeData = 0;
248
249     emit q->statusChanged(q->status());
250 }
251
252 void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p)
253 {
254     Q_Q(QDeclarativeComponent);
255
256     progress = p;
257
258     emit q->progressChanged(p);
259 }
260
261 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data)
262 {
263     url = data->finalUrl();
264     QDeclarativeCompiledData *c = data->compiledData();
265
266     if (!c) {
267         Q_ASSERT(data->isError());
268         state.errors = data->errors();
269     } else {
270         cc = c;
271     }
272
273     data->release();
274 }
275
276 void QDeclarativeComponentPrivate::clear()
277 {
278     if (typeData) {
279         typeData->unregisterCallback(this);
280         typeData->release();
281         typeData = 0;
282     }
283         
284     if (cc) { 
285         cc->release();
286         cc = 0;
287     }
288 }
289
290 /*!
291     \internal
292 */
293 QDeclarativeComponent::QDeclarativeComponent(QObject *parent)
294     : QObject(*(new QDeclarativeComponentPrivate), parent)
295 {
296 }
297
298 /*!
299     Destruct the QDeclarativeComponent.
300 */
301 QDeclarativeComponent::~QDeclarativeComponent()
302 {
303     Q_D(QDeclarativeComponent);
304
305     if (d->state.completePending) {
306         qWarning("QDeclarativeComponent: Component destroyed while completion pending");
307         d->completeCreate();
308     }
309
310     if (d->typeData) {
311         d->typeData->unregisterCallback(d);
312         d->typeData->release();
313     }
314     if (d->cc)
315         d->cc->release();
316 }
317
318 /*!
319     \qmlproperty enumeration Component::status
320     This property holds the status of component loading.  It can be one of:
321     \list
322     \o Component.Null - no data is available for the component
323     \o Component.Ready - the component has been loaded, and can be used to create instances.
324     \o Component.Loading - the component is currently being loaded
325     \o Component.Error - an error occurred while loading the component.
326                Calling errorString() will provide a human-readable description of any errors.
327     \endlist
328  */
329
330 /*!
331     \property QDeclarativeComponent::status
332     The component's current \l{QDeclarativeComponent::Status} {status}.
333  */
334 QDeclarativeComponent::Status QDeclarativeComponent::status() const
335 {
336     Q_D(const QDeclarativeComponent);
337
338     if (d->typeData)
339         return Loading;
340     else if (!d->state.errors.isEmpty())
341         return Error;
342     else if (d->engine && d->cc)
343         return Ready;
344     else
345         return Null;
346 }
347
348 /*!
349     Returns true if status() == QDeclarativeComponent::Null.
350 */
351 bool QDeclarativeComponent::isNull() const
352 {
353     return status() == Null;
354 }
355
356 /*!
357     Returns true if status() == QDeclarativeComponent::Ready.
358 */
359 bool QDeclarativeComponent::isReady() const
360 {
361     return status() == Ready;
362 }
363
364 /*!
365     Returns true if status() == QDeclarativeComponent::Error.
366 */
367 bool QDeclarativeComponent::isError() const
368 {
369     return status() == Error;
370 }
371
372 /*!
373     Returns true if status() == QDeclarativeComponent::Loading.
374 */
375 bool QDeclarativeComponent::isLoading() const
376 {
377     return status() == Loading;
378 }
379
380 /*!
381     \qmlproperty real Component::progress
382     The progress of loading the component, from 0.0 (nothing loaded)
383     to 1.0 (finished).
384 */
385
386 /*!
387     \property QDeclarativeComponent::progress
388     The progress of loading the component, from 0.0 (nothing loaded)
389     to 1.0 (finished).
390 */
391 qreal QDeclarativeComponent::progress() const
392 {
393     Q_D(const QDeclarativeComponent);
394     return d->progress;
395 }
396
397 /*!
398     \fn void QDeclarativeComponent::progressChanged(qreal progress)
399
400     Emitted whenever the component's loading progress changes.  \a progress will be the
401     current progress between 0.0 (nothing loaded) and 1.0 (finished).
402 */
403
404 /*!
405     \fn void QDeclarativeComponent::statusChanged(QDeclarativeComponent::Status status)
406
407     Emitted whenever the component's status changes.  \a status will be the
408     new status.
409 */
410
411 /*!
412     Create a QDeclarativeComponent with no data and give it the specified
413     \a engine and \a parent. Set the data with setData().
414 */
415 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QObject *parent)
416     : QObject(*(new QDeclarativeComponentPrivate), parent)
417 {
418     Q_D(QDeclarativeComponent);
419     d->engine = engine;
420 }
421
422 /*!
423     Create a QDeclarativeComponent from the given \a url and give it the
424     specified \a parent and \a engine.
425
426     Ensure that the URL provided is full and correct, in particular, use
427     \l QUrl::fromLocalFile() when loading a file from the local filesystem.
428
429     \sa loadUrl()
430 */
431 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QUrl &url, QObject *parent)
432 : QObject(*(new QDeclarativeComponentPrivate), parent)
433 {
434     Q_D(QDeclarativeComponent);
435     d->engine = engine;
436     loadUrl(url);
437 }
438
439 /*!
440     Create a QDeclarativeComponent from the given \a fileName and give it the specified 
441     \a parent and \a engine.
442
443     \sa loadUrl()
444 */
445 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QString &fileName, 
446                            QObject *parent)
447 : QObject(*(new QDeclarativeComponentPrivate), parent)
448 {
449     Q_D(QDeclarativeComponent);
450     d->engine = engine;
451     loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
452 }
453
454 /*!
455     \internal
456 */
457 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, QObject *parent)
458     : QObject(*(new QDeclarativeComponentPrivate), parent)
459 {
460     Q_D(QDeclarativeComponent);
461     d->engine = engine;
462     d->cc = cc;
463     cc->addref();
464     d->start = start;
465     d->url = cc->url;
466     d->progress = 1.0;
467 }
468
469 /*!
470     Sets the QDeclarativeComponent to use the given QML \a data.  If \a url
471     is provided, it is used to set the component name and to provide
472     a base path for items resolved by this component.
473 */
474 void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url)
475 {
476     Q_D(QDeclarativeComponent);
477
478     d->clear();
479
480     d->url = url;
481
482     QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url);
483     
484     if (typeData->isCompleteOrError()) {
485         d->fromTypeData(typeData);
486     } else {
487         d->typeData = typeData;
488         d->typeData->registerCallback(d);
489     }
490
491     d->progress = 1.0;
492     emit statusChanged(status());
493     emit progressChanged(d->progress);
494 }
495
496 /*!
497 Returns the QDeclarativeContext the component was created in.  This is only
498 valid for components created directly from QML.
499 */
500 QDeclarativeContext *QDeclarativeComponent::creationContext() const
501 {
502     Q_D(const QDeclarativeComponent);
503     if(d->creationContext)
504         return d->creationContext->asQDeclarativeContext();
505
506     return qmlContext(this);
507 }
508
509 /*!
510     Load the QDeclarativeComponent from the provided \a url.
511
512     Ensure that the URL provided is full and correct, in particular, use
513     \l QUrl::fromLocalFile() when loading a file from the local filesystem.
514 */
515 void QDeclarativeComponent::loadUrl(const QUrl &url)
516 {
517     Q_D(QDeclarativeComponent);
518
519     d->clear();
520
521     if ((url.isRelative() && !url.isEmpty())
522     || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
523         d->url = d->engine->baseUrl().resolved(url);
524     else
525         d->url = url;
526
527     if (url.isEmpty()) {
528         QDeclarativeError error;
529         error.setDescription(tr("Invalid empty URL"));
530         d->state.errors << error;
531         return;
532     }
533
534     QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url);
535
536     if (data->isCompleteOrError()) {
537         d->fromTypeData(data);
538         d->progress = 1.0;
539     } else {
540         d->typeData = data;
541         d->typeData->registerCallback(d);
542         d->progress = data->progress();
543     }
544
545     emit statusChanged(status());
546     emit progressChanged(d->progress);
547 }
548
549 /*!
550     Return the list of errors that occurred during the last compile or create
551     operation.  An empty list is returned if isError() is not set.
552 */
553 QList<QDeclarativeError> QDeclarativeComponent::errors() const
554 {
555     Q_D(const QDeclarativeComponent);
556     if (isError())
557         return d->state.errors;
558     else
559         return QList<QDeclarativeError>();
560 }
561
562 /*!
563     \qmlmethod string Component::errorString()
564
565     Returns a human-readable description of any errors.
566
567     The string includes the file, location, and description of each error.
568     If multiple errors are present they are separated by a newline character.
569
570     If no errors are present, an empty string is returned.
571 */
572
573 /*!
574     \internal
575     errorString is only meant as a way to get the errors in script
576 */
577 QString QDeclarativeComponent::errorString() const
578 {
579     Q_D(const QDeclarativeComponent);
580     QString ret;
581     if(!isError())
582         return ret;
583     foreach(const QDeclarativeError &e, d->state.errors) {
584         ret += e.url().toString() + QLatin1Char(':') +
585                QString::number(e.line()) + QLatin1Char(' ') +
586                e.description() + QLatin1Char('\n');
587     }
588     return ret;
589 }
590
591 /*!
592     \qmlproperty url Component::url
593     The component URL.  This is the URL that was used to construct the component.
594 */
595
596 /*!
597     \property QDeclarativeComponent::url
598     The component URL.  This is the URL passed to either the constructor,
599     or the loadUrl() or setData() methods.
600 */
601 QUrl QDeclarativeComponent::url() const
602 {
603     Q_D(const QDeclarativeComponent);
604     return d->url;
605 }
606
607 /*!
608     \internal
609 */
610 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject *parent)
611     : QObject(dd, parent)
612 {
613 }
614
615 /*!
616     \qmlmethod object Component::createObject(Item parent, object properties)
617
618     Creates and returns an object instance of this component that will have
619     the given \a parent and \a properties. The \a properties argument is optional.
620     Returns null if object creation fails.
621
622     The object will be created in the same context as the one in which the component
623     was created. This function will always return null when called on components
624     which were not created in QML.
625
626     If you wish to create an object without setting a parent, specify \c null for
627     the \a parent value. Note that if the returned object is to be displayed, you 
628     must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} 
629     property, or else the object will not be visible.
630
631     If a \a parent is not provided to createObject(), a reference to the returned object must be held so that
632     it is not destroyed by the garbage collector.  This is true regardless of whether \l{Item::parent} is set afterwards,
633     since setting the Item parent does not change object ownership; only the graphical parent is changed.
634
635     As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a
636     map of initial property values for the created object. These values are applied before object
637     creation is finalized. (This is more efficient than setting property values after object creation,
638     particularly where large sets of property values are defined, and also allows property bindings
639     to be set up before the object is created.)
640
641     The \a properties argument is specified as a map of property-value items. For example, the code
642     below creates an object with initial \c x and \c y values of 100 and 200, respectively:
643
644     \js
645         var component = Qt.createComponent("Button.qml");
646         if (component.status == Component.Ready)
647             component.createObject(parent, {"x": 100, "y": 100});
648     \endjs
649
650     Dynamically created instances can be deleted with the \c destroy() method.
651     See \l {Dynamic Object Management in QML} for more information.
652 */
653
654 /*!
655     \internal
656     A version of create which returns a scriptObject, for use in script.
657     This function will only work on components created in QML.
658
659     Sets graphics object parent because forgetting to do this is a frequent
660     and serious problem.
661 */
662 void QDeclarativeComponent::createObject(QDeclarativeV8Function *args)
663 {
664     Q_ASSERT(args);
665
666 #define RETURN(result) { args->returnValue((result)); return; }
667
668     Q_D(QDeclarativeComponent);
669
670     Q_ASSERT(d->engine);
671
672     QDeclarativeEngine *engine = d->engine;
673     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
674     QV8Engine *v8engine = ep->v8engine();
675
676     QDeclarativeContext *ctxt = creationContext();
677     if (!ctxt) ctxt = engine->rootContext();
678
679     v8::Local<v8::Object> valuemap;
680     if (args->Length() >= 2) {
681         v8::Local<v8::Value> v = (*args)[1];
682         if (!v->IsObject() || v->IsArray()) {
683             qmlInfo(this) << tr("createObject: value is not an object");
684             RETURN(v8::Null());
685         }
686         valuemap = v8::Local<v8::Object>::Cast(v);
687     }
688
689     QObject *parent = args->Length()?v8engine->toQObject((*args)[0]):0;
690
691     QObject *ret = beginCreate(ctxt);
692     if (!ret) {
693         completeCreate();
694         RETURN(v8::Null());
695     }
696
697     if (parent) {
698         ret->setParent(parent);
699
700         QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
701
702         bool needParent = false;
703
704         for (int ii = 0; ii < functions.count(); ++ii) {
705             QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent);
706             if (res == QDeclarativePrivate::Parented) {
707                 needParent = false;
708                 break;
709             } else if (res == QDeclarativePrivate::IncompatibleParent) {
710                 needParent = true;
711             }
712         }
713
714         if (needParent)
715             qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
716     }
717
718     v8::Handle<v8::Value> ov = v8engine->newQObject(ret);
719     Q_ASSERT(ov->IsObject());
720     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
721
722     if (!valuemap.IsEmpty()) {
723
724 #define SET_ARGS_SOURCE \
725         "(function(object, values) {"\
726             "try {"\
727                 "for(var property in values) {"\
728                     "try {"\
729                         "var properties = property.split(\".\");"\
730                         "var o = object;"\
731                         "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
732                             "o = o[properties[ii]];"\
733                         "}"\
734                         "o[properties[properties.length - 1]] = values[property];"\
735                     "} catch(e) {}"\
736                 "}"\
737             "} catch(e) {}"\
738         "})"
739
740         v8::Local<v8::Script> script = v8engine->qmlModeCompile(SET_ARGS_SOURCE);
741         v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(script->Run(args->qmlGlobal()));
742
743         // Try catch isn't needed as the function itself is loaded with try/catch
744         v8::Handle<v8::Value> args[] = { object, valuemap };
745         function->Call(v8engine->global(), 2, args);
746     }
747
748     completeCreate();
749     
750     QDeclarativeData *ddata = QDeclarativeData::get(ret);
751     Q_ASSERT(ddata);
752     ddata->setImplicitDestructible();
753
754     RETURN(object);
755
756 #undef RETURN
757 }
758
759 /*!
760     Create an object instance from this component.  Returns 0 if creation
761     failed.  \a context specifies the context within which to create the object
762     instance.  
763
764     If \a context is 0 (the default), it will create the instance in the
765     engine' s \l {QDeclarativeEngine::rootContext()}{root context}.
766 */
767 QObject *QDeclarativeComponent::create(QDeclarativeContext *context)
768 {
769     Q_D(QDeclarativeComponent);
770
771     if (!context)
772         context = d->engine->rootContext();
773
774     QObject *rv = beginCreate(context);
775     completeCreate();
776     return rv;
777 }
778
779 /*!
780     This method provides more advanced control over component instance creation.
781     In general, programmers should use QDeclarativeComponent::create() to create a 
782     component.
783
784     Create an object instance from this component.  Returns 0 if creation
785     failed.  \a context specifies the context within which to create the object
786     instance.  
787
788     When QDeclarativeComponent constructs an instance, it occurs in three steps:
789     \list 1
790     \i The object hierarchy is created, and constant values are assigned.
791     \i Property bindings are evaluated for the the first time.
792     \i If applicable, QDeclarativeParserStatus::componentComplete() is called on objects.
793     \endlist 
794     QDeclarativeComponent::beginCreate() differs from QDeclarativeComponent::create() in that it
795     only performs step 1.  QDeclarativeComponent::completeCreate() must be called to 
796     complete steps 2 and 3.
797
798     This breaking point is sometimes useful when using attached properties to
799     communicate information to an instantiated component, as it allows their
800     initial values to be configured before property bindings take effect.
801 */
802 QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *context)
803 {
804     Q_D(QDeclarativeComponent);
805     QObject *rv = d->beginCreate(context?QDeclarativeContextData::get(context):0, QBitField());
806     if (rv) {
807         QDeclarativeData *ddata = QDeclarativeData::get(rv);
808         Q_ASSERT(ddata);
809         ddata->indestructible = true;
810     }
811     return rv;
812 }
813
814 QObject *
815 QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, const QBitField &bindings)
816 {
817     Q_Q(QDeclarativeComponent);
818     if (!context) {
819         qWarning("QDeclarativeComponent: Cannot create a component in a null context");
820         return 0;
821     }
822
823     if (!context->isValid()) {
824         qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
825         return 0;
826     }
827
828     if (context->engine != engine) {
829         qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
830         return 0;
831     }
832
833     if (state.completePending) {
834         qWarning("QDeclarativeComponent: Cannot create new component instance before completing the previous");
835         return 0;
836     }
837
838     if (!q->isReady()) {
839         qWarning("QDeclarativeComponent: Component is not ready");
840         return 0;
841     }
842
843     return begin(context, creationContext, cc, start, &state, 0, bindings);
844 }
845
846 /*
847     Try to do what's necessary for a reasonable display of the type
848     name, but no more (just enough for the client to do more extensive cleanup).
849
850     Should only be called when debugging is enabled.
851 */
852 static inline QString buildTypeNameForDebug(const QMetaObject *metaObject)
853 {
854     static const QString qmlMarker(QLatin1String("_QML"));
855     static const QChar underscore(QLatin1Char('_'));
856     static const QChar asterisk(QLatin1Char('*'));
857     QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaObject);
858     QString typeName = type ? QLatin1String(type->qmlTypeName()) : QLatin1String(metaObject->className());
859     if (!type) {
860         //### optimize further?
861         int marker = typeName.indexOf(qmlMarker);
862         if (marker != -1 && marker < typeName.count() - 1) {
863             if (typeName[marker + 1] == underscore) {
864                 const QString className = typeName.left(marker) + asterisk;
865                 type = QDeclarativeMetaType::qmlType(QMetaType::type(className.toLatin1()));
866                 if (type)
867                     typeName = QLatin1String(type->qmlTypeName());
868             }
869         }
870     }
871     return typeName;
872 }
873
874 QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext, 
875                                               QDeclarativeContextData *componentCreationContext,
876                                               QDeclarativeCompiledData *component, int start, 
877                                               ConstructionState *state, QList<QDeclarativeError> *errors,
878                                               const QBitField &bindings)
879 {
880     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentContext->engine);
881     bool isRoot = !enginePriv->inBeginCreate;
882
883     Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided
884     Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided
885
886     if (isRoot)
887         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
888
889     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
890     ctxt->isInternal = true;
891     ctxt->url = component->url;
892     ctxt->imports = component->importCache;
893
894     // Nested global imports
895     if (componentCreationContext && start != -1) {
896         ctxt->importedScripts = componentCreationContext->importedScripts;
897         for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
898             ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
899     }
900
901     component->importCache->addref();
902     ctxt->setParent(parentContext);
903
904     enginePriv->inBeginCreate = true;
905
906     QDeclarativeVME vme;
907     enginePriv->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
908     QObject *rv = vme.run(ctxt, component, start, bindings);
909     enginePriv->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
910
911     if (vme.isError()) {
912        if(errors) *errors = vme.errors();
913        else state->errors = vme.errors();
914     }
915
916     if (isRoot) {
917         enginePriv->inBeginCreate = false;
918
919         state->bindValues = enginePriv->bindValues;
920         state->parserStatus = enginePriv->parserStatus;
921         state->finalizedParserStatus = enginePriv->finalizedParserStatus;
922         state->componentAttached = enginePriv->componentAttached;
923         if (state->componentAttached)
924             state->componentAttached->prev = &state->componentAttached;
925
926         enginePriv->componentAttached = 0;
927         enginePriv->bindValues.clear();
928         enginePriv->parserStatus.clear();
929         enginePriv->finalizedParserStatus.clear();
930         state->completePending = true;
931         enginePriv->inProgressCreations++;
932     }
933
934     if (enginePriv->isDebugging && rv) {
935         if  (!parentContext->isInternal)
936             parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
937         QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
938         if (isRoot) {
939             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, buildTypeNameForDebug(rv->metaObject()));
940             QDeclarativeData *data = QDeclarativeData::get(rv);
941             QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, component->url, data ? data->lineNumber : -1);
942         }
943     }
944
945     return rv;
946 }
947
948 void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *enginePriv,
949                                                  QObject *object, ConstructionState *state)
950 {
951     bool isRoot = !enginePriv->inBeginCreate;
952     enginePriv->inBeginCreate = true;
953
954     QDeclarativeVME vme;
955     vme.runDeferred(object);
956
957     if (vme.isError()) 
958         state->errors = vme.errors();
959
960     if (isRoot) {
961         enginePriv->inBeginCreate = false;
962
963         state->bindValues = enginePriv->bindValues;
964         state->parserStatus = enginePriv->parserStatus;
965         state->finalizedParserStatus = enginePriv->finalizedParserStatus;
966         state->componentAttached = enginePriv->componentAttached;
967         if (state->componentAttached)
968             state->componentAttached->prev = &state->componentAttached;
969
970         enginePriv->componentAttached = 0;
971         enginePriv->bindValues.clear();
972         enginePriv->parserStatus.clear();
973         enginePriv->finalizedParserStatus.clear();
974         state->completePending = true;
975         enginePriv->inProgressCreations++;
976     }
977 }
978
979 void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state)
980 {
981     if (state->completePending) {
982
983         for (int ii = 0; ii < state->bindValues.count(); ++ii) {
984             QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bv = 
985                 state->bindValues.at(ii);
986             for (int jj = 0; jj < bv.count; ++jj) {
987                 if(bv.at(jj)) {
988                     bv.at(jj)->m_mePtr = 0;
989                     bv.at(jj)->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | 
990                                                 QDeclarativePropertyPrivate::DontRemoveBinding);
991                 }
992             }
993             QDeclarativeEnginePrivate::clear(bv);
994         }
995
996         for (int ii = 0; ii < state->parserStatus.count(); ++ii) {
997             QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> ps = 
998                 state->parserStatus.at(ii);
999
1000             for (int jj = ps.count - 1; jj >= 0; --jj) {
1001                 QDeclarativeParserStatus *status = ps.at(jj);
1002                 if (status && status->d) {
1003                     status->d = 0;
1004                     status->componentComplete();
1005                 }
1006             }
1007             QDeclarativeEnginePrivate::clear(ps);
1008         }
1009
1010         for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) {
1011             QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii);
1012             QObject *obj = status.first;
1013             if (obj) {
1014                 void *args[] = { 0 };
1015                 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
1016                                       status.second, args);
1017             }
1018         }
1019
1020         //componentComplete() can register additional finalization objects
1021         //that are then never handled. Handle them manually here.
1022         if (1 == enginePriv->inProgressCreations) {
1023             for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) {
1024                 QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii);
1025                 QObject *obj = status.first;
1026                 if (obj) {
1027                     void *args[] = { 0 };
1028                     QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
1029                                           status.second, args);
1030                 }
1031             }
1032             enginePriv->finalizedParserStatus.clear();
1033         }
1034
1035         while (state->componentAttached) {
1036             QDeclarativeComponentAttached *a = state->componentAttached;
1037             a->rem();
1038             QDeclarativeData *d = QDeclarativeData::get(a->parent());
1039             Q_ASSERT(d);
1040             Q_ASSERT(d->context);
1041             a->add(&d->context->componentAttached);
1042             emit a->completed();
1043         }
1044
1045         state->bindValues.clear();
1046         state->parserStatus.clear();
1047         state->finalizedParserStatus.clear();
1048         state->completePending = false;
1049
1050         enginePriv->inProgressCreations--;
1051         if (0 == enginePriv->inProgressCreations) {
1052             while (enginePriv->erroredBindings) {
1053                 enginePriv->warning(enginePriv->erroredBindings->error);
1054                 enginePriv->erroredBindings->removeError();
1055             }
1056         }
1057     }
1058 }
1059
1060 /*!
1061     This method provides more advanced control over component instance creation.
1062     In general, programmers should use QDeclarativeComponent::create() to create a 
1063     component.
1064
1065     Complete a component creation begin with QDeclarativeComponent::beginCreate().
1066 */
1067 void QDeclarativeComponent::completeCreate()
1068 {
1069     Q_D(QDeclarativeComponent);
1070     d->completeCreate();
1071 }
1072
1073 void QDeclarativeComponentPrivate::completeCreate()
1074 {
1075     if (state.completePending) {
1076         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1077         complete(ep, &state);
1078
1079         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1080     }
1081 }
1082
1083 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
1084 : QObject(parent), prev(0), next(0)
1085 {
1086 }
1087
1088 QDeclarativeComponentAttached::~QDeclarativeComponentAttached()
1089 {
1090     if (prev) *prev = next;
1091     if (next) next->prev = prev;
1092     prev = 0;
1093     next = 0;
1094 }
1095
1096 /*!
1097     \internal
1098 */
1099 QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObject *obj)
1100 {
1101     QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj);
1102
1103     QDeclarativeEngine *engine = qmlEngine(obj);
1104     if (!engine)
1105         return a;
1106
1107     if (QDeclarativeEnginePrivate::get(engine)->inBeginCreate) {
1108         QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
1109         a->add(&p->componentAttached);
1110     } else {
1111         QDeclarativeData *d = QDeclarativeData::get(obj);
1112         Q_ASSERT(d);
1113         Q_ASSERT(d->context);
1114         a->add(&d->context->componentAttached);
1115     }
1116
1117     return a;
1118 }
1119
1120 QT_END_NAMESPACE