~ubuntu-branches/debian/jessie/qtdeclarative-opensource-src/jessie

« back to all changes in this revision

Viewing changes to src/qml/qml/qqmlobjectcreator.cpp

  • Committer: Package Import Robot
  • Author(s): Lisandro Damián Nicanor Pérez Meyer
  • Date: 2014-06-05 23:53:56 UTC
  • mfrom: (8.1.11 experimental)
  • Revision ID: package-import@ubuntu.com-20140605235356-cf36ioh08oh2oow4
Tags: 5.3.0-5
* Upload to unstable.
* Backport v4_yarr_jit_push_pop_addressTempRegister.patch to fix a bug
  of the JIT compiler in arm. Thanks Scott Kitterman for pointing it out.
* Update symbols files with buildds' logs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
#include "qqmlobjectcreator_p.h"
43
43
 
44
44
#include <private/qqmlengine_p.h>
45
 
#include <private/qqmlabstractbinding_p.h>
46
45
#include <private/qqmlvmemetaobject_p.h>
47
46
#include <private/qv4function_p.h>
48
47
#include <private/qv4functionobject_p.h>
52
51
#include <private/qqmlboundsignal_p.h>
53
52
#include <private/qqmltrace_p.h>
54
53
#include <private/qqmlcomponentattached_p.h>
55
 
#include <QQmlComponent>
56
54
#include <private/qqmlcomponent_p.h>
57
 
#include <private/qqmlcodegenerator_p.h>
 
55
#include <private/qqmlcustomparser_p.h>
 
56
#include <private/qqmlscriptstring_p.h>
 
57
#include <private/qqmlpropertyvalueinterceptor_p.h>
 
58
#include <private/qqmlvaluetypeproxybinding_p.h>
58
59
 
59
60
QT_USE_NAMESPACE
60
61
 
61
62
namespace {
62
63
struct ActiveOCRestorer
63
64
{
64
 
    ActiveOCRestorer(QmlObjectCreator *creator, QQmlEnginePrivate *ep)
 
65
    ActiveOCRestorer(QQmlObjectCreator *creator, QQmlEnginePrivate *ep)
65
66
    : ep(ep), oldCreator(ep->activeObjectCreator) { ep->activeObjectCreator = creator; }
66
67
    ~ActiveOCRestorer() { ep->activeObjectCreator = oldCreator; }
67
68
 
68
69
    QQmlEnginePrivate *ep;
69
 
    QmlObjectCreator *oldCreator;
 
70
    QQmlObjectCreator *oldCreator;
70
71
};
71
72
}
72
73
 
73
 
QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUnit *unit)
74
 
    : url(url)
75
 
    , qmlUnit(unit)
76
 
{
77
 
}
78
 
 
79
 
void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
80
 
{
81
 
    QQmlError error;
82
 
    error.setUrl(url);
83
 
    error.setLine(location.line);
84
 
    error.setColumn(location.column);
85
 
    error.setDescription(description);
86
 
    errors << error;
87
 
}
88
 
 
89
 
#define COMPILE_EXCEPTION(token, desc) \
90
 
    { \
91
 
        recordError((token)->location, desc); \
92
 
        return false; \
93
 
    }
94
 
 
95
 
static QAtomicInt classIndexCounter(0);
96
 
 
97
 
QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, const QQmlImports *imports,
98
 
                                                   QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes)
99
 
    : QQmlCompilePass(url, unit)
100
 
    , enginePrivate(enginePrivate)
101
 
    , imports(imports)
102
 
    , resolvedTypes(resolvedTypes)
103
 
{
104
 
}
105
 
 
106
 
bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData)
107
 
{
108
 
    Q_ASSERT(!stringAt(obj->inheritedTypeNameIndex).isEmpty());
109
 
 
110
 
    QQmlCompiledData::TypeReference typeRef = resolvedTypes->value(obj->inheritedTypeNameIndex);
111
 
    QQmlPropertyCache *baseTypeCache = typeRef.createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
112
 
    Q_ASSERT(baseTypeCache);
113
 
    if (obj->nProperties == 0 && obj->nSignals == 0 && obj->nFunctions == 0) {
114
 
        *resultCache = baseTypeCache;
115
 
        vmeMetaObjectData->clear();
116
 
        return true;
117
 
    }
118
 
 
119
 
    QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
120
 
                                                             obj->nProperties,
121
 
                                                             obj->nFunctions + obj->nProperties + obj->nSignals,
122
 
                                                             obj->nSignals + obj->nProperties);
123
 
    *resultCache = cache;
124
 
 
125
 
    vmeMetaObjectData->clear();
126
 
 
127
 
    struct TypeData {
128
 
        QV4::CompiledData::Property::Type dtype;
129
 
        int metaType;
130
 
    } builtinTypes[] = {
131
 
        { QV4::CompiledData::Property::Var, QMetaType::QVariant },
132
 
        { QV4::CompiledData::Property::Variant, QMetaType::QVariant },
133
 
        { QV4::CompiledData::Property::Int, QMetaType::Int },
134
 
        { QV4::CompiledData::Property::Bool, QMetaType::Bool },
135
 
        { QV4::CompiledData::Property::Real, QMetaType::Double },
136
 
        { QV4::CompiledData::Property::String, QMetaType::QString },
137
 
        { QV4::CompiledData::Property::Url, QMetaType::QUrl },
138
 
        { QV4::CompiledData::Property::Color, QMetaType::QColor },
139
 
        { QV4::CompiledData::Property::Font, QMetaType::QFont },
140
 
        { QV4::CompiledData::Property::Time, QMetaType::QTime },
141
 
        { QV4::CompiledData::Property::Date, QMetaType::QDate },
142
 
        { QV4::CompiledData::Property::DateTime, QMetaType::QDateTime },
143
 
        { QV4::CompiledData::Property::Rect, QMetaType::QRectF },
144
 
        { QV4::CompiledData::Property::Point, QMetaType::QPointF },
145
 
        { QV4::CompiledData::Property::Size, QMetaType::QSizeF },
146
 
        { QV4::CompiledData::Property::Vector2D, QMetaType::QVector2D },
147
 
        { QV4::CompiledData::Property::Vector3D, QMetaType::QVector3D },
148
 
        { QV4::CompiledData::Property::Vector4D, QMetaType::QVector4D },
149
 
        { QV4::CompiledData::Property::Matrix4x4, QMetaType::QMatrix4x4 },
150
 
        { QV4::CompiledData::Property::Quaternion, QMetaType::QQuaternion }
151
 
    };
152
 
    static const uint builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
153
 
 
154
 
    QByteArray newClassName;
155
 
 
156
 
    if (false /* ### compileState->root == obj && !compileState->nested*/) {
157
 
#if 0 // ###
158
 
        QString path = output->url.path();
159
 
        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
160
 
        if (lastSlash > -1) {
161
 
            QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
162
 
            if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
163
 
                newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
164
 
                               QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
165
 
        }
166
 
#endif
167
 
    }
168
 
    if (newClassName.isEmpty()) {
169
 
        newClassName = QQmlMetaObject(baseTypeCache).className();
170
 
        newClassName.append("_QML_");
171
 
        newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
172
 
    }
173
 
 
174
 
    cache->_dynamicClassName = newClassName;
175
 
 
176
 
    int aliasCount = 0;
177
 
    int varPropCount = 0;
178
 
 
179
 
    const QV4::CompiledData::Property *p = obj->propertyTable();
180
 
    for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
181
 
 
182
 
        if (p->type == QV4::CompiledData::Property::Alias)
183
 
            aliasCount++;
184
 
        else if (p->type == QV4::CompiledData::Property::Var)
185
 
            varPropCount++;
186
 
 
187
 
#if 0 // ### Do this elsewhere
188
 
        // No point doing this for both the alias and non alias cases
189
 
        QQmlPropertyData *d = property(obj, p->name);
190
 
        if (d && d->isFinal())
191
 
            COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
192
 
#endif
193
 
    }
194
 
 
195
 
    typedef QQmlVMEMetaData VMD;
196
 
 
197
 
    QByteArray &dynamicData = *vmeMetaObjectData = QByteArray(sizeof(QQmlVMEMetaData)
198
 
                                                              + obj->nProperties * sizeof(VMD::PropertyData)
199
 
                                                              + obj->nFunctions * sizeof(VMD::MethodData)
200
 
                                                              + aliasCount * sizeof(VMD::AliasData), 0);
201
 
 
202
 
    int effectivePropertyIndex = cache->propertyIndexCacheStart;
203
 
    int effectiveMethodIndex = cache->methodIndexCacheStart;
204
 
 
205
 
    // For property change signal override detection.
206
 
    // We prepopulate a set of signal names which already exist in the object,
207
 
    // and throw an error if there is a signal/method defined as an override.
208
 
    QSet<QString> seenSignals;
209
 
    seenSignals << QStringLiteral("destroyed") << QStringLiteral("parentChanged") << QStringLiteral("objectNameChanged");
210
 
    QQmlPropertyCache *parentCache = cache;
211
 
    while ((parentCache = parentCache->parent())) {
212
 
        if (int pSigCount = parentCache->signalCount()) {
213
 
            int pSigOffset = parentCache->signalOffset();
214
 
            for (int i = pSigOffset; i < pSigCount; ++i) {
215
 
                QQmlPropertyData *currPSig = parentCache->signal(i);
216
 
                // XXX TODO: find a better way to get signal name from the property data :-/
217
 
                for (QQmlPropertyCache::StringCache::ConstIterator iter = parentCache->stringCache.begin();
218
 
                        iter != parentCache->stringCache.end(); ++iter) {
219
 
                    if (currPSig == (*iter).second) {
220
 
                        seenSignals.insert(iter.key());
221
 
                        break;
222
 
                    }
223
 
                }
224
 
            }
225
 
        }
226
 
    }
227
 
 
228
 
    // First set up notify signals for properties - first normal, then var, then alias
229
 
    enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
230
 
    for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
231
 
 
232
 
        if (ii == NSS_Var && varPropCount == 0) continue;
233
 
        else if (ii == NSS_Alias && aliasCount == 0) continue;
234
 
 
235
 
        const QV4::CompiledData::Property *p = obj->propertyTable();
236
 
        for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
237
 
            if ((ii == NSS_Normal && (p->type == QV4::CompiledData::Property::Alias ||
238
 
                                      p->type == QV4::CompiledData::Property::Var)) ||
239
 
                ((ii == NSS_Var) && (p->type != QV4::CompiledData::Property::Var)) ||
240
 
                ((ii == NSS_Alias) && (p->type != QV4::CompiledData::Property::Alias)))
241
 
                continue;
242
 
 
243
 
            quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
244
 
                            QQmlPropertyData::IsVMESignal;
245
 
 
246
 
            QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
247
 
            seenSignals.insert(changedSigName);
248
 
 
249
 
            cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
250
 
        }
251
 
    }
252
 
 
253
 
    // Dynamic signals
