57class Q_QML_EXPORT
QQmlData :
public QAbstractDeclarativeData
60 enum Ownership { DoesNotOwnMemory, OwnsMemory };
62 QQmlData(Ownership ownership);
65 static inline void init() {
66 static bool initialized =
false;
69 QAbstractDeclarativeData::destroyed = destroyed;
70 QAbstractDeclarativeData::signalEmitted = signalEmitted;
71 QAbstractDeclarativeData::receivers = receivers;
72 QAbstractDeclarativeData::isSignalConnected = isSignalConnected;
76 static void destroyed(QAbstractDeclarativeData *, QObject *);
77 static void signalEmitted(QAbstractDeclarativeData *, QObject *,
int,
void **);
78 static int receivers(QAbstractDeclarativeData *,
const QObject *,
int);
79 static bool isSignalConnected(QAbstractDeclarativeData *,
const QObject *,
int);
81 void destroyed(QObject *);
83 void setImplicitDestructible() {
84 if (!explicitIndestructibleSet) indestructible =
false;
94 quint32 indestructible:1;
97 quint32 explicitIndestructibleSet:1;
100 quint32 hasTaintedV4Object:1;
101 quint32 isQueuedForDeletion:1;
103
104
105
106 quint32 rootObjectInCreation:1;
108 quint32 hasInterceptorMetaObject:1;
109 quint32 hasVMEMetaObject:1;
111
112
113
114
115 quint32 hasConstWrapper: 1;
121 quint32 bindingBitsArraySize : 16;
122 typedef quintptr BindingBitsType;
124 BitsPerType =
sizeof(BindingBitsType) * 8,
125 InlineBindingArraySize = 2
128 BindingBitsType *bindingBits;
129 BindingBitsType bindingBitsValue[InlineBindingArraySize];
132 QAtomicPointer<QQmlNotifyList> notifyList;
134 inline QQmlNotifierEndpoint *notify(
int index)
const;
135 void addNotify(
int index, QQmlNotifierEndpoint *);
136 int endpointCount(
int index);
137 bool signalHasEndpoint(
int index)
const;
138 static void connectEndpoint(QQmlNotifierEndpoint *endPoint, QObject *source,
int sourceSignal,
139 QQmlEngine *engine,
bool doNotify =
true);
141 enum class DeleteNotifyList { Yes, No };
142 void disconnectNotifiers(DeleteNotifyList doDelete);
145 QQmlContextData *context =
nullptr;
147 QQmlContextData *outerContext =
nullptr;
148 QQmlRefPointer<QQmlContextData> ownContext;
150 QQmlAbstractBinding *bindings =
nullptr;
151 QQmlBoundSignal *signalHandlers =
nullptr;
152 std::vector<QQmlPropertyObserver> propertyObservers;
155 QQmlData *nextContextObject =
nullptr;
156 QQmlData**prevContextObject =
nullptr;
158 inline bool hasBindingBit(
int)
const;
159 inline void setBindingBit(QObject *obj,
int);
160 inline void clearBindingBit(
int);
162 inline bool hasPendingBindingBit(
int index)
const;
163 inline void setPendingBindingBit(QObject *obj,
int);
164 inline void clearPendingBindingBit(
int);
166 quint16 lineNumber = 0;
167 quint16 columnNumber = 0;
169 quint32 jsEngineId = 0;
171 struct DeferredData {
174 unsigned int deferredIdx;
175 QMultiHash<
int,
const QV4::CompiledData::Binding *> bindings;
178 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
181 QQmlRefPointer<QQmlContextData> context;
183
184
185 QString inlineComponentName;
186 Q_DISABLE_COPY(DeferredData);
188 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
189 QList<DeferredData *> deferredData;
193 int cuObjectIndex = -1;
195 void deferData(
int objectIndex,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &,
196 const QQmlRefPointer<QQmlContextData> &,
const QString &inlineComponentName);
197 void releaseDeferredData();
199 QV4::WeakValue jsWrapper;
201 QQmlPropertyCache::ConstPtr propertyCache;
203 QQmlGuardImpl *guards =
nullptr;
205 static QQmlData *get(QObjectPrivate *priv,
bool create) {
208 if (priv->isDeletingChildren || priv->wasDeleted) {
211 }
else if (priv->declarativeData) {
212 return static_cast<QQmlData *>(priv->declarativeData);
214 return createQQmlData(priv);
220 static QQmlData *get(
const QObjectPrivate *priv) {
223 if (priv->isDeletingChildren || priv->wasDeleted)
225 if (priv->declarativeData)
226 return static_cast<QQmlData *>(priv->declarativeData);
230 static QQmlData *get(QObject *object,
bool create) {
231 return QQmlData::get(QObjectPrivate::get(object), create);
234 static QQmlData *get(
const QObject *object) {
235 return QQmlData::get(QObjectPrivate::get(object));
239 static bool keepAliveDuringGarbageCollection(
const QObject *object) {
240 QQmlData *ddata = get(object);
241 if (!ddata || ddata->indestructible || ddata->rootObjectInCreation)
246 bool hasExtendedData()
const {
return extendedData !=
nullptr; }
247 QHash<QQmlAttachedPropertiesFunc, QObject *> *attachedProperties()
const;
249 static inline bool wasDeleted(
const QObject *);
250 static inline bool wasDeleted(
const QObjectPrivate *);
252 static void markAsDeleted(QObject *);
253 static void setQueuedForDeletion(QObject *);
255 static inline void flushPendingBinding(QObject *object,
int coreIndex);
256 void flushPendingBinding(
int coreIndex);
258 static QQmlPropertyCache::ConstPtr ensurePropertyCache(QObject *object)
260 QQmlData *ddata = QQmlData::get(object,
true);
261 if (Q_LIKELY(ddata->propertyCache))
262 return ddata->propertyCache;
263 return createPropertyCache(object);
266 Q_ALWAYS_INLINE
static uint offsetForBit(
int bit) {
return static_cast<uint>(bit) / BitsPerType; }
267 Q_ALWAYS_INLINE
static BindingBitsType bitFlagForBit(
int bit) {
return BindingBitsType(1) << (
static_cast<uint>(bit) & (BitsPerType - 1)); }
273 mutable QQmlDataExtended *extendedData =
nullptr;
275 Q_NEVER_INLINE
static QQmlData *createQQmlData(QObjectPrivate *priv);
276 Q_NEVER_INLINE
static QQmlPropertyCache::ConstPtr createPropertyCache(QObject *object);
278 void removeFromContext();
279 void clearBindings();
280 bool clearSignalHandlers();
282 Q_ALWAYS_INLINE
bool hasBitSet(
int bit)
const
284 uint offset = offsetForBit(bit);
285 if (bindingBitsArraySize <= offset)
288 const BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
289 return bits[offset] & bitFlagForBit(bit);
292 Q_ALWAYS_INLINE
void clearBit(
int bit)
294 uint offset = QQmlData::offsetForBit(bit);
295 if (bindingBitsArraySize > offset) {
296 BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
297 bits[offset] &= ~QQmlData::bitFlagForBit(bit);
301 Q_ALWAYS_INLINE
void setBit(QObject *obj,
int bit)
303 uint offset = QQmlData::offsetForBit(bit);
304 BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
305 if (Q_UNLIKELY(bindingBitsArraySize <= offset))
306 bits = growBits(obj, bit);
307 bits[offset] |= QQmlData::bitFlagForBit(bit);
310 Q_NEVER_INLINE BindingBitsType *growBits(QObject *obj,
int bit);
312 Q_DISABLE_COPY_MOVE(QQmlData);
385inline void QQmlData::connectEndpoint(QQmlNotifierEndpoint *endpoint, QObject *source,
386 int sourceSignal, QQmlEngine *engine,
bool doNotify)
388 endpoint->disconnect();
391 if (QObjectPrivate::get(source)->threadData.loadRelaxed()->threadId.loadRelaxed()
392 != QObjectPrivate::get(engine)->threadData.loadRelaxed()->threadId.loadRelaxed()) {
395 QDebug(&sourceName) << source;
396 sourceName = sourceName.left(sourceName.size() - 1);
398 QDebug(&engineName).nospace() << engine;
399 engineName = engineName.left(engineName.size() - 1);
401 qFatal(
"QQmlEngine: Illegal attempt to connect to %s that is in"
402 " a different thread than the QML engine %s.",
403 qPrintable(sourceName), qPrintable(engineName));
406 endpoint->setSender(qintptr(source));
407 endpoint->sourceSignal = sourceSignal;
408 QQmlPropertyPrivate::flushSignal(source, sourceSignal);
409 QQmlData *ddata = QQmlData::get(source,
true);
410 ddata->addNotify(sourceSignal, endpoint);
412 endpoint->needsConnectNotify = doNotify;
413 QObjectPrivate *
const priv = QObjectPrivate::get(source);
414 priv->connectNotify(QMetaObjectPrivate::signal(source->metaObject(), sourceSignal));