6#include <QtQml/qqmlengine.h>
7#include <QtQml/private/qqmlcomponentattached_p.h>
8#include <QtQml/private/qqmljavascriptexpression_p.h>
9#include <QtQml/private/qqmlguardedcontextdata_p.h>
13void QQmlContextData::installContext(QQmlData *ddata, QQmlContextData::QmlObjectKind kind)
16 if (kind == QQmlContextData::DocumentRoot) {
18 Q_ASSERT(ddata->context !=
this);
19 Q_ASSERT(ddata->outerContext);
20 Q_ASSERT(ddata->outerContext !=
this);
21 QQmlRefPointer<QQmlContextData> c = ddata->context;
22 while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
24 c->setLinkedContext(
this);
26 ddata->context =
this;
28 ddata->ownContext.reset(ddata->context);
29 }
else if (!ddata->context) {
30 ddata->context =
this;
33 addOwnedObject(ddata);
36QUrl QQmlContextData::resolvedUrl(
const QUrl &src)
const
39 if (src.isRelative() && !src.isEmpty()) {
40 const QUrl ownUrl = url();
41 if (ownUrl.isValid()) {
42 resolved = ownUrl.resolved(src);
44 for (QQmlRefPointer<QQmlContextData> ctxt = parent(); ctxt; ctxt = ctxt->parent()) {
45 const QUrl ctxtUrl = ctxt->url();
46 if (ctxtUrl.isValid()) {
47 resolved = ctxtUrl.resolved(src);
52 if (m_engine && resolved.isEmpty())
53 resolved = m_engine->baseUrl().resolved(src);
59 if (resolved.isEmpty())
62 return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
66void QQmlContextData::emitDestruction()
68 if (!m_hasEmittedDestruction) {
69 m_hasEmittedDestruction =
true;
74 while (m_componentAttacheds) {
75 QQmlComponentAttached *attached = m_componentAttacheds;
76 attached->removeFromList();
77 emit attached->destruction();
80 for (QQmlRefPointer<QQmlContextData> child = m_childContexts; !child.isNull(); child = child->m_nextChild)
81 child->emitDestruction();
86void QQmlContextData::invalidate()
90 while (m_childContexts) {
91 Q_ASSERT(m_childContexts !=
this);
92 m_childContexts->invalidate();
96 *m_prevChild = m_nextChild;
97 if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
98 m_nextChild =
nullptr;
99 m_prevChild =
nullptr;
102 if (!m_hasWeakImportedScripts) {
103 if (m_engine && !m_importedScripts.isNullOrUndefined()) {
104 QV4::Scope scope(m_engine->handle());
105 QV4::ScopedValue val(scope, m_importedScripts.value());
106 m_importedScripts.~PersistentValue();
107 new (&m_weakImportedScripts) QV4::WeakValue();
108 m_weakImportedScripts.set(m_engine->handle(), val);
109 m_hasWeakImportedScripts =
true;
112 m_importedScripts.clear();
120void QQmlContextData::clearContextRecursively()
124 for (
auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
125 ctxIt->clearContextRecursively();
130void QQmlContextData::clearContext()
134 QQmlJavaScriptExpression *expression = m_expressions;
136 QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
138 expression->m_prevExpression =
nullptr;
139 expression->m_nextExpression =
nullptr;
141 expression->setContext(
nullptr);
143 expression = nextExpression;
145 m_expressions =
nullptr;
148QQmlContextData::~QQmlContextData()
150 Q_ASSERT(refCount() == 0);
154 if (!m_hasWeakImportedScripts) {
157 m_importedScripts.clear();
160 if (m_hasWeakImportedScripts)
161 m_weakImportedScripts.~WeakValue();
163 m_importedScripts.~PersistentValue();
164 m_linkedContext.reset();
166 Q_ASSERT(refCount() == 1);
168 Q_ASSERT(refCount() == 1);
170 while (m_ownedObjects) {
171 QQmlData *co = m_ownedObjects;
172 m_ownedObjects = m_ownedObjects->nextContextObject;
174 if (co->context ==
this)
175 co->context =
nullptr;
176 co->outerContext =
nullptr;
177 co->nextContextObject =
nullptr;
178 co->prevContextObject =
nullptr;
180 Q_ASSERT(refCount() == 1);
182 QQmlGuardedContextData *contextGuard = m_contextGuards;
183 while (contextGuard) {
185 QQmlGuardedContextData *next = contextGuard->next();
186 contextGuard->setContextData({});
189 m_contextGuards =
nullptr;
190 Q_ASSERT(refCount() == 1);
192 delete [] m_idValues;
193 m_idValues =
nullptr;
195 Q_ASSERT(refCount() == 1);
197 delete m_publicContext;
199 Q_ASSERT(refCount() == 1);
202void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
204 QQmlJavaScriptExpression::DeleteWatcher w(expression);
206 if (expression->m_nextExpression)
207 refreshExpressionsRecursive(expression->m_nextExpression);
210 expression->refresh();
213void QQmlContextData::refreshExpressionsRecursive(
bool isGlobal)
216 if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
217 QQmlGuardedContextData guard(
this);
220 m_childContexts->refreshExpressionsRecursive(isGlobal);
222 if (guard.isNull())
return;
225 m_nextChild->refreshExpressionsRecursive(isGlobal);
227 if (guard.isNull())
return;
229 if (hasExpressionsToRun(isGlobal))
230 refreshExpressionsRecursive(m_expressions);
232 }
else if (hasExpressionsToRun(isGlobal)) {
233 refreshExpressionsRecursive(m_expressions);
234 }
else if (m_nextChild && m_childContexts) {
235 QQmlGuardedContextData guard(
this);
236 m_childContexts->refreshExpressionsRecursive(isGlobal);
237 if (!guard.isNull() && m_nextChild)
238 m_nextChild->refreshExpressionsRecursive(isGlobal);
239 }
else if (m_nextChild) {
240 m_nextChild->refreshExpressionsRecursive(isGlobal);
241 }
else if (m_childContexts) {
242 m_childContexts->refreshExpressionsRecursive(isGlobal);
249void QQmlContextData::refreshExpressions()
251 bool isGlobal = (m_parent ==
nullptr);
254 if (hasExpressionsToRun(isGlobal) && m_childContexts) {
255 QQmlGuardedContextData guard(
this);
256 m_childContexts->refreshExpressionsRecursive(isGlobal);
257 if (!guard.isNull() && hasExpressionsToRun(isGlobal))
258 refreshExpressionsRecursive(m_expressions);
259 }
else if (hasExpressionsToRun(isGlobal)) {
260 refreshExpressionsRecursive(m_expressions);
261 }
else if (m_childContexts) {
262 m_childContexts->refreshExpressionsRecursive(isGlobal);
266void QQmlContextData::addOwnedObject(QQmlData *data)
268 if (data->outerContext) {
269 if (data->nextContextObject)
270 data->nextContextObject->prevContextObject = data->prevContextObject;
271 if (data->prevContextObject)
272 *data->prevContextObject = data->nextContextObject;
273 else if (data->outerContext->m_ownedObjects == data)
274 data->outerContext->m_ownedObjects = data->nextContextObject;
277 data->outerContext =
this;
279 data->nextContextObject = m_ownedObjects;
280 if (data->nextContextObject)
281 data->nextContextObject->prevContextObject = &data->nextContextObject;
282 data->prevContextObject = &m_ownedObjects;
283 m_ownedObjects = data;
286void QQmlContextData::setIdValue(
int idx, QObject *obj)
288 m_idValues[idx] = obj;
289 m_idValues[idx].setContext(
this);
292QString QQmlContextData::findObjectId(
const QObject *obj)
const
294 for (
int ii = 0; ii < m_idValueCount; ii++) {
295 if (m_idValues[ii] == obj)
296 return propertyName(ii);
299 const QVariant objVariant = QVariant::fromValue(obj);
300 if (m_publicContext) {
301 QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
302 for (
int ii = 0; ii < p->numPropertyValues(); ++ii)
303 if (p->propertyValue(ii) == objVariant)
304 return propertyName(ii);
307 if (m_contextObject) {
309 for (
const QMetaObject *metaObject = m_contextObject->metaObject();
310 metaObject; metaObject = metaObject->superClass()) {
311 for (
int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
313 const QMetaProperty prop = metaObject->property(i);
314 if (prop.metaType().flags() & QMetaType::PointerToQObject
315 && prop.read(m_contextObject) == objVariant) {
316 return QString::fromUtf8(prop.name());
325void QQmlContextData::initFromTypeCompilationUnit(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int subComponentIndex)
327 m_typeCompilationUnit = unit;
328 m_componentObjectIndex = subComponentIndex == -1 ? 0 : subComponentIndex;
329 Q_ASSERT(!m_idValues);
330 m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
331 ->nNamedObjectsInComponent;
332 if (m_idValueCount > 0)
333 m_idValues =
new ContextGuard[m_idValueCount];
336void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
338 attached->insertIntoList(&m_componentAttacheds);
341void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
343 expression->insertIntoList(&m_expressions);
346void QQmlContextData::initPropertyNames()
const
348 if (m_typeCompilationUnit)
349 m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
351 m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
352 Q_ASSERT(!m_propertyNameCache.isEmpty());
355QUrl QQmlContextData::url()
const
357 if (m_typeCompilationUnit)
358 return m_typeCompilationUnit->finalUrl();
362QString QQmlContextData::urlString()
const
364 if (m_typeCompilationUnit)
365 return m_typeCompilationUnit->finalUrlString();
366 return m_baseUrlString;