254
 
    for (uint i = 0; i < obj->nSignals; ++i) {
255
 
        const QV4::CompiledData::Signal *s = obj->signalAt(i);
256
 
        const int paramCount = s->nParameters;
257
 
 
258
 
        QList<QByteArray> names;
259
 
        QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
260
 
 
261
 
        if (paramCount) {
262
 
            paramTypes[0] = paramCount;
263
 
 
264
 
            for (int i = 0; i < paramCount; ++i) {
265
 
                const QV4::CompiledData::Parameter *param = s->parameterAt(i);
266
 
                names.append(stringAt(param->nameIndex).toUtf8());
267
 
                if (param->type < builtinTypeCount) {
268
 
                    // built-in type
269
 
                    paramTypes[i + 1] = builtinTypes[param->type].metaType;
270
 
                } else {
271
 
                    // lazily resolved type
272
 
                    Q_ASSERT(param->type == QV4::CompiledData::Property::Custom);
273
 
                    const QString customTypeName = stringAt(param->customTypeNameIndex);
274
 
                    QQmlType *qmltype = 0;
275
 
                    if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0))
276
 
                        COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(customTypeName));
277
 
 
278
 
                    if (qmltype->isComposite()) {
279
 
                        QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
280
 
                        Q_ASSERT(tdata);
281
 
                        Q_ASSERT(tdata->isComplete());
282
 
 
283
 
                        QQmlCompiledData *data = tdata->compiledData();
284
 
 
285
 
                        paramTypes[i + 1] = data->metaTypeId;
286
 
 
287
 
                        tdata->release();
288
 
                    } else {
289
 
                        paramTypes[i + 1] = qmltype->typeId();
290
 
                    }
291
 
                }
292
 
            }
293
 
        }
294
 
 
295
 
        ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
296
 
 
297
 
        quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
298
 
                        QQmlPropertyData::IsVMESignal;
299
 
        if (paramCount)
300
 
            flags |= QQmlPropertyData::HasArguments;
301
 
 
302
 
        QString signalName = stringAt(s->nameIndex);
303
 
        if (seenSignals.contains(signalName))
304
 
            COMPILE_EXCEPTION(s, tr("Duplicate signal name: invalid override of property change signal or superclass signal"));
305
 
        seenSignals.insert(signalName);
306
 
 
307
 
        cache->appendSignal(signalName, flags, effectiveMethodIndex++,
308
 
                            paramCount?paramTypes.constData():0, names);
309
 
    }
310
 
 
311
 
 
312
 
    // Dynamic slots
313
 
    const quint32 *functionIndex = obj->functionOffsetTable();
314
 
    for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
315
 
        const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
316
 
        int paramCount = s->nFormals;
317
 
 
318
 
        quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
319
 
 
320
 
        if (paramCount)
321
 
            flags |= QQmlPropertyData::HasArguments;
322
 
 
323
 
        QString slotName = stringAt(s->nameIndex);
324
 
        if (seenSignals.contains(slotName))
325
 
            COMPILE_EXCEPTION(s, tr("Duplicate method name: invalid override of property change signal or superclass signal"));
326
 
        // Note: we don't append slotName to the seenSignals list, since we don't
327
 
        // protect against overriding change signals or methods with properties.
328
 
 
329
 
        const quint32 *formalsIndices = s->formalsTable();
330
 
        QList<QByteArray> parameterNames;
331
 
        parameterNames.reserve(paramCount);
332
 
        for (int i = 0; i < paramCount; ++i)
333
 
            parameterNames << stringAt(formalsIndices[i]).toUtf8();
334
 
 
335
 
        cache->appendMethod(slotName, flags, effectiveMethodIndex++, parameterNames);
336
 
    }
337
 
 
338
 
 
339
 
    // Dynamic properties (except var and aliases)
340
 
    int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
341
 
    /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
342
 
    for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
343
 
 
344
 
        if (p->type == QV4::CompiledData::Property::Alias ||
345
 
            p->type == QV4::CompiledData::Property::Var)
346
 
            continue;
347
 
 
348
 
        int propertyType = 0;
349
 
        int vmePropertyType = 0;
350
 
        quint32 propertyFlags = 0;
351
 
 
352
 
        if (p->type < builtinTypeCount) {
353
 
            propertyType = builtinTypes[p->type].metaType;
354
 
            vmePropertyType = propertyType;
355
 
 
356
 
            if (p->type == QV4::CompiledData::Property::Variant)
357
 
                propertyFlags |= QQmlPropertyData::IsQVariant;
358
 
        } else {
359
 
            Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList ||
360
 
                     p->type == QV4::CompiledData::Property::Custom);
361
 
 
362
 
            QQmlType *qmltype = 0;
363
 
            if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
364
 
                COMPILE_EXCEPTION(p, tr("Invalid property type"));
365
 
            }
366
 
 
367
 
            Q_ASSERT(qmltype);
368
 
            if (qmltype->isComposite()) {
369
 
                QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
370
 
                Q_ASSERT(tdata);
371
 
                Q_ASSERT(tdata->isComplete());
372
 
 
373
 
                QQmlCompiledData *data = tdata->compiledData();
374
 
 
375
 
                if (p->type == QV4::CompiledData::Property::Custom) {
376
 
                    propertyType = data->metaTypeId;
377
 
                    vmePropertyType = QMetaType::QObjectStar;
378
 
                } else {
379
 
                    propertyType = data->listMetaTypeId;
380
 
                    vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
381
 
                }
382
 
 
383
 
                tdata->release();
384
 
            } else {
385
 
                if (p->type == QV4::CompiledData::Property::Custom) {
386
 
                    propertyType = qmltype->typeId();
387
 
                    vmePropertyType = QMetaType::QObjectStar;
388
 
                } else {
389
 
                    propertyType = qmltype->qListTypeId();
390
 
                    vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
391
 
                }
392
 
            }
393
 
 
394
 
            if (p->type == QV4::CompiledData::Property::Custom)
395
 
                propertyFlags |= QQmlPropertyData::IsQObjectDerived;
396
 
            else
397
 
                propertyFlags |= QQmlPropertyData::IsQList;
398
 
        }
399
 
 
400
 
        if ((!p->flags & QV4::CompiledData::Property::IsReadOnly) && p->type != QV4::CompiledData::Property::CustomList)
401
 
            propertyFlags |= QQmlPropertyData::IsWritable;
402
 
 
403
 
 
404
 
        QString propertyName = stringAt(p->nameIndex);
405
 
        if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
406
 
        cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
407
 
                              propertyType, effectiveSignalIndex);
408
 
 
409
 
        effectiveSignalIndex++;
410
 
 
411
 
        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
412
 
        (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
413
 
        vmd->propertyCount++;
414
 
    }
415
 
 
416
 
    // Now do var properties
417
 
    /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
418
 
    for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
419
 
 
420
 
        if (p->type != QV4::CompiledData::Property::Var)
421
 
            continue;
422
 
 
423
 
        quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
424
 
        if (!p->flags & QV4::CompiledData::Property::IsReadOnly)
425
 
            propertyFlags |= QQmlPropertyData::IsWritable;
426
 
 
427
 
        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
428
 
        (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
429
 
        vmd->propertyCount++;
430
 
        ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
431
 
 
432
 
        QString propertyName = stringAt(p->nameIndex);
433
 
        if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
434
 
        cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
435
 
                              QMetaType::QVariant, effectiveSignalIndex);
436
 
 
437
 
        effectiveSignalIndex++;
438
 
    }
439
 
 
440
 
    // Alias property count.  Actual data is setup in buildDynamicMetaAliases
441
 
    ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
442
 
 
443
 
    // Dynamic slot data - comes after the property data
444
 
    /*const quint32* */functionIndex = obj->functionOffsetTable();
445
 
    for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
446
 
        const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
447
 
 
448
 
        VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
449
 
                                       int(s->nFormals),
450
 
                                       /* s->location.start.line */0 }; // ###
451
 
 
452
 
        VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
453
 
        VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
454
 
        vmd->methodCount++;
455
 
        md = methodData;
456
 
    }
457
 
 
458
 
    return true;
459
 
}
460
 
 
461
74
static void removeBindingOnProperty(QObject *o, int index)
462
75
{
463
76
    int coreIndex = index & 0x0000FFFF;
467
80
    if (binding) binding->destroy();
468
81
}
469
82
 
470
 
QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData)
471
 
    : QQmlCompilePass(compiledData->url, compiledData->qmlUnit)
472
 
    , componentAttached(0)
473
 
    , engine(parentContext->engine)
474
 
    , jsUnit(compiledData->compilationUnit)
475
 
    , parentContext(parentContext)
476
 
    , context(0)
477
 
    , resolvedTypes(compiledData->resolvedTypes)
478
 
    , propertyCaches(compiledData->propertyCaches)
479
 
    , vmeMetaObjectData(compiledData->datas)
480
 
    , compiledData(compiledData)
481
 
    , _qobject(0)
482
 
    , _qobjectForBindings(0)
483
 
    , _valueTypeProperty(0)
484
 
    , _compiledObject(0)
485
 
    , _ddata(0)
486
 
    , _propertyCache(0)
487
 
    , _vmeMetaObject(0)
488
 
    , _qmlContext(0)
489
 
{
 
83
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
 
84
    : phase(Startup)
 
85
    , compiledData(compiledData)
 
86
    , resolvedTypes(compiledData->resolvedTypes)
 
87
    , propertyCaches(compiledData->propertyCaches)
 
88
    , vmeMetaObjectData(compiledData->metaObjects)
 
89
    , activeVMEDataForRootContext(activeVMEDataForRootContext)
 
90
{
 
91
    init(parentContext);
 
92
 
 
93
    sharedState = new QQmlObjectCreatorSharedState;
 
94
    sharedState.setFlag(); // We own it, so we must delete it
 
95
    sharedState->componentAttached = 0;
 
96
    sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
 
97
    sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
 
98
    sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
 
99
    sharedState->creationContext = creationContext;
 
100
    sharedState->rootContext = 0;
 
101
 
 
102
    QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
 
103
    Q_QML_PROFILE_IF_ENABLED(profiler,
 
104
            sharedState->profiler.init(profiler, compiledData->totalParserStatusCount));
 
105
}
 
106
 
 
107
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
 
108
    : phase(Startup)
 
109
    , compiledData(compiledData)
 
110
    , resolvedTypes(compiledData->resolvedTypes)
 
111
    , propertyCaches(compiledData->propertyCaches)
 
112
    , vmeMetaObjectData(compiledData->metaObjects)
 
113
    , activeVMEDataForRootContext(0)
 
114
{
 
115
    init(parentContext);
 
116
 
 
117
    sharedState = inheritedSharedState;
 
118
}
 
119
 
 
120
void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
 
121
{
 
122
    parentContext = providedParentContext;
 
123
    engine = parentContext->engine;
 
124
 
490
125
    if (!compiledData->isInitialized())
491
126
        compiledData->initialize(engine);
492
 
}
493
 
 
494
 
QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent)
495
 
{
 
127
 
 
128
    qmlUnit = compiledData->qmlUnit;
 
129
    context = 0;
 
130
    _qobject = 0;
 
131
    _scopeObject = 0;
 
132
    _valueTypeProperty = 0;
 
133
    _compiledObject = 0;
 
134
    _ddata = 0;
 
135
    _propertyCache = 0;
 
136
    _vmeMetaObject = 0;
 
137
    _qmlContext = 0;
 
138
}
 
139
 
 
140
QQmlObjectCreator::~QQmlObjectCreator()
 
141
{
 
142
    if (sharedState.flag()) {
 
143
        {
 
144
            QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data());
 
145
        }
 
146
        for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
 
147
            QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
 
148
            if (b)
 
149
                b->m_mePtr = 0;
 
150
        }
 
151
        for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
 
152
            QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
 
153
            if (ps)
 
154
                ps->d = 0;
 
155
        }
 
156
        delete sharedState.data();
 
157
    }
 
158
}
 
159
 
 
160
QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt)
 
161
{
 
162
    if (phase == CreatingObjectsPhase2) {
 
163
        phase = ObjectsCreated;
 
164
        return context->contextObject;
 
165
    }
 
166
    Q_ASSERT(phase == Startup);
 
167
    phase = CreatingObjects;
 
168
 
496
169
    int objectToCreate;
497
170
 
498
171
    if (subComponentIndex == -1) {
512
185
    context->imports->addref();
513
186
    context->setParent(parentContext);
514
187
 
 
188
    if (!sharedState->rootContext) {
 
189
        sharedState->rootContext = context;
 
190
        sharedState->rootContext->activeVMEData = activeVMEDataForRootContext;
 
191
        sharedState->rootContext->isRootObjectInCreation = true;
 
192
    }
 
193
 
515
194
    QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count());
516
195
    for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
517
196
         it != end; ++it) {
528
207
        QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
529
208
        QV4::Scope scope(v4);
530
209
        QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
 
210
        context->importedScripts = scripts;
531
211
        for (int i = 0; i < compiledData->scripts.count(); ++i) {
532
212
            QQmlScriptData *s = compiledData->scripts.at(i);
533
213
            scripts->putIndexed(i, s->scriptValueForContext(context));
534
214
        }
535
 
        context->importedScripts = scripts;
536
 
    } else if (parentContext) {
537
 
        context->importedScripts = parentContext->importedScripts;
 
215
    } else if (sharedState->creationContext) {
 
216
        context->importedScripts = sharedState->creationContext->importedScripts;
538
217
    }
539
218
 
540
 
    QObject *instance = createInstance(objectToCreate, parent);
 
219
    QObject *instance = createInstance(objectToCreate, parent, /*isContextObject*/true);
541
220
    if (instance) {
542
221
        QQmlData *ddata = QQmlData::get(instance);
543
222
        Q_ASSERT(ddata);
 
223
        if (ddata->compiledData)
 
224
            ddata->compiledData->release();
544
225
        ddata->compiledData = compiledData;
545
226
        ddata->compiledData->addref();
546
 
 
547
 
        context->contextObject = instance;
548
227
    }
 
228
 
 
229
    phase = CreatingObjectsPhase2;
 
230
 
 
231
    if (interrupt && interrupt->shouldInterrupt())
 
232
        return 0;
 
233
 
 
234
    phase = ObjectsCreated;
 
235
 
549
236
    return instance;
550
237
}
551
238
 
552
 
void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
 
239
bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
 
240
{
 
241
    QQmlData *declarativeData = QQmlData::get(instance);
 
242
    context = declarativeData->deferredData->context;
 
243
    sharedState->rootContext = context;
 
244
    const int objectIndex = declarativeData->deferredData->deferredIdx;
 
245
 
 
246
    const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
 
247
    QObject *bindingTarget = instance;
 
248
 
 
249
    QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
 
250
    QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
 
251
 
 
252
    QObject *scopeObject = instance;
 
253
    qSwap(_scopeObject, scopeObject);
 
254
 
 
255
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
 
256
    QV4::Scope valueScope(v4);
 
257
    QV4::ScopedValue scopeObjectProtector(valueScope, declarativeData->jsWrapper.value());
 
258
    Q_UNUSED(scopeObjectProtector);
 
259
    QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
 
260
    QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
 
261
    QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
 
262
 
 
263
    qSwap(_qmlContext, qmlContext);
 
264
 
 
265
    qSwap(_propertyCache, cache);
 
266
    qSwap(_qobject, instance);
 
267
    qSwap(_compiledObject, obj);
 
268
    qSwap(_ddata, declarativeData);
 
269
    qSwap(_bindingTarget, bindingTarget);
 
270
    qSwap(_vmeMetaObject, vmeMetaObject);
 
271
 
 
272
    QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(objectIndex);
 
273
    for (int i = 0; i < bindingSkipList.count(); ++i)
 
274
        bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
 
275
 
 
276
    setupBindings(bindingSkipList);
 
277
 
 
278
    qSwap(_vmeMetaObject, vmeMetaObject);
 
279
    qSwap(_bindingTarget, bindingTarget);
 
280
    qSwap(_ddata, declarativeData);
 
281
    qSwap(_compiledObject, obj);
 
282
    qSwap(_qobject, instance);
 
283
    qSwap(_propertyCache, cache);
 
284
 
 
285
    qSwap(_qmlContext, qmlContext);
 
286
    qSwap(_scopeObject, scopeObject);
 
287
 
 
288
    phase = ObjectsCreated;
 
289
 
 
290
    return errors.isEmpty();
 
291
}
 
292
 
 
293
void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
553
294
{
554
295
    QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
555
296
                                                               QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
558
299
 
559
300
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
560
301
    QV4::Scope scope(v4);
561
 
    // ### enums
562
 
 
563
 
    switch (property->propType) {
 
302
 
 
303
    int propertyType = property->propType;
 
304
 
 
305
    if (property->isEnum()) {
 
306
        if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) {
 
307
            propertyType = QMetaType::Int;
 
308
        } else {
 
309
            // ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
 
310
            QVariant value = binding->valueAsString(&qmlUnit->header);
 
311
            bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
 
312
            Q_ASSERT(ok);
 
313
            Q_UNUSED(ok);
 
314
            return;
 
315
        }
 
316
    }
 
317
 
 
318
    switch (propertyType) {
564
319
    case QMetaType::QVariant: {
565
320
        if (binding->type == QV4::CompiledData::Binding::Type_Number) {
566
321
            double n = binding->valueAsNumber();
604
359
    }
605
360
    break;
606
361
    case QVariant::String: {
607
 
        if (binding->type == QV4::CompiledData::Binding::Type_String) {
608
 
            QString value = binding->valueAsString(&qmlUnit->header);
609
 
            argv[0] = &value;
610
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
611
 
        } else {
612
 
            recordError(binding->location, tr("Invalid property assignment: string expected"));
613
 
        }
 
362
        Q_ASSERT(binding->evaluatesToString());
 
363
        QString value = binding->valueAsString(&qmlUnit->header);
 
364
        argv[0] = &value;
 
365
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
614
366
    }
615
367
    break;
616
368
    case QVariant::StringList: {
617
 
        if (binding->type == QV4::CompiledData::Binding::Type_String) {
618
 
            QStringList value(binding->valueAsString(&qmlUnit->header));
619
 
            argv[0] = &value;
620
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
621
 
        } else {
622
 
            recordError(binding->location, tr("Invalid property assignment: string or string list expected"));
623
 
        }
 
369
        Q_ASSERT(binding->evaluatesToString());
 
370
        QStringList value(binding->valueAsString(&qmlUnit->header));
 
371
        argv[0] = &value;
 
372
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
624
373
    }
625
374
    break;
626
375
    case QVariant::ByteArray: {
627
 
        if (binding->type == QV4::CompiledData::Binding::Type_String) {
628
 
            QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
629
 
            argv[0] = &value;
630
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
631
 
        } else {
632
 
            recordError(binding->location, tr("Invalid property assignment: byte array expected"));
633
 
        }
 
376
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
 
377
        QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
 
378
        argv[0] = &value;
 
379
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
634
380
    }
635
381
    break;
636
382
    case QVariant::Url: {
637
 
        if (binding->type == QV4::CompiledData::Binding::Type_String) {
638
 
            QString string = binding->valueAsString(&qmlUnit->header);
639
 
            // Encoded dir-separators defeat QUrl processing - decode them first
640
 
            string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
641
 
            QUrl value = string.isEmpty() ? QUrl() : this->url.resolved(QUrl(string));
642
 
            // Apply URL interceptor
643
 
            if (engine->urlInterceptor())
644
 
                value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
645
 
            argv[0] = &value;
646
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
647
 
        } else {
648
 
            recordError(binding->location, tr("Invalid property assignment: url expected"));
649
 
        }
 
383
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
 
384
        QString string = binding->valueAsString(&qmlUnit->header);
 
385
        // Encoded dir-separators defeat QUrl processing - decode them first
 
386
        string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
 
387
        QUrl value = string.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(string));
 
388
        // Apply URL interceptor
 
389
        if (engine->urlInterceptor())
 
390
            value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
 
391
        argv[0] = &value;
 
392
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
650
393
    }
651
394
    break;
652
395
    case QVariant::UInt: {
653
 
        if (binding->type == QV4::CompiledData::Binding::Type_Number) {
654
 
            double d = binding->valueAsNumber();
655
 
            if (double(uint(d)) == d) {
656
 
                uint value = uint(d);
657
 
                argv[0] = &value;
658
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
659
 
                break;
660
 
            }
661
 
        }
662
 
        recordError(binding->location, tr("Invalid property assignment: unsigned int expected"));
 
396
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
397
        double d = binding->valueAsNumber();
 
398
        uint value = uint(d);
 
399
        argv[0] = &value;
 
400
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
 
401
        break;
663
402
    }
664
403
    break;
665
404
    case QVariant::Int: {
666
 
        if (binding->type == QV4::CompiledData::Binding::Type_Number) {
667
 
            double d = binding->valueAsNumber();
668
 
            if (double(int(d)) == d) {
669
 
                int value = int(d);
670
 
                argv[0] = &value;
671
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
672
 
                break;
673
 
            }
674
 
        }
675
 
        recordError(binding->location, tr("Invalid property assignment: int expected"));
 
405
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
406
        double d = binding->valueAsNumber();
 
407
        int value = int(d);
 
408
        argv[0] = &value;
 
409
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
 
410
        break;
676
411
    }
677
412
    break;
678
413
    case QMetaType::Float: {
679
 
        if (binding->type == QV4::CompiledData::Binding::Type_Number) {
680
 
            float value = float(binding->valueAsNumber());
681
 
            argv[0] = &value;
682
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
683
 
        } else {
684
 
            recordError(binding->location, tr("Invalid property assignment: number expected"));
685
 
        }
 
414
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
415
        float value = float(binding->valueAsNumber());
 
416
        argv[0] = &value;
 
417
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
686
418
    }
687
419
    break;
688
420
    case QVariant::Double: {
689
 
        if (binding->type == QV4::CompiledData::Binding::Type_Number) {
690
 
            double value = binding->valueAsNumber();
691
 
            argv[0] = &value;
692
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
693
 
        } else {
694
 
            recordError(binding->location, tr("Invalid property assignment: number expected"));
695
 
        }
 
421
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
422
        double value = binding->valueAsNumber();
 
423
        argv[0] = &value;
 
424
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
696
425
    }
697
426
    break;
698
427
    case QVariant::Color: {
699
428
        bool ok = false;
700
429
        uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(&qmlUnit->header), &ok);
701
 
 
702
 
        if (ok) {
703
 
            struct { void *data[4]; } buffer;
704
 
            if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
705
 
                argv[0] = reinterpret_cast<void *>(&buffer);
706
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
707
 
            }
708
 
        } else {
709
 
            recordError(binding->location, tr("Invalid property assignment: color expected"));
 
430
        Q_ASSERT(ok);
 
431
        struct { void *data[4]; } buffer;
 
432
        if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
 
433
            argv[0] = reinterpret_cast<void *>(&buffer);
 
434
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
710
435
        }
711
436
    }
712
437
    break;
714
439
    case QVariant::Date: {
715
440
        bool ok = false;
716
441
        QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(&qmlUnit->header), &ok);
717
 
        if (ok) {
718
 
            argv[0] = &value;
719
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
720
 
        } else {
721
 
            recordError(binding->location, tr("Invalid property assignment: date expected"));
722
 
        }
 
442
        Q_ASSERT(ok);
 
443
        argv[0] = &value;
 
444
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
723
445
    }
724
446
    break;
725
447
    case QVariant::Time: {
726
448
        bool ok = false;
727
449
        QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(&qmlUnit->header), &ok);
728
 
        if (ok) {
729
 
            argv[0] = &value;
730
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
731
 
        } else {
732
 
            recordError(binding->location, tr("Invalid property assignment: time expected"));
733
 
        }
 
450
        Q_ASSERT(ok);
 
451
        argv[0] = &value;
 
452
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
734
453
    }
735
454
    break;
736
455
    case QVariant::DateTime: {
737
456
        bool ok = false;
738
457
        QDateTime value = QQmlStringConverters::dateTimeFromString(binding->valueAsString(&qmlUnit->header), &ok);
739
 
        if (ok) {
740
 
            argv[0] = &value;
741
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
742
 
        } else {
743
 
            recordError(binding->location, tr("Invalid property assignment: datetime expected"));
 
458
        // ### VME compatibility :(
 
459
        {
 
460
            const qint64 date = value.date().toJulianDay();
 
461
            const int msecsSinceStartOfDay = value.time().msecsSinceStartOfDay();
 
462
            value = QDateTime(QDate::fromJulianDay(date), QTime::fromMSecsSinceStartOfDay(msecsSinceStartOfDay));
744
463
        }
 
464
        Q_ASSERT(ok);
 
465
        argv[0] = &value;
 
466
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
745
467
    }
746
468
    break;
747
469
#endif // QT_NO_DATESTRING
748
470
    case QVariant::Point: {
749
471
        bool ok = false;
750
472
        QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
751
 
        if (ok) {
752
 
            argv[0] = &value;
753
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
754
 
        } else {
755
 
            recordError(binding->location, tr("Invalid property assignment: point expected"));
756
 
        }
 
473
        Q_ASSERT(ok);
 
474
        argv[0] = &value;
 
475
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
757
476
    }
758
477
    break;
759
478
    case QVariant::PointF: {
760
479
        bool ok = false;
761
480
        QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
762
 
        if (ok) {
763
 
            argv[0] = &value;
764
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
765
 
        } else {
766
 
            recordError(binding->location, tr("Invalid property assignment: point expected"));
767
 
        }
 
481
        Q_ASSERT(ok);
 
482
        argv[0] = &value;
 
483
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
768
484
    }
769
485
    break;
770
486
    case QVariant::Size: {
771
487
        bool ok = false;
772
488
        QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
773
 
        if (ok) {
774
 
            argv[0] = &value;
775
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
776
 
        } else {
777
 
            recordError(binding->location, tr("Invalid property assignment: size expected"));
778
 
        }
 
489
        Q_ASSERT(ok);
 
490
        argv[0] = &value;
 
491
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
779
492
    }
780
493
    break;
781
494
    case QVariant::SizeF: {
782
495
        bool ok = false;
783
496
        QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
784
 
        if (ok) {
785
 
            argv[0] = &value;
786
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
787
 
        } else {
788
 
            recordError(binding->location, tr("Invalid property assignment: size expected"));
789
 
        }
 
497
        Q_ASSERT(ok);
 
498
        argv[0] = &value;
 
499
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
790
500
    }
791
501
    break;
792
502
    case QVariant::Rect: {
793
503
        bool ok = false;
794
504
        QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
795
 
        if (ok) {
796
 
            argv[0] = &value;
797
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
798
 
        } else {
799
 
            recordError(binding->location, tr("Invalid property assignment: point expected"));
800
 
        }
 
505
        Q_ASSERT(ok);
 
506
        argv[0] = &value;
 
507
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
801
508
    }
802
509
    break;
803
510
    case QVariant::RectF: {
804
511
        bool ok = false;
805
512
        QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
806
 
        if (ok) {
807
 
            argv[0] = &value;
808
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
809
 
        } else {
810
 
            recordError(binding->location, tr("Invalid property assignment: point expected"));
811
 
        }
 
513
        Q_ASSERT(ok);
 
514
        argv[0] = &value;
 
515
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
812
516
    }
813
517
    break;
814
518
    case QVariant::Bool: {
815
 
        if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
816
 
            bool value = binding->valueAsBoolean();
817
 
            argv[0] = &value;
818
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
819
 
        } else {
820
 
            recordError(binding->location, tr("Invalid property assignment: boolean expected"));
821
 
        }
 
519
        Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
 
520
        bool value = binding->valueAsBoolean();
 
521
        argv[0] = &value;
 
522
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
822
523
    }
823
524
    break;
824
525
    case QVariant::Vector3D: {
827
528
            float yp;
828
529
            float zy;
829
530
        } vec;
830
 
        if (QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
831
 
            argv[0] = reinterpret_cast<void *>(&vec);
832
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
833
 
        } else {
834
 
            recordError(binding->location, tr("Invalid property assignment: 3D vector expected"));
835
 
        }
 
531
        bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
 
532
        Q_ASSERT(ok);
 
533
        Q_UNUSED(ok);
 
534
        argv[0] = reinterpret_cast<void *>(&vec);
 
535
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
836
536
    }
837
537
    break;
838
538
    case QVariant::Vector4D: {
842
542
            float zy;
843
543
            float wp;
844
544
        } vec;
845
 
        if (QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
846
 
            argv[0] = reinterpret_cast<void *>(&vec);
847
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
848
 
        } else {
849
 
            recordError(binding->location, tr("Invalid property assignment: 4D vector expected"));
850
 
        }
 
545
        bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
 
546
        Q_ASSERT(ok);
 
547
        Q_UNUSED(ok);
 
548
        argv[0] = reinterpret_cast<void *>(&vec);
 
549
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
851
550
    }
852
551
    break;
853
552
    case QVariant::RegExp:
854
 
        recordError(binding->location, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
 
553
        Q_ASSERT(!"not possible");
855
554
        break;
856
555
    default: {
857
556
        // generate single literal value assignment to a list property if required
858
557
        if (property->propType == qMetaTypeId<QList<qreal> >()) {
859
 
            if (binding->type == QV4::CompiledData::Binding::Type_Number) {
860
 
                QList<qreal> value;
861
 
                value.append(binding->valueAsNumber());
862
 
                argv[0] = reinterpret_cast<void *>(&value);
863
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
864
 
            } else {
865
 
                recordError(binding->location, tr("Invalid property assignment: real or array of reals expected"));
866
 
            }
 
558
            Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
559
            QList<qreal> value;
 
560
            value.append(binding->valueAsNumber());
 
561
            argv[0] = reinterpret_cast<void *>(&value);
 
562
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
867
563
            break;
868
564
        } else if (property->propType == qMetaTypeId<QList<int> >()) {
869
 
            if (binding->type == QV4::CompiledData::Binding::Type_Number) {
870
 
                double n = binding->valueAsNumber();
871
 
                if (double(int(n)) == n) {
872
 
                    QList<int> value;
873
 
                    value.append(int(n));
874
 
                    argv[0] = reinterpret_cast<void *>(&value);
875
 
                    QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
876
 
                    break;
877
 
                } else {
878
 
                    recordError(binding->location, tr("Invalid property assignment: int or array of ints expected"));
879
 
                }
880
 
            }
 
565
            Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
 
566
            double n = binding->valueAsNumber();
 
567
            QList<int> value;
 
568
            value.append(int(n));
 
569
            argv[0] = reinterpret_cast<void *>(&value);
 
570
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
881
571
            break;
882
572
        } else if (property->propType == qMetaTypeId<QList<bool> >()) {
883
 
            if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
884
 
                QList<bool> value;
885
 
                value.append(binding->valueAsBoolean());
886
 
                argv[0] = reinterpret_cast<void *>(&value);
887
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
888
 
            } else {
889
 
                recordError(binding->location, tr("Invalid property assignment: bool or array of bools expected"));
890
 
            }
 
573
            Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
 
574
            QList<bool> value;
 
575
            value.append(binding->valueAsBoolean());
 
576
            argv[0] = reinterpret_cast<void *>(&value);
 
577
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
891
578
            break;
892
579
        } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
893
 
            if (binding->type == QV4::CompiledData::Binding::Type_String) {
894
 
                QString urlString = binding->valueAsString(&qmlUnit->header);
895
 
                QUrl u = urlString.isEmpty() ? QUrl() : this->url.resolved(QUrl(urlString));
896
 
                QList<QUrl> value;
897
 
                value.append(u);
898
 
                argv[0] = reinterpret_cast<void *>(&value);
899
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
900
 
            } else {
901
 
                recordError(binding->location, tr("Invalid property assignment: url or array of urls expected"));
902
 
            }
 
580
            Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
 
581
            QString urlString = binding->valueAsString(&qmlUnit->header);
 
582
            QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(urlString));
 
583
            QList<QUrl> value;
 
584
            value.append(u);
 
585
            argv[0] = reinterpret_cast<void *>(&value);
 
586
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
903
587
            break;
904
588
        } else if (property->propType == qMetaTypeId<QList<QString> >()) {
905
 
            if (binding->type == QV4::CompiledData::Binding::Type_String) {
906
 
                QList<QString> value;
907
 
                value.append(binding->valueAsString(&qmlUnit->header));
908
 
                argv[0] = reinterpret_cast<void *>(&value);
909
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
910
 
            } else {
911
 
                recordError(binding->location, tr("Invalid property assignment: string or array of strings expected"));
912
 
            }
 
589
            Q_ASSERT(binding->evaluatesToString());
 
590
            QList<QString> value;
 
591
            value.append(binding->valueAsString(&qmlUnit->header));
 
592
            argv[0] = reinterpret_cast<void *>(&value);
 
593
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
913
594
            break;
914
595
        } else if (property->propType == qMetaTypeId<QJSValue>()) {
915
596
            QJSValue value;
932
613
        // otherwise, try a custom type assignment
933
614
        QString stringValue = binding->valueAsString(&qmlUnit->header);
934
615
        QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
935
 
        if (converter) {
936
 
            QVariant value = (*converter)(stringValue);
937
 
 
938
 
            QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
939
 
            if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
940
 
                recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
941
 
                break;
942
 
            }
943
 
 
944
 
            argv[0] = value.data();
945
 
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
946
 
        } else {
947
 
            recordError(binding->location, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
 
616
        Q_ASSERT(converter);
 
617
        QVariant value = (*converter)(stringValue);
 
618
 
 
619
        QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
 
620
        if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
 
621
            recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
 
622
            break;
948
623
        }
 
624
 
 
625
        argv[0] = value.data();
 
626
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
949
627
    }
950
628
    break;
951
629
    }
952
630
}
953
631
 
954
 
void QmlObjectCreator::setupBindings()
 
632
static QQmlType *qmlTypeForObject(QObject *object)
 
633
{
 
634
    QQmlType *type = 0;
 
635
    const QMetaObject *mo = object->metaObject();
 
636
    while (mo && !type) {
 
637
        type = QQmlMetaType::qmlType(mo);
 
638
        mo = mo->superClass();
 
639
    }
 
640
    return type;
 
641
}
 
642
 
 
643
void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
955
644
{
956
645
    QQmlListProperty<void> savedList;
957
646
    qSwap(_currentList, savedList);
958
647
 
959
648
    QQmlPropertyData *property = 0;
960
 
    bool defaultPropertyQueried = false;
961
 
    QQmlPropertyData *defaultProperty = 0;
 
649
    QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
962
650
 
963
651
    QString id = stringAt(_compiledObject->idIndex);
964
652
    if (!id.isEmpty()) {
965
653
        QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
966
 
        if (idProperty) {
 
654
        if (idProperty && idProperty->isWritable()) {
967
655
            QV4::CompiledData::Binding idBinding;
968
656
            idBinding.propertyNameIndex = 0; // Not used
969
657
            idBinding.flags = 0;
974
662
        }
975
663
    }
976
664
 
 
665
    // ### this is best done through type-compile-time binding skip lists.
 
666
    if (_valueTypeProperty) {
 
667
        QQmlAbstractBinding *binding =
 
668
            QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
 
669
 
 
670
        if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
 
671
            QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
 
672
            binding->destroy();
 
673
        } else if (binding) {
 
674
            QQmlValueTypeProxyBinding *proxy =
 
675
                static_cast<QQmlValueTypeProxyBinding *>(binding);
 
676
 
 
677
            if (qmlTypeForObject(_bindingTarget)) {
 
678
                quint32 bindingSkipList = 0;
 
679
 
 
680
                const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
 
681
                for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
 
682
                    property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
 
683
                    if (property)
 
684
                        bindingSkipList |= (1 << property->coreIndex);
 
685
                }
 
686
                property = 0;
 
687
 
 
688
                proxy->removeBindings(bindingSkipList);
 
689
            }
 
690
        }
 
691
    }
 
692
 
977
693
    const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
978
694
    for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
979
695
 
981
697
        if (name.isEmpty())
982
698
            property = 0;
983
699
 
984
 
        if (!property || (i > 0 && (binding - 1)->propertyNameIndex != binding->propertyNameIndex)) {
985
 
            if (!name.isEmpty())
986
 
                property = _propertyCache->property(name, _qobject, context);
987
 
            else {
988
 
                if (!defaultPropertyQueried) {
989
 
                    defaultProperty = _propertyCache->defaultProperty();
990
 
                    defaultPropertyQueried = true;
991
 
                }
 
700
        if (!property
 
701
            || (i > 0 && ((binding - 1)->propertyNameIndex != binding->propertyNameIndex
 
702
                          || (binding - 1)->flags != binding->flags))
 
703
           ) {
 
704
            if (!name.isEmpty()) {
 
705
                if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
 
706
                    || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
 
707
                    property = QmlIR::PropertyResolver(_propertyCache).signal(name, /*notInRevision*/0, _qobject, context);
 
708
                else
 
709
                    property = _propertyCache->property(name, _qobject, context);
 
710
            } else
992
711
                property = defaultProperty;
993
 
            }
994
712
 
995
713
            if (property && property->isQList()) {
996
714
                void *argv[1] = { (void*)&_currentList };
1000
718
 
1001
719
        }
1002
720
 
1003
 
        if (!setPropertyValue(property, i, binding))
 
721
        if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
 
722
            continue;
 
723
 
 
724
        if (!setPropertyBinding(property, binding))
1004
725
            return;
1005
726
    }
1006
727
 
1007
728
    qSwap(_currentList, savedList);
1008
729
}
1009
730
 
1010
 
bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingIndex, const QV4::CompiledData::Binding *binding)
 
731
bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
1011
732
{
1012
733
    if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
1013
734
        Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
1014
 
        QQmlType *attachedType = resolvedTypes.value(binding->propertyNameIndex).type;
 
735
        QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
 
736
        Q_ASSERT(tr);
 
737
        QQmlType *attachedType = tr->type;
1015
738
        const int id = attachedType->attachedPropertiesId();
1016
739
        QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject);
1017
 
        QQmlRefPointer<QQmlPropertyCache> cache = QQmlEnginePrivate::get(engine)->cache(qmlObject);
1018
 
        if (!populateInstance(binding->value.objectIndex, qmlObject, cache, _qobject, /*value type property*/0))
 
740
        if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject, /*value type property*/0))
1019
741
            return false;
1020
742
        return true;
1021
743
    }
1022
744
 
 
745
    // ### resolve this at compile time
 
746
    if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
 
747
        QQmlScriptString ss(binding->valueAsScriptString(&qmlUnit->header), context->asQQmlContext(), _scopeObject);
 
748
        ss.d.data()->bindingId = binding->value.compiledScriptIndex;
 
749
        ss.d.data()->lineNumber = binding->location.line;
 
750
        ss.d.data()->columnNumber = binding->location.column;
 
751
        ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String;
 
752
        ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number;
 
753
        ss.d.data()->numberValue = binding->valueAsNumber();
 
754
 
 
755
        QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
 
756
                                                                   QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
 
757
        int propertyWriteStatus = -1;
 
758
        void *argv[] = { &ss, 0, &propertyWriteStatus, &propertyWriteFlags };
 
759
        QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
 
760
        return true;
 
761
    }
 
762
 
1023
763
    QObject *createdSubObject = 0;
1024
764
    if (binding->type == QV4::CompiledData::Binding::Type_Object) {
1025
 
        createdSubObject = createInstance(binding->value.objectIndex, _qobject);
 
765
        createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
1026
766
        if (!createdSubObject)
1027
767
            return false;
1028
768
    }
1034
774
        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(binding->value.objectIndex);
1035
775
        if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
1036
776
 
1037
 
            QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
1038
 
            QQmlRefPointer<QQmlPropertyCache> groupedObjCache;
1039
 
            QObject *groupedObjInstance = 0;
1040
 
            QObject *objForBindings = _qobjectForBindings;
 
777
            QObject *groupObject = 0;
1041
778
            QQmlValueType *valueType = 0;
1042
779
            QQmlPropertyData *valueTypeProperty = 0;
 
780
            QObject *bindingTarget = _bindingTarget;
1043
781
 
1044
782
            if (QQmlValueTypeFactory::isValueType(property->propType)) {
1045
783
                valueType = QQmlValueTypeFactory::valueType(property->propType);
1050
788
 
1051
789
                valueType->read(_qobject, property->coreIndex);
1052
790
 
1053
 
                groupedObjCache = enginePrivate->cache(valueType);
1054
 
                groupedObjInstance = valueType;
 
791
                groupObject = valueType;
1055
792
                valueTypeProperty = property;
1056
793
            } else {
1057
 
                groupedObjCache = enginePrivate->propertyCacheForType(property->propType);
1058
 
                if (!groupedObjCache) {
1059
 
                    recordError(binding->location, tr("Invalid grouped property access"));
1060
 
                    return false;
1061
 
                }
1062
 
 
1063
 
                void *argv[1] = { &groupedObjInstance };
 
794
                void *argv[1] = { &groupObject };
1064
795
                QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
1065
 
                if (!groupedObjInstance) {
 
796
                if (!groupObject) {
1066
797
                    recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
1067
798
                    return false;
1068
799
                }
1069
800
 
1070
 
                objForBindings = groupedObjInstance;
 
801
                bindingTarget = groupObject;
1071
802
            }
1072
803
 
1073
 
            if (!populateInstance(binding->value.objectIndex, groupedObjInstance, groupedObjCache, objForBindings, valueTypeProperty))
 
804
            if (!populateInstance(binding->value.objectIndex, groupObject, bindingTarget, valueTypeProperty))
1074
805
                return false;
1075
806
 
1076
807
            if (valueType)
1080
811
        }
1081
812
    }
1082
813
 
1083
 
    if (_ddata->hasBindingBit(property->coreIndex))
1084
 
        removeBindingOnProperty(_qobject, property->coreIndex);
 
814
    if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
 
815
        && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
 
816
        && !_valueTypeProperty)
 
817
        removeBindingOnProperty(_bindingTarget, property->coreIndex);
1085
818
 
1086
819
    if (binding->type == QV4::CompiledData::Binding::Type_Script) {
1087
 
        QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
 
820
        QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1088
821
 
1089
822
        QV4::Scope scope(_qmlContext);
1090
 
        QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction));
 
823
        QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction, /*createProto*/ false));
1091
824
 
1092
825
        if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
1093
826
            int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
1094
 
            QQmlBoundSignal *bs = new QQmlBoundSignal(_qobject, signalIndex, _qobject, engine);
1095
 
            QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_qobject, signalIndex,
1096
 
                                                                            context, _qobject, function);
 
827
            QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
 
828
            QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
 
829
                                                                            context, _scopeObject, function);
1097
830
 
1098
831
            bs->takeExpression(expr);
1099
832
        } else {
1100
 
            QQmlBinding *qmlBinding = new QQmlBinding(function, _qobject, context,
1101
 
                                                      QString(), 0, 0); // ###
 
833
            QQmlBinding *qmlBinding = new QQmlBinding(function, _scopeObject, context);
1102
834
 
1103
835
            // When writing bindings to grouped properties implemented as value types,
1104
836
            // such as point.x: { someExpression; }, then the binding is installed on
1109
841
            if (_valueTypeProperty)
1110
842
                targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
1111
843
 
1112
 
            qmlBinding->setTarget(_qobjectForBindings, targetCorePropertyData, context);
1113
 
            qmlBinding->addToObject();
1114
 
 
1115
 
            _createdBindings[bindingIndex] = qmlBinding;
1116
 
            qmlBinding->m_mePtr = &_createdBindings[bindingIndex];
 
844
            sharedState->allCreatedBindings.push(qmlBinding);
 
845
            qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top();
 
846
 
 
847
            qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context);
 
848
 
 
849
            if (targetCorePropertyData.isAlias()) {
 
850
                QQmlAbstractBinding *old =
 
851
                    QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget,
 
852
                                                            targetCorePropertyData.coreIndex,
 
853
                                                            targetCorePropertyData.getValueTypeCoreIndex(),
 
854
                                                            qmlBinding);
 
855
                if (old) { old->destroy(); }
 
856
            } else {
 
857
                qmlBinding->addToObject();
 
858
 
 
859
                if (!_valueTypeProperty) {
 
860
                    QQmlData *targetDeclarativeData = QQmlData::get(_bindingTarget);
 
861
                    Q_ASSERT(targetDeclarativeData);
 
862
                    targetDeclarativeData->setPendingBindingBit(_bindingTarget, property->coreIndex);
 
863
                }
 
864
            }
1117
865
        }
1118
866
        return true;
1119
867
    }
1120
868
 
1121
869
    if (binding->type == QV4::CompiledData::Binding::Type_Object) {
 
870
        if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
 
871
            // ### determine value source and interceptor casts ahead of time.
 
872
            QQmlType *type = qmlTypeForObject(createdSubObject);
 
873
            Q_ASSERT(type);
 
874
 
 
875
            QQmlPropertyData targetCorePropertyData = *property;
 
876
            if (_valueTypeProperty)
 
877
                targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
 
878
 
 
879
            int valueSourceCast = type->propertyValueSourceCast();
 
880
            if (valueSourceCast != -1) {
 
881
                QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
 
882
                QObject *target = createdSubObject->parent();
 
883
                vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
 
884
                return true;
 
885
            }
 
886
            int valueInterceptorCast = type->propertyValueInterceptorCast();
 
887
            if (valueInterceptorCast != -1) {
 
888
                QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
 
889
                QObject *target = createdSubObject->parent();
 
890
 
 
891
                QQmlProperty prop =
 
892
                    QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
 
893
                vi->setTarget(prop);
 
894
                QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
 
895
                Q_ASSERT(mo);
 
896
                mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
 
897
                return true;
 
898
            }
 
899
            return false;
 
900
        }
 
901
 
 
902
        // Assigning object to signal property?
 
903
        if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
 
904
            if (!property->isFunction()) {
 
905
                recordError(binding->valueLocation, tr("Cannot assign an object to signal property %1").arg(property->name(_qobject)));
 
906
                return false;
 
907
            }
 
908
            QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
 
909
            if (!method.isValid()) {
 
910
                recordError(binding->valueLocation, tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
 
911
                return false;
 
912
            }
 
913
 
 
914
            QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex);
 
915
            if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
 
916
                recordError(binding->valueLocation, tr("Cannot connect mismatched signal/slot %1 %vs. %2")
 
917
                              .arg(QString::fromLatin1(method.methodSignature().constData()))
 
918
                              .arg(QString::fromLatin1(signalMethod.methodSignature().constData())));
 
919
                return false;
 
920
            }
 
921
 
 
922
            QQmlPropertyPrivate::connect(_qobject, property->coreIndex, createdSubObject, method.methodIndex());
 
923
            return true;
 
924
        }
 
925
 
1122
926
        QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
1123
927
                                                                   QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
1124
928
        int propertyWriteStatus = -1;
1158
962
 
1159
963
            if (_currentList.append)
1160
964
                _currentList.append(&_currentList, itemToAdd);
 
965
            else {
 
966
                recordError(binding->location, tr("Cannot assign object to read only list"));
 
967
                return false;
 
968
            }
 
969
 
1161
970
        } else {
1162
 
            QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
1163
 
 
1164
 
            // We want to raw metaObject here as the raw metaobject is the
1165
 
            // actual property type before we applied any extensions that might
1166
 
            // effect the properties on the type, but don't effect assignability
1167
 
            QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
1168
 
 
1169
 
            // Will be true if the assgned type inherits propertyMetaObject
1170
 
            bool isAssignable = false;
1171
 
            // Determine isAssignable value
1172
 
            if (propertyMetaObject) {
1173
 
                QQmlPropertyCache *c = propertyCaches.value(binding->value.objectIndex);
1174
 
                if (!c)
1175
 
                    c = enginePrivate->cache(createdSubObject);
1176
 
                while (c && !isAssignable) {
1177
 
                    isAssignable |= c == propertyMetaObject;
1178
 
                    c = c->parent();
1179
 
                }
1180
 
            }
1181
 
 
1182
 
            if (isAssignable) {
1183
 
                argv[0] = &createdSubObject;
1184
 
                QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
1185
 
            } else {
1186
 
                recordError(binding->location, tr("Cannot assign object to property"));
1187
 
                return false;
1188
 
            }
 
971
            // pointer compatibility was tested in QQmlPropertyValidator at type compile time
 
972
            argv[0] = &createdSubObject;
 
973
            QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
1189
974
        }
1190
975
        return true;
1191
976
    }
1199
984
    return true;
1200
985
}
1201
986
 
1202
 
void QmlObjectCreator::setupFunctions()
 
987
void QQmlObjectCreator::setupFunctions()
1203
988
{
1204
989
    QV4::Scope scope(_qmlContext);
1205
990
    QV4::ScopedValue function(scope);
1206
 
    QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(_qobject);
1207
991
 
1208
992
    const quint32 *functionIdx = _compiledObject->functionOffsetTable();
1209
993
    for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1210
 
        QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[*functionIdx];
1211
 
        const QString name = runtimeFunction->name->toQString();
 
994
        QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[*functionIdx];
 
995
        const QString name = runtimeFunction->name()->toQString();
1212
996
 
1213
997
        QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
1214
998
        if (!property->isVMEFunction())
1215
999
            continue;
1216
1000
 
1217
 
        function = QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction);
1218
 
        vme->setVmeMethod(property->coreIndex, function);
 
1001
        function = QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction);
 
1002
        _vmeMetaObject->setVmeMethod(property->coreIndex, function);
1219
1003
    }
1220
1004
}
1221
1005
 
1222
 
QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
1223
 
{
 
1006
void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
 
1007
{
 
1008
    QQmlError error;
 
1009
    error.setUrl(compiledData->url);
 
1010
    error.setLine(location.line);
 
1011
    error.setColumn(location.column);
 
1012
    error.setDescription(description);
 
1013
    errors << error;
 
1014
}
 
1015
 
 
1016
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
 
1017
{
 
1018
    QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
1224
1019
    ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
1225
1020
 
1226
1021
    bool isComponent = false;
1227
1022
    QObject *instance = 0;
 
1023
    QQmlData *ddata = 0;
 
1024
    QQmlCustomParser *customParser = 0;
 
1025
    QQmlParserStatus *parserStatus = 0;
 
1026
    bool installPropertyCache = true;
1228
1027
 
 
1028
    const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
1229
1029
    if (compiledData->isComponent(index)) {
1230
1030
        isComponent = true;
1231
1031
        QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
 
1032
        Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"),
 
1033
                context->url, obj->location.line, obj->location.column));
1232
1034
        QQmlComponentPrivate::get(component)->creationContext = context;
1233
1035
        instance = component;
 
1036
        ddata = QQmlData::get(instance, /*create*/true);
1234
1037
    } else {
1235
 
        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
1236
 
 
1237
 
        QQmlCompiledData::TypeReference typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
1238
 
        QQmlType *type = typeRef.type;
 
1038
        QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
 
1039
        Q_ASSERT(typeRef);
 
1040
        installPropertyCache = !typeRef->isFullyDynamicType;
 
1041
        QQmlType *type = typeRef->type;
1239
1042
        if (type) {
 
1043
            Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
 
1044
                    context->url, obj->location.line, obj->location.column));
1240
1045
            instance = type->create();
1241
1046
            if (!instance) {
1242
1047
                recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
1243
1048
                return 0;
1244
1049
            }
 
1050
 
 
1051
            const int parserStatusCast = type->parserStatusCast();
 
1052
            if (parserStatusCast != -1)
 
1053
                parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
 
1054
 
 
1055
            customParser = type->customParser();
 
1056
 
 
1057
            if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
 
1058
                QQmlData *ddata = QQmlData::get(instance, /*create*/true);
 
1059
                ddata->rootObjectInCreation = true;
 
1060
                sharedState->rootContext->isRootObjectInCreation = false;
 
1061
            }
 
1062
 
 
1063
            sharedState->allCreatedObjects.push(instance);
1245
1064
        } else {
1246
 
            Q_ASSERT(typeRef.component);
1247
 
            if (typeRef.component->qmlUnit->isSingleton())
 
1065
            Q_ASSERT(typeRef->component);
 
1066
            Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->name,
 
1067
                    context->url, obj->location.line, obj->location.column));
 
1068
            if (typeRef->component->qmlUnit->isSingleton())
1248
1069
            {
1249
1070
                recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
1250
1071
                return 0;
1251
1072
            }
1252
 
            QmlObjectCreator subCreator(context, typeRef.component);
 
1073
 
 
1074
            QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data());
1253
1075
            instance = subCreator.create();
1254
1076
            if (!instance) {
1255
1077
                errors += subCreator.errors;
1256
1078
                return 0;
1257
1079
            }
1258
 
            if (subCreator.componentAttached)
1259
 
                subCreator.componentAttached->add(&componentAttached);
1260
 
            allCreatedBindings << subCreator.allCreatedBindings;
1261
1080
        }
1262
 
        // ### use no-event variant
1263
1081
        if (parent)
1264
 
            instance->setParent(parent);
 
1082
            QQml_setParent_noEvent(instance, parent);
 
1083
 
 
1084
        ddata = QQmlData::get(instance, /*create*/true);
 
1085
        ddata->lineNumber = obj->location.line;
 
1086
        ddata->columnNumber = obj->location.column;
1265
1087
    }
1266
1088
 
1267
 
    QQmlData *ddata = QQmlData::get(instance, /*create*/true);
1268
 
    if (static_cast<quint32>(index) == qmlUnit->indexOfRootObject) {
 
1089
    ddata->setImplicitDestructible();
 
1090
    if (static_cast<quint32>(index) == qmlUnit->indexOfRootObject || ddata->rootObjectInCreation) {
1269
1091
        if (ddata->context) {
1270
1092
            Q_ASSERT(ddata->context != context);
1271
1093
            Q_ASSERT(ddata->outerContext);
1281
1103
 
1282
1104
    ddata->outerContext = context;
1283
1105
 
 
1106
    if (parserStatus) {
 
1107
        parserStatus->classBegin();
 
1108
        // push() the profiler state here, together with the parserStatus, as we'll pop() them
 
1109
        // together, too.
 
1110
        Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(profiler));
 
1111
        sharedState->allParserStatusCallbacks.push(parserStatus);
 
1112
        parserStatus->d = &sharedState->allParserStatusCallbacks.top();
 
1113
    }
 
1114
 
1284
1115
    QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index);
1285
1116
    if (idEntry != objectIndexToId.constEnd())
1286
1117
        context->setIdProperty(idEntry.value(), instance);
1287
1118
 
1288
 
    if (!isComponent) {
1289
 
        QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index);
1290
 
        Q_ASSERT(!cache.isNull());
1291
 
 
1292
 
        if (!populateInstance(index, instance, cache, instance, /*value type property*/0))
1293
 
            return 0;
1294
 
    }
1295
 
 
1296
 
    return instance;
 
1119
    // Register the context object in the context early on in order for pending binding
 
1120
    // initialization to find it available.
 
1121
    if (isContextObject)
 
1122
        context->contextObject = instance;
 
1123
 
 
1124
    QBitArray bindingsToSkip;
 
1125
    if (customParser) {
 
1126
        QHash<int, QQmlCompiledData::CustomParserData>::ConstIterator entry = compiledData->customParserData.find(index);
 
1127
        if (entry != compiledData->customParserData.constEnd()) {
 
1128
            customParser->setCustomData(instance, entry->compilationArtifact, compiledData);
 
1129
            bindingsToSkip = entry->bindings;
 
1130
        }
 
1131
    }
 
1132
 
 
1133
    if (isComponent)
 
1134
        return instance;
 
1135
 
 
1136
    QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index);
 
1137
    Q_ASSERT(!cache.isNull());
 
1138
    if (installPropertyCache) {
 
1139
        if (ddata->propertyCache)
 
1140
            ddata->propertyCache->release();;
 
1141
        ddata->propertyCache = cache;
 
1142
        ddata->propertyCache->addref();
 
1143
    }
 
1144
 
 
1145
    QObject *scopeObject = instance;
 
1146
    qSwap(_scopeObject, scopeObject);
 
1147
 
 
1148
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
 
1149
    QV4::Scope valueScope(v4);
 
1150
    QV4::ScopedValue scopeObjectProtector(valueScope, ddata ? ddata->jsWrapper.value() : 0);
 
1151
    Q_UNUSED(scopeObjectProtector);
 
1152
    QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
 
1153
    QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
 
1154
    QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
 
1155
 
 
1156
    qSwap(_qmlContext, qmlContext);
 
1157
 
 
1158
    bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip);
 
1159
 
 
1160
    qSwap(_qmlContext, qmlContext);
 
1161
    qSwap(_scopeObject, scopeObject);
 
1162
 
 
1163
    return result ? instance : 0;
1297
1164
}
1298
1165
 
1299
 
void QmlObjectCreator::finalize()
 
1166
QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1300
1167
{
 
1168
    Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
 
1169
    phase = Finalizing;
 
1170
 
 
1171
    QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data());
 
1172
    ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
 
1173
 
1301
1174
    {
1302
1175
    QQmlTrace trace("VME Binding Enable");
1303
1176
    trace.event("begin binding eval");
1304
1177
 
1305
 
    Q_ASSERT(allCreatedBindings.isEmpty() || allCreatedBindings.isDetached());
1306
 
 
1307
 
    for (QLinkedList<QVector<QQmlAbstractBinding*> >::Iterator it = allCreatedBindings.begin(), end = allCreatedBindings.end();
1308
 
         it != end; ++it) {
1309
 
        const QVector<QQmlAbstractBinding *> &bindings = *it;
1310
 
        for (int i = 0; i < bindings.count(); ++i) {
1311
 
            QQmlAbstractBinding *b = bindings.at(i);
1312
 
            if (!b)
1313
 
                continue;
1314
 
            b->m_mePtr = 0;
1315
 
            QQmlData *data = QQmlData::get(b->object());
1316
 
            Q_ASSERT(data);
1317
 
            data->clearPendingBindingBit(b->propertyIndex());
1318
 
            b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
1319
 
                          QQmlPropertyPrivate::DontRemoveBinding);
1320
 
        }
1321
 
    }
 
1178
    while (!sharedState->allCreatedBindings.isEmpty()) {
 
1179
        QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
 
1180
        if (!b)
 
1181
            continue;
 
1182
        b->m_mePtr = 0;
 
1183
        QQmlData *data = QQmlData::get(b->object());
 
1184
        Q_ASSERT(data);
 
1185
        data->clearPendingBindingBit(b->propertyIndex());
 
1186
        b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
 
1187
                      QQmlPropertyPrivate::DontRemoveBinding);
 
1188
 
 
1189
        if (watcher.hasRecursed() || interrupt.shouldInterrupt())
 
1190
            return 0;
 
1191
    }
 
1192
    }
 
1193
 
 
1194
    if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
 
1195
        QQmlTrace trace("VME Component Complete");
 
1196
        while (!sharedState->allParserStatusCallbacks.isEmpty()) {
 
1197
            QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
 
1198
            QQmlParserStatus *status = sharedState->allParserStatusCallbacks.pop();
 
1199
 
 
1200
            if (status && status->d) {
 
1201
                status->d = 0;
 
1202
                status->componentComplete();
 
1203
            }
 
1204
 
 
1205
            if (watcher.hasRecursed() || interrupt.shouldInterrupt())
 
1206
                return 0;
 
1207
        }
 
1208
    }
 
1209
 
 
1210
    {
 
1211
    QQmlTrace trace("VME Finalize Callbacks");
 
1212
    for (int ii = 0; ii < sharedState->finalizeCallbacks.count(); ++ii) {
 
1213
        QQmlEnginePrivate::FinalizeCallback callback = sharedState->finalizeCallbacks.at(ii);
 
1214
        QObject *obj = callback.first;
 
1215
        if (obj) {
 
1216
            void *args[] = { 0 };
 
1217
            QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
 
1218
        }
 
1219
        if (watcher.hasRecursed())
 
1220
            return 0;
 
1221
    }
 
1222
    sharedState->finalizeCallbacks.clear();
1322
1223
    }
1323
1224
 
1324
1225
    {
1325
1226
    QQmlTrace trace("VME Component.onCompleted Callbacks");
1326
 
    while (componentAttached) {
1327
 
        QQmlComponentAttached *a = componentAttached;
 
1227
    while (sharedState->componentAttached) {
 
1228
        QQmlComponentAttached *a = sharedState->componentAttached;
1328
1229
        a->rem();
1329
1230
        QQmlData *d = QQmlData::get(a->parent());
1330
1231
        Q_ASSERT(d);
1331
1232
        Q_ASSERT(d->context);
1332
1233
        a->add(&d->context->componentAttached);
1333
 
        // ### designer if (componentCompleteEnabled())
 
1234
        if (QQmlVME::componentCompleteEnabled())
1334
1235
            emit a->completed();
1335
1236
 
1336
 
#if 0 // ###
1337
1237
        if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1338
1238
            return 0;
1339
 
#endif
1340
 
    }
1341
 
    }
1342
 
}
1343
 
 
1344
 
bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache,
1345
 
                                        QObject *scopeObjectForBindings, QQmlPropertyData *valueTypeProperty)
 
1239
    }
 
1240
    }
 
1241
 
 
1242
    phase = Done;
 
1243
 
 
1244
    return sharedState->rootContext;
 
1245
}
 
1246
 
 
1247
void QQmlObjectCreator::clear()
 
1248
{
 
1249
    if (phase == Done || phase == Finalizing || phase == Startup)
 
1250
        return;
 
1251
    Q_ASSERT(phase != Startup);
 
1252
 
 
1253
    while (!sharedState->allCreatedObjects.isEmpty())
 
1254
        delete sharedState->allCreatedObjects.pop();
 
1255
 
 
1256
    phase = Done;
 
1257
}
 
1258
 
 
1259
bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
1346
1260
{
1347
1261
    const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
1348
1262
 
1349
 
    Q_ASSERT(scopeObjectForBindings);
1350
 
 
1351
1263
    QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
1352
1264
 
1353
 
    qSwap(_propertyCache, cache);
1354
1265
    qSwap(_qobject, instance);
1355
 
    qSwap(_qobjectForBindings, scopeObjectForBindings);
1356
1266
    qSwap(_valueTypeProperty, valueTypeProperty);
1357
1267
    qSwap(_compiledObject, obj);
1358
1268
    qSwap(_ddata, declarativeData);
 
1269
    qSwap(_bindingTarget, bindingTarget);
 
1270
 
 
1271
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
 
1272
    QV4::Scope valueScope(v4);
 
1273
    QV4::ScopedValue scopeObjectProtector(valueScope);
 
1274
 
 
1275
    QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index);
1359
1276
 
1360
1277
    QQmlVMEMetaObject *vmeMetaObject = 0;
1361
1278
    const QByteArray data = vmeMetaObjectData.value(index);
1362
1279
    if (!data.isEmpty()) {
 
1280
        Q_ASSERT(!cache.isNull());
1363
1281
        // install on _object
1364
 
        vmeMetaObject = new QQmlVMEMetaObject(_qobjectForBindings, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
 
1282
        vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
1365
1283
        if (_ddata->propertyCache)
1366
1284
            _ddata->propertyCache->release();
1367
 
        _ddata->propertyCache = _propertyCache;
 
1285
        _ddata->propertyCache = cache;
1368
1286
        _ddata->propertyCache->addref();
 
1287
        scopeObjectProtector = _ddata->jsWrapper.value();
1369
1288
    } else {
1370
 
        vmeMetaObject = QQmlVMEMetaObject::get(_qobjectForBindings);
 
1289
        vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
1371
1290
    }
1372
 
 
1373
 
    _ddata->lineNumber = _compiledObject->location.line;
1374
 
    _ddata->columnNumber = _compiledObject->location.column;
1375
 
 
 
1291
    qSwap(_propertyCache, cache);
1376
1292
    qSwap(_vmeMetaObject, vmeMetaObject);
1377
1293
 
1378
 
    QVector<QQmlAbstractBinding*> createdBindings(_compiledObject->nBindings, 0);
1379
 
    qSwap(_createdBindings, createdBindings);
1380
 
 
1381
 
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
1382
 
    QV4::Scope valueScope(v4);
1383
 
    QV4::ScopedObject scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _qobjectForBindings));
1384
 
    QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject));
1385
 
    QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
1386
 
 
1387
 
    qSwap(_qmlContext, qmlContext);
1388
 
 
1389
 
    setupBindings();
 
1294
    QBitArray bindingSkipList = bindingsToSkip;
 
1295
    {
 
1296
        QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(index);
 
1297
        if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
 
1298
            if (bindingSkipList.isEmpty())
 
1299
                bindingSkipList.resize(deferredBindings->count());
 
1300
 
 
1301
            for (int i = 0; i < deferredBindings->count(); ++i)
 
1302
                if (deferredBindings->testBit(i))
 
1303
                    bindingSkipList.setBit(i);
 
1304
            QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
 
1305
            deferData->deferredIdx = index;
 
1306
            deferData->compiledData = compiledData;
 
1307
            deferData->compiledData->addref();
 
1308
            deferData->context = context;
 
1309
            _ddata->deferredData = deferData;
 
1310
        }
 
1311
    }
 
1312
 
1390
1313
    setupFunctions();
1391
 
 
1392
 
    allCreatedBindings.append(_createdBindings);
1393
 
 
1394
 
    qSwap(_qmlContext, qmlContext);
1395
 
 
1396
 
    qSwap(_createdBindings, createdBindings);
 
1314
    setupBindings(bindingSkipList);
 
1315
 
1397
1316
    qSwap(_vmeMetaObject, vmeMetaObject);
1398
 
    qSwap(_propertyCache, cache);
 
1317
    qSwap(_bindingTarget, bindingTarget);
1399
1318
    qSwap(_ddata, declarativeData);
1400
1319
    qSwap(_compiledObject, obj);
1401
1320
    qSwap(_valueTypeProperty, valueTypeProperty);
1402
 
    qSwap(_qobjectForBindings, scopeObjectForBindings);
1403
1321
    qSwap(_qobject, instance);
1404
 
 
1405
 
    return errors.isEmpty();
1406
 
}
1407
 
 
1408
 
 
1409
 
QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
1410
 
                                                               const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
1411
 
                                                               const QList<QQmlPropertyCache *> &propertyCaches, QList<QByteArray> *vmeMetaObjectData,
1412
 
                                                               QHash<int, int> *objectIndexToIdForRoot,
1413
 
                                                               QHash<int, QHash<int, int> > *objectIndexToIdPerComponent)
1414
 
    : QQmlCompilePass(url, qmlUnit)
1415
 
    , _componentIndex(-1)
1416
 
    , _objectIndexToIdInScope(0)
1417
 
    , resolvedTypes(resolvedTypes)
1418
 
    , propertyCaches(propertyCaches)
1419
 
    , vmeMetaObjectData(vmeMetaObjectData)
1420
 
    , objectIndexToIdForRoot(objectIndexToIdForRoot)
1421
 
    , objectIndexToIdPerComponent(objectIndexToIdPerComponent)
1422
 
{
1423
 
}
1424
 
 
1425
 
bool QQmlComponentAndAliasResolver::resolve()
1426
 
{
1427
 
    Q_ASSERT(componentRoots.isEmpty());
1428
 
 
1429
 
    // Find objects that are Components. This is missing an extra pass
1430
 
    // that finds implicitly defined components, i.e.
1431
 
    //    someProperty: Item { ... }
1432
 
    // when someProperty _is_ a QQmlComponent. In that case the Item {}
1433
 
    // should be implicitly surrounded by Component {}
1434
 
 
1435
 
    for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
1436
 
        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
1437
 
        if (stringAt(obj->inheritedTypeNameIndex).isEmpty())
1438
 
            continue;
1439
 
 
1440
 
        QQmlCompiledData::TypeReference tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
1441
 
        if (!tref.type)
1442
 
            continue;
1443
 
        if (tref.type->metaObject() != &QQmlComponent::staticMetaObject)
1444
 
            continue;
1445
 
 
1446
 
        componentRoots.append(i);
1447
 
        // Sanity checks: There can be only an (optional) id property and
1448
 
        // a default property, that defines the component tree.
1449
 
    }
1450
 
 
1451
 
    std::sort(componentRoots.begin(), componentRoots.end());
1452
 
 
1453
 
    // For each component's tree, remember to which component the children
1454
 
    // belong to
1455
 
    for (int i = 0; i < componentRoots.count(); ++i) {
1456
 
        const QV4::CompiledData::Object *component = qmlUnit->objectAt(componentRoots.at(i));
1457
 
 
1458
 
        if (component->nFunctions > 0)
1459
 
            COMPILE_EXCEPTION(component, tr("Component objects cannot declare new functions."));
1460
 
        if (component->nProperties > 0)
1461
 
            COMPILE_EXCEPTION(component, tr("Component objects cannot declare new properties."));
1462
 
        if (component->nSignals > 0)
1463
 
            COMPILE_EXCEPTION(component, tr("Component objects cannot declare new signals."));
1464
 
 
1465
 
        if (component->nBindings == 0)
1466
 
            COMPILE_EXCEPTION(component, tr("Cannot create empty component specification"));
1467
 
 
1468
 
        const QV4::CompiledData::Binding *rootBinding = component->bindingTable();
1469
 
        if (component->nBindings > 1 || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
1470
 
            COMPILE_EXCEPTION(rootBinding, tr("Component elements may not contain properties other than id"));
1471
 
 
1472
 
        _componentIndex = i;
1473
 
        _idToObjectIndex.clear();
1474
 
 
1475
 
        _objectIndexToIdInScope = &(*objectIndexToIdPerComponent)[componentRoots.at(i)];
1476
 
 
1477
 
        _objectsWithAliases.clear();
1478
 
 
1479
 
        if (!collectIdsAndAliases(rootBinding->value.objectIndex))
1480
 
            return false;
1481
 
 
1482
 
        if (!resolveAliases())
1483
 
            return false;
1484
 
    }
1485
 
 
1486
 
    // Collect ids and aliases for root
1487
 
    _componentIndex = -1;
1488
 
    _idToObjectIndex.clear();
1489
 
    _objectIndexToIdInScope = objectIndexToIdForRoot;
1490
 
    _objectsWithAliases.clear();
1491
 
 
1492
 
    collectIdsAndAliases(qmlUnit->indexOfRootObject);
1493
 
 
1494
 
    resolveAliases();
1495
 
 
1496
 
    return errors.isEmpty();
1497
 
}
1498
 
 
1499
 
bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
1500
 
{
1501
 
    const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
1502
 
 
1503
 
    // Only include creatable types. Everything else is synthetic, such as group property
1504
 
    // objects.
1505
 
    if (_componentIndex != -1 && !stringAt(obj->inheritedTypeNameIndex).isEmpty())
1506
 
        objectIndexToComponentIndex.insert(objectIndex, _componentIndex);
1507
 
 
1508
 
    QString id = stringAt(obj->idIndex);
1509
 
    if (!id.isEmpty()) {
1510
 
        if (_idToObjectIndex.contains(obj->idIndex)) {
1511
 
            recordError(obj->locationOfIdProperty, tr("id is not unique"));
1512
 
            return false;
1513
 
        }
1514
 
        _idToObjectIndex.insert(obj->idIndex, objectIndex);
1515
 
        _objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
1516
 
    }
1517
 
 
1518
 
    const QV4::CompiledData::Property *property = obj->propertyTable();
1519
 
    for (quint32 i = 0; i < obj->nProperties; ++i, ++property)
1520
 
        if (property->type == QV4::CompiledData::Property::Alias) {
1521
 
            _objectsWithAliases.append(objectIndex);
1522
 
            break;
1523
 
        }
1524
 
 
1525
 
    const QV4::CompiledData::Binding *binding = obj->bindingTable();
1526
 
    for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1527
 
        if (binding->type != QV4::CompiledData::Binding::Type_Object
1528
 
            && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
1529
 
            && binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
1530
 
            continue;
1531
 
 
1532
 
        // Stop at Component boundary
1533
 
        if (std::binary_search(componentRoots.constBegin(), componentRoots.constEnd(), binding->value.objectIndex))
1534
 
            continue;
1535
 
 
1536
 
        if (!collectIdsAndAliases(binding->value.objectIndex))
1537
 
            return false;
1538
 
    }
1539
 
 
1540
 
    return true;
1541
 
}
1542
 
 
1543
 
bool QQmlComponentAndAliasResolver::resolveAliases()
1544
 
{
1545
 
    foreach (int objectIndex, _objectsWithAliases) {
1546
 
        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
1547
 
 
1548
 
        QQmlPropertyCache *propertyCache = propertyCaches.value(objectIndex);
1549
 
        Q_ASSERT(propertyCache);
1550
 
 
1551
 
        int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
1552
 
        int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
1553
 
        int effectiveAliasIndex = 0;
1554
 
 
1555
 
        const QV4::CompiledData::Property *p = obj->propertyTable();
1556
 
        for (quint32 propertyIndex = 0; propertyIndex < obj->nProperties; ++propertyIndex, ++p) {
1557
 
            if (p->type != QV4::CompiledData::Property::Alias)
1558
 
                continue;
1559
 
 
1560
 
            const int idIndex = p->aliasIdValueIndex;
1561
 
            const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
1562
 
            if (targetObjectIndex == -1) {
1563
 
                recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
1564
 
                return false;
1565
 
            }
1566
 
            const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
1567
 
            Q_ASSERT(targetId != -1);
1568
 
 
1569
 
            const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
1570
 
 
1571
 
            QStringRef property;
1572
 
            QStringRef subProperty;
1573
 
 
1574
 
            const int propertySeparator = aliasPropertyValue.indexOf(QLatin1Char('.'));
1575
 
            if (propertySeparator != -1) {
1576
 
                property = aliasPropertyValue.leftRef(propertySeparator);
1577
 
                subProperty = aliasPropertyValue.midRef(propertySeparator + 1);
1578
 
            } else
1579
 
                property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
1580
 
 
1581
 
            int propIdx = -1;
1582
 
            int propType = 0;
1583
 
            int notifySignal = -1;
1584
 
            int flags = 0;
1585
 
            int type = 0;
1586
 
            bool writable = false;
1587
 
            bool resettable = false;
1588
 
 
1589
 
            quint32 propertyFlags = QQmlPropertyData::IsAlias;
1590
 
 
1591
 
            if (property.isEmpty()) {
1592
 
                const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(targetObjectIndex);
1593
 
                QQmlCompiledData::TypeReference typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex);
1594
 
 
1595
 
                if (typeRef.type)
1596
 
                    type = typeRef.type->typeId();
1597
 
                else
1598
 
                    type = typeRef.component->metaTypeId;
1599
 
 
1600
 
                flags |= QML_ALIAS_FLAG_PTR;
1601
 
                propertyFlags |= QQmlPropertyData::IsQObjectDerived;
1602
 
            } else {
1603
 
                QQmlPropertyCache *targetCache = propertyCaches.value(targetObjectIndex);
1604
 
                Q_ASSERT(targetCache);
1605
 
                QtQml::PropertyResolver resolver(targetCache);
1606
 
 
1607
 
                QQmlPropertyData *targetProperty = resolver.property(property.toString());
1608
 
                if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
1609
 
                    recordError(p->aliasLocation, tr("Invalid alias location"));
1610
 
                    return false;
1611
 
                }
1612
 
 
1613
 
                propIdx = targetProperty->coreIndex;
1614
 
                type = targetProperty->propType;
1615
 
 
1616
 
                writable = targetProperty->isWritable();
1617
 
                resettable = targetProperty->isResettable();
1618
 
                notifySignal = targetProperty->notifyIndex;
1619
 
 
1620
 
                if (!subProperty.isEmpty()) {
1621
 
                    QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
1622
 
                    if (!valueType) {
1623
 
                        recordError(p->aliasLocation, tr("Invalid alias location"));
1624
 
                        return false;
1625
 
                    }
1626
 
 
1627
 
                    propType = type;
1628
 
 
1629
 
                    int valueTypeIndex =
1630
 
                        valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
1631
 
                    if (valueTypeIndex == -1) {
1632
 
                        recordError(p->aliasLocation, tr("Invalid alias location"));
1633
 
                        return false;
1634
 
                    }
1635
 
                    Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
1636
 
 
1637
 
                    propIdx |= (valueTypeIndex << 16);
1638
 
                    if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
1639
 
                        type = QVariant::Int;
1640
 
                    else
1641
 
                        type = valueType->metaObject()->property(valueTypeIndex).userType();
1642
 
 
1643
 
                } else {
1644
 
                    if (targetProperty->isEnum()) {
1645
 
                        type = QVariant::Int;
1646
 
                    } else {
1647
 
                        // Copy type flags
1648
 
                        propertyFlags |= targetProperty->getFlags() & QQmlPropertyData::PropTypeFlagMask;
1649
 
 
1650
 
                        if (targetProperty->isVarProperty())
1651
 
                            propertyFlags |= QQmlPropertyData::IsQVariant;
1652
 
 
1653
 
                        if (targetProperty->isQObject())
1654
 
                            flags |= QML_ALIAS_FLAG_PTR;
1655
 
                    }
1656
 
                }
1657
 
            }
1658
 
 
1659
 
            QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal };
1660
 
 
1661
 
            typedef QQmlVMEMetaData VMD;
1662
 
            QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex];
1663
 
            Q_ASSERT(!dynamicData.isEmpty());
1664
 
            VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
1665
 
            *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
1666
 
 
1667
 
            Q_ASSERT(dynamicData.isDetached());
1668
 
 
1669
 
            if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
1670
 
                propertyFlags |= QQmlPropertyData::IsWritable;
1671
 
            else
1672
 
                propertyFlags &= ~QQmlPropertyData::IsWritable;
1673
 
 
1674
 
            if (resettable)
1675
 
                propertyFlags |= QQmlPropertyData::IsResettable;
1676
 
            else
1677
 
                propertyFlags &= ~QQmlPropertyData::IsResettable;
1678
 
 
1679
 
            QString propertyName = stringAt(p->nameIndex);
1680
 
            if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
1681
 
            propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
1682
 
                                          type, effectiveSignalIndex++);
1683
 
 
1684
 
        }
1685
 
    }
1686
 
    return true;
1687
 
}
1688
 
 
1689
 
 
1690
 
QQmlPropertyValidator::QQmlPropertyValidator(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
1691
 
                                             const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
1692
 
                                             const QList<QQmlPropertyCache *> &propertyCaches, const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent)
1693
 
    : QQmlCompilePass(url, qmlUnit)
1694
 
    , resolvedTypes(resolvedTypes)
1695
 
    , propertyCaches(propertyCaches)
1696
 
    , objectIndexToIdPerComponent(objectIndexToIdPerComponent)
1697
 
{
1698
 
}
1699
 
 
1700
 
bool QQmlPropertyValidator::validate()
1701
 
{
1702
 
    for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
1703
 
        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
1704
 
        if (stringAt(obj->inheritedTypeNameIndex).isEmpty())
1705
 
            continue;
1706
 
 
1707
 
        if (isComponent(i))
1708
 
            continue;
1709
 
 
1710
 
        QQmlPropertyCache *propertyCache = propertyCaches.value(i);
1711
 
        Q_ASSERT(propertyCache);
1712
 
 
1713
 
        if (!validateObject(obj, i, propertyCache))
1714
 
            return false;
1715
 
    }
1716
 
    return true;
1717
 
}
1718
 
 
1719
 
bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache)
1720
 
{
1721
 
    PropertyResolver propertyResolver(propertyCache);
1722
 
 
1723
 
    QQmlPropertyData *defaultProperty = propertyCache->defaultProperty();
1724
 
 
1725
 
    const QV4::CompiledData::Binding *binding = obj->bindingTable();
1726
 
    for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1727
 
        if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty
1728
 
            || binding->type == QV4::CompiledData::Binding::Type_GroupProperty)
1729
 
            continue;
1730
 
 
1731
 
        const QString name = stringAt(binding->propertyNameIndex);
1732
 
 
1733
 
        bool bindingToDefaultProperty = false;
1734
 
 
1735
 
        bool notInRevision = false;
1736
 
        QQmlPropertyData *pd = 0;
1737
 
        if (!name.isEmpty()) {
1738
 
            pd = propertyResolver.property(name, &notInRevision);
1739
 
 
1740
 
            if (notInRevision) {
1741
 
                QString typeName = stringAt(obj->inheritedTypeNameIndex);
1742
 
                QQmlCompiledData::TypeReference type = resolvedTypes.value(objectIndex);
1743
 
                if (type.type) {
1744
 
                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
1745
 
                } else {
1746
 
                    COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
1747
 
                }
1748
 
            }
1749
 
        } else {
1750
 
           pd = defaultProperty;
1751
 
           bindingToDefaultProperty = true;
1752
 
        }
1753
 
 
1754
 
        if (!pd) {
1755
 
            if (bindingToDefaultProperty) {
1756
 
                COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent default property"));
1757
 
            } else {
1758
 
                COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent property \"%1\"").arg(name));
1759
 
            }
1760
 
        }
1761
 
    }
1762
 
 
1763
 
    return true;
1764
 
}
 
1322
    qSwap(_propertyCache, cache);
 
1323
 
 
1324
    return errors.isEmpty();
 
1325
}
 
1326
 
 
1327