1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdeclarativecontext.h"
43 #include "private/qdeclarativecontext_p.h"
44 
45 #include "private/qdeclarativecomponent_p.h"
46 #include "private/qdeclarativeexpression_p.h"
47 #include "private/qdeclarativeengine_p.h"
48 #include "qdeclarativeengine.h"
49 #include "private/qdeclarativecompiledbindings_p.h"
50 #include "qdeclarativeinfo.h"
51 #include "private/qdeclarativeglobalscriptclass_p.h"
52 
53 #include <qscriptengine.h>
54 #include <QtCore/qvarlengtharray.h>
55 #include <QtCore/qdebug.h>
56 
57 #include <private/qscriptdeclarativeclass_p.h>
58 
59 QT_BEGIN_NAMESPACE
60 
QDeclarativeContextPrivate()61 QDeclarativeContextPrivate::QDeclarativeContextPrivate()
62 : data(0), notifyIndex(-1)
63 {
64 }
65 
66 /*!
67     \class QDeclarativeContext
68     \since 4.7
69     \brief The QDeclarativeContext class defines a context within a QML engine.
70     \mainclass
71 
72     Contexts allow data to be exposed to the QML components instantiated by the
73     QML engine.
74 
75     Each QDeclarativeContext contains a set of properties, distinct from its QObject
76     properties, that allow data to be explicitly bound to a context by name.  The
77     context properties are defined and updated by calling
78     QDeclarativeContext::setContextProperty().  The following example shows a Qt model
79     being bound to a context and then accessed from a QML file.
80 
81     \code
82     QDeclarativeEngine engine;
83     QStringListModel modelData;
84     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
85     context->setContextProperty("myModel", &modelData);
86 
87     QDeclarativeComponent component(&engine);
88     component.setData("import QtQuick 1.0\nListView { model: myModel }", QUrl());
89     QObject *window = component.create(context);
90     \endcode
91 
92     Note it is the responsibility of the creator to delete any QDeclarativeContext it
93     constructs. If the \c context object in the example is no longer needed when the
94     \c window component instance is destroyed, the \c context must be destroyed explicitly.
95     The simplest way to ensure this is to set \c window as the parent of \c context.
96 
97     To simplify binding and maintaining larger data sets, a context object can be set
98     on a QDeclarativeContext.  All the properties of the context object are available
99     by name in the context, as though they were all individually added through calls
100     to QDeclarativeContext::setContextProperty().  Changes to the property's values are
101     detected through the property's notify signal.  Setting a context object is both
102     faster and easier than manually adding and maintaing context property values.
103 
104     The following example has the same effect as the previous one, but it uses a context
105     object.
106 
107     \code
108     class MyDataSet : ... {
109         ...
110         Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
111         ...
112     };
113 
114     MyDataSet myDataSet;
115     QDeclarativeEngine engine;
116     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
117     context->setContextObject(&myDataSet);
118 
119     QDeclarativeComponent component(&engine);
120     component.setData("import QtQuick 1.0\nListView { model: myModel }", QUrl());
121     component.create(context);
122     \endcode
123 
124     All properties added explicitly by QDeclarativeContext::setContextProperty() take
125     precedence over the context object's properties.
126 
127     \section2 The Context Hierarchy
128 
129     Contexts form a hierarchy. The root of this hierarchy is the QML engine's
130     \l {QDeclarativeEngine::rootContext()}{root context}. Child contexts inherit
131     the context properties of their parents; if a child context sets a context property
132     that already exists in its parent, the new context property overrides that of the
133     parent.
134 
135     The following example defines two contexts - \c context1 and \c context2.  The
136     second context overrides the "b" context property inherited from the first with a
137     new value.
138 
139     \code
140     QDeclarativeEngine engine;
141     QDeclarativeContext *context1 = new QDeclarativeContext(engine.rootContext());
142     QDeclarativeContext *context2 = new QDeclarativeContext(context1);
143 
144     context1->setContextProperty("a", 12);
145     context1->setContextProperty("b", 12);
146 
147     context2->setContextProperty("b", 15);
148     \endcode
149 
150     While QML objects instantiated in a context are not strictly owned by that
151     context, their bindings are.  If a context is destroyed, the property bindings of
152     outstanding QML objects will stop evaluating.
153 
154     \warning Setting the context object or adding new context properties after an object
155     has been created in that context is an expensive operation (essentially forcing all bindings
156     to reevaluate). Thus whenever possible you should complete "setup" of the context
157     before using it to create any objects.
158 
159     \sa {Using QML Bindings in C++ Applications}
160 */
161 
162 /*! \internal */
QDeclarativeContext(QDeclarativeEngine * e,bool)163 QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *e, bool)
164 : QObject(*(new QDeclarativeContextPrivate))
165 {
166     Q_D(QDeclarativeContext);
167     d->data = new QDeclarativeContextData(this);
168 
169     d->data->engine = e;
170 }
171 
172 /*!
173     Create a new QDeclarativeContext as a child of \a engine's root context, and the
174     QObject \a parent.
175 */
QDeclarativeContext(QDeclarativeEngine * engine,QObject * parent)176 QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *engine, QObject *parent)
177 : QObject(*(new QDeclarativeContextPrivate), parent)
178 {
179     Q_D(QDeclarativeContext);
180     d->data = new QDeclarativeContextData(this);
181 
182     d->data->setParent(engine?QDeclarativeContextData::get(engine->rootContext()):0);
183 }
184 
185 /*!
186     Create a new QDeclarativeContext with the given \a parentContext, and the
187     QObject \a parent.
188 */
QDeclarativeContext(QDeclarativeContext * parentContext,QObject * parent)189 QDeclarativeContext::QDeclarativeContext(QDeclarativeContext *parentContext, QObject *parent)
190 : QObject(*(new QDeclarativeContextPrivate), parent)
191 {
192     Q_D(QDeclarativeContext);
193     d->data = new QDeclarativeContextData(this);
194 
195     d->data->setParent(parentContext?QDeclarativeContextData::get(parentContext):0);
196 }
197 
198 /*!
199     \internal
200 */
QDeclarativeContext(QDeclarativeContextData * data)201 QDeclarativeContext::QDeclarativeContext(QDeclarativeContextData *data)
202 : QObject(*(new QDeclarativeContextPrivate), 0)
203 {
204     Q_D(QDeclarativeContext);
205     d->data = data;
206 }
207 
208 /*!
209     Destroys the QDeclarativeContext.
210 
211     Any expressions, or sub-contexts dependent on this context will be
212     invalidated, but not destroyed (unless they are parented to the QDeclarativeContext
213     object).
214  */
~QDeclarativeContext()215 QDeclarativeContext::~QDeclarativeContext()
216 {
217     Q_D(QDeclarativeContext);
218 
219     if (!d->data->isInternal)
220         d->data->destroy();
221 }
222 
223 /*!
224     Returns whether the context is valid.
225 
226     To be valid, a context must have a engine, and it's contextObject(), if any,
227     must not have been deleted.
228 */
isValid() const229 bool QDeclarativeContext::isValid() const
230 {
231     Q_D(const QDeclarativeContext);
232     return d->data && d->data->isValid();
233 }
234 
235 /*!
236     Return the context's QDeclarativeEngine, or 0 if the context has no QDeclarativeEngine or the
237     QDeclarativeEngine was destroyed.
238 */
engine() const239 QDeclarativeEngine *QDeclarativeContext::engine() const
240 {
241     Q_D(const QDeclarativeContext);
242     return d->data->engine;
243 }
244 
245 /*!
246     Return the context's parent QDeclarativeContext, or 0 if this context has no
247     parent or if the parent has been destroyed.
248 */
parentContext() const249 QDeclarativeContext *QDeclarativeContext::parentContext() const
250 {
251     Q_D(const QDeclarativeContext);
252     return d->data->parent?d->data->parent->asQDeclarativeContext():0;
253 }
254 
255 /*!
256     Return the context object, or 0 if there is no context object.
257 */
contextObject() const258 QObject *QDeclarativeContext::contextObject() const
259 {
260     Q_D(const QDeclarativeContext);
261     return d->data->contextObject;
262 }
263 
264 /*!
265     Set the context \a object.
266 */
setContextObject(QObject * object)267 void QDeclarativeContext::setContextObject(QObject *object)
268 {
269     Q_D(QDeclarativeContext);
270 
271     QDeclarativeContextData *data = d->data;
272 
273     if (data->isInternal) {
274         qWarning("QDeclarativeContext: Cannot set context object for internal context.");
275         return;
276     }
277 
278     if (!isValid()) {
279         qWarning("QDeclarativeContext: Cannot set context object on invalid context.");
280         return;
281     }
282 
283     data->contextObject = object;
284 }
285 
286 /*!
287     Set a the \a value of the \a name property on this context.
288 */
setContextProperty(const QString & name,const QVariant & value)289 void QDeclarativeContext::setContextProperty(const QString &name, const QVariant &value)
290 {
291     Q_D(QDeclarativeContext);
292     if (d->notifyIndex == -1)
293         d->notifyIndex = this->metaObject()->methodCount();
294 
295     QDeclarativeContextData *data = d->data;
296 
297     if (data->isInternal) {
298         qWarning("QDeclarativeContext: Cannot set property on internal context.");
299         return;
300     }
301 
302     if (!isValid()) {
303         qWarning("QDeclarativeContext: Cannot set property on invalid context.");
304         return;
305     }
306 
307     if (data->engine) {
308         bool ok;
309         QObject *o = QDeclarativeEnginePrivate::get(data->engine)->toQObject(value, &ok);
310         if (ok) {
311             setContextProperty(name, o);
312             return;
313         }
314     }
315 
316     if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
317 
318     int idx = data->propertyNames->value(name);
319     if (idx == -1) {
320         data->propertyNames->add(name, data->idValueCount + d->propertyValues.count());
321         d->propertyValues.append(value);
322 
323         data->refreshExpressions();
324     } else {
325         d->propertyValues[idx] = value;
326         QMetaObject::activate(this, idx + d->notifyIndex, 0);
327     }
328 }
329 
330 /*!
331     Set the \a value of the \a name property on this context.
332 
333     QDeclarativeContext does \bold not take ownership of \a value.
334 */
setContextProperty(const QString & name,QObject * value)335 void QDeclarativeContext::setContextProperty(const QString &name, QObject *value)
336 {
337     Q_D(QDeclarativeContext);
338     if (d->notifyIndex == -1)
339         d->notifyIndex = this->metaObject()->methodCount();
340 
341     QDeclarativeContextData *data = d->data;
342 
343     if (data->isInternal) {
344         qWarning("QDeclarativeContext: Cannot set property on internal context.");
345         return;
346     }
347 
348     if (!isValid()) {
349         qWarning("QDeclarativeContext: Cannot set property on invalid context.");
350         return;
351     }
352 
353     if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
354     int idx = data->propertyNames->value(name);
355 
356     if (idx == -1) {
357         data->propertyNames->add(name, data->idValueCount + d->propertyValues.count());
358         d->propertyValues.append(QVariant::fromValue(value));
359 
360         data->refreshExpressions();
361     } else {
362         d->propertyValues[idx] = QVariant::fromValue(value);
363         QMetaObject::activate(this, idx + d->notifyIndex, 0);
364     }
365 }
366 
367 /*!
368   Returns the value of the \a name property for this context
369   as a QVariant.
370  */
contextProperty(const QString & name) const371 QVariant QDeclarativeContext::contextProperty(const QString &name) const
372 {
373     Q_D(const QDeclarativeContext);
374     QVariant value;
375     int idx = -1;
376 
377     QDeclarativeContextData *data = d->data;
378 
379     if (data->propertyNames)
380         idx = data->propertyNames->value(name);
381 
382     if (idx == -1) {
383         QByteArray utf8Name = name.toUtf8();
384         if (data->contextObject) {
385             QObject *obj = data->contextObject;
386             QDeclarativePropertyCache::Data local;
387             QDeclarativePropertyCache::Data *property =
388                 QDeclarativePropertyCache::property(data->engine, obj, name, local);
389 
390             if (property) value = obj->metaObject()->property(property->coreIndex).read(obj);
391         }
392         if (!value.isValid() && parentContext())
393             value = parentContext()->contextProperty(name);
394     } else {
395         if (idx >= d->propertyValues.count())
396             value = QVariant::fromValue(data->idValues[idx - d->propertyValues.count()].data());
397         else
398             value = d->propertyValues[idx];
399     }
400 
401     return value;
402 }
403 
404 /*!
405     Resolves the URL \a src relative to the URL of the
406     containing component.
407 
408     \sa QDeclarativeEngine::baseUrl(), setBaseUrl()
409 */
resolvedUrl(const QUrl & src)410 QUrl QDeclarativeContext::resolvedUrl(const QUrl &src)
411 {
412     Q_D(QDeclarativeContext);
413     return d->data->resolvedUrl(src);
414 }
415 
resolvedUrl(const QUrl & src)416 QUrl QDeclarativeContextData::resolvedUrl(const QUrl &src)
417 {
418     QDeclarativeContextData *ctxt = this;
419 
420     if (src.isRelative() && !src.isEmpty()) {
421         if (ctxt) {
422             while(ctxt) {
423                 if(ctxt->url.isValid())
424                     break;
425                 else
426                     ctxt = ctxt->parent;
427             }
428 
429             if (ctxt)
430                 return ctxt->url.resolved(src);
431             else if (engine)
432                 return engine->baseUrl().resolved(src);
433         }
434         return QUrl();
435     } else {
436         return src;
437     }
438 }
439 
440 
441 /*!
442     Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
443 
444     Calling this function will override the url of the containing
445     component used by default.
446 
447     \sa resolvedUrl()
448 */
setBaseUrl(const QUrl & baseUrl)449 void QDeclarativeContext::setBaseUrl(const QUrl &baseUrl)
450 {
451     Q_D(QDeclarativeContext);
452 
453     d->data->url = baseUrl;
454 }
455 
456 /*!
457     Returns the base url of the component, or the containing component
458     if none is set.
459 */
baseUrl() const460 QUrl QDeclarativeContext::baseUrl() const
461 {
462     Q_D(const QDeclarativeContext);
463     const QDeclarativeContextData* data = d->data;
464     while (data && data->url.isEmpty())
465         data = data->parent;
466 
467     if (data)
468         return data->url;
469     else
470         return QUrl();
471 }
472 
context_count(QDeclarativeListProperty<QObject> * prop)473 int QDeclarativeContextPrivate::context_count(QDeclarativeListProperty<QObject> *prop)
474 {
475     QDeclarativeContext *context = static_cast<QDeclarativeContext*>(prop->object);
476     QDeclarativeContextPrivate *d = QDeclarativeContextPrivate::get(context);
477     int contextProperty = (int)(quintptr)prop->data;
478 
479     if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
480         return 0;
481     } else {
482         return ((const QList<QObject> *)d->propertyValues.at(contextProperty).constData())->count();
483     }
484 }
485 
context_at(QDeclarativeListProperty<QObject> * prop,int index)486 QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject> *prop, int index)
487 {
488     QDeclarativeContext *context = static_cast<QDeclarativeContext*>(prop->object);
489     QDeclarativeContextPrivate *d = QDeclarativeContextPrivate::get(context);
490     int contextProperty = (int)(quintptr)prop->data;
491 
492     if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
493         return 0;
494     } else {
495         return ((const QList<QObject*> *)d->propertyValues.at(contextProperty).constData())->at(index);
496     }
497 }
498 
499 
QDeclarativeContextData()500 QDeclarativeContextData::QDeclarativeContextData()
501 : parent(0), engine(0), isInternal(false), publicContext(0), propertyNames(0), contextObject(0),
502   imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
503   contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
504   componentAttached(0)
505 {
506 }
507 
QDeclarativeContextData(QDeclarativeContext * ctxt)508 QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
509 : parent(0), engine(0), isInternal(false), publicContext(ctxt), propertyNames(0), contextObject(0),
510   imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
511   contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
512   componentAttached(0)
513 {
514 }
515 
invalidate()516 void QDeclarativeContextData::invalidate()
517 {
518     while (childContexts)
519         childContexts->invalidate();
520 
521     while (componentAttached) {
522         QDeclarativeComponentAttached *a = componentAttached;
523         componentAttached = a->next;
524         if (componentAttached) componentAttached->prev = &componentAttached;
525 
526         a->next = 0;
527         a->prev = 0;
528 
529         emit a->destruction();
530     }
531 
532     if (prevChild) {
533         *prevChild = nextChild;
534         if (nextChild) nextChild->prevChild = prevChild;
535         nextChild = 0;
536         prevChild = 0;
537     }
538 
539     engine = 0;
540     parent = 0;
541 }
542 
clearContext()543 void QDeclarativeContextData::clearContext()
544 {
545     if (engine) {
546         while (componentAttached) {
547             QDeclarativeComponentAttached *a = componentAttached;
548             componentAttached = a->next;
549             if (componentAttached) componentAttached->prev = &componentAttached;
550 
551             a->next = 0;
552             a->prev = 0;
553 
554             emit a->destruction();
555         }
556     }
557 
558     QDeclarativeAbstractExpression *expression = expressions;
559     while (expression) {
560         QDeclarativeAbstractExpression *nextExpression = expression->m_nextExpression;
561 
562         expression->m_context = 0;
563         expression->m_prevExpression = 0;
564         expression->m_nextExpression = 0;
565 
566         expression = nextExpression;
567     }
568     expressions = 0;
569 }
570 
destroy()571 void QDeclarativeContextData::destroy()
572 {
573     if (linkedContext)
574         linkedContext->destroy();
575 
576     if (engine) invalidate();
577 
578     clearContext();
579 
580     while (contextObjects) {
581         QDeclarativeData *co = contextObjects;
582         contextObjects = contextObjects->nextContextObject;
583 
584         co->context = 0;
585         co->outerContext = 0;
586         co->nextContextObject = 0;
587         co->prevContextObject = 0;
588     }
589 
590     QDeclarativeGuardedContextData *contextGuard = contextGuards;
591     while (contextGuard) {
592         QDeclarativeGuardedContextData *next = contextGuard->m_next;
593         contextGuard->m_next = 0;
594         contextGuard->m_prev = 0;
595         contextGuard->m_contextData = 0;
596         contextGuard = next;
597     }
598     contextGuards = 0;
599 
600     if (propertyNames)
601         propertyNames->release();
602 
603     if (imports)
604         imports->release();
605 
606     if (optimizedBindings)
607         optimizedBindings->release();
608 
609     delete [] idValues;
610 
611     if (isInternal)
612         delete publicContext;
613 
614     delete this;
615 }
616 
setParent(QDeclarativeContextData * p)617 void QDeclarativeContextData::setParent(QDeclarativeContextData *p)
618 {
619     if (p) {
620         parent = p;
621         engine = p->engine;
622         nextChild = p->childContexts;
623         if (nextChild) nextChild->prevChild = &nextChild;
624         prevChild = &p->childContexts;
625         p->childContexts = this;
626     }
627 }
628 
629 /*
630 Refreshes all expressions that could possibly depend on this context.  Refreshing flushes all
631 context-tree dependent caches in the expressions, and should occur every time the context tree
632  *structure* (not values) changes.
633 */
refreshExpressions()634 void QDeclarativeContextData::refreshExpressions()
635 {
636     QDeclarativeContextData *child = childContexts;
637     while (child) {
638         child->refreshExpressions();
639         child = child->nextChild;
640     }
641 
642     QDeclarativeAbstractExpression *expression = expressions;
643     while (expression) {
644         expression->refresh();
645         expression = expression->m_nextExpression;
646     }
647 }
648 
addObject(QObject * o)649 void QDeclarativeContextData::addObject(QObject *o)
650 {
651     QDeclarativeData *data = QDeclarativeData::get(o, true);
652 
653     Q_ASSERT(data->context == 0);
654 
655     data->context = this;
656     data->outerContext = this;
657 
658     data->nextContextObject = contextObjects;
659     if (data->nextContextObject)
660         data->nextContextObject->prevContextObject = &data->nextContextObject;
661     data->prevContextObject = &contextObjects;
662     contextObjects = data;
663 }
664 
addImportedScript(const QDeclarativeParser::Object::ScriptBlock & script)665 void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script)
666 {
667     if (!engine)
668         return;
669 
670     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
671     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
672 
673     const QString &code = script.code;
674     const QString &url = script.file;
675     const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas;
676 
677     Q_ASSERT(!url.isEmpty());
678 
679     if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) {
680 
681         QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url);
682         if (iter == enginePriv->m_sharedScriptImports.end()) {
683             QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
684 
685             scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url));
686             scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
687 
688             QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
689             scriptContext->pushScope(scope);
690 
691             scriptEngine->evaluate(code, url, 1);
692 
693             if (scriptEngine->hasUncaughtException()) {
694                 QDeclarativeError error;
695                 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
696                 enginePriv->warning(error);
697             }
698 
699             scriptEngine->popContext();
700 
701             iter = enginePriv->m_sharedScriptImports.insert(url, scope);
702         }
703 
704         importedScripts.append(*iter);
705 
706     } else {
707 
708         QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
709 
710         scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url));
711         scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
712 
713         QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
714         scriptContext->pushScope(scope);
715 
716         scriptEngine->evaluate(code, url, 1);
717 
718         if (scriptEngine->hasUncaughtException()) {
719             QDeclarativeError error;
720             QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
721             enginePriv->warning(error);
722         }
723 
724         scriptEngine->popContext();
725 
726         importedScripts.append(scope);
727 
728     }
729 }
730 
setIdProperty(int idx,QObject * obj)731 void QDeclarativeContextData::setIdProperty(int idx, QObject *obj)
732 {
733     idValues[idx] = obj;
734     idValues[idx].context = this;
735 }
736 
setIdPropertyData(QDeclarativeIntegerCache * data)737 void QDeclarativeContextData::setIdPropertyData(QDeclarativeIntegerCache *data)
738 {
739     Q_ASSERT(!propertyNames);
740     propertyNames = data;
741     propertyNames->addref();
742 
743     idValueCount = data->count();
744     idValues = new ContextGuard[idValueCount];
745 }
746 
findObjectId(const QObject * obj) const747 QString QDeclarativeContextData::findObjectId(const QObject *obj) const
748 {
749     if (!idValues || !propertyNames)
750         return QString();
751 
752     for (int i=0; i<idValueCount; i++) {
753         if (idValues[i] == obj)
754             return propertyNames->findId(i);
755     }
756 
757     if (linkedContext)
758         return linkedContext->findObjectId(obj);
759     return QString();
760 }
761 
asQDeclarativeContext()762 QDeclarativeContext *QDeclarativeContextData::asQDeclarativeContext()
763 {
764     if (!publicContext)
765         publicContext = new QDeclarativeContext(this);
766     return publicContext;
767 }
768 
asQDeclarativeContextPrivate()769 QDeclarativeContextPrivate *QDeclarativeContextData::asQDeclarativeContextPrivate()
770 {
771     return QDeclarativeContextPrivate::get(asQDeclarativeContext());
772 }
773 
774 QT_END_NAMESPACE
775