39 ** |
39 ** |
40 ****************************************************************************/ |
40 ****************************************************************************/ |
41 |
41 |
42 #include "private/qdeclarativecompiler_p.h" |
42 #include "private/qdeclarativecompiler_p.h" |
43 |
43 |
44 #include "private/qdeclarativecompositetypedata_p.h" |
|
45 #include "private/qdeclarativeparser_p.h" |
44 #include "private/qdeclarativeparser_p.h" |
46 #include "private/qdeclarativescriptparser_p.h" |
45 #include "private/qdeclarativescriptparser_p.h" |
47 #include "qdeclarativepropertyvaluesource.h" |
46 #include "qdeclarativepropertyvaluesource.h" |
48 #include "qdeclarativecomponent.h" |
47 #include "qdeclarativecomponent.h" |
49 #include "private/qmetaobjectbuilder_p.h" |
48 #include "private/qmetaobjectbuilder_p.h" |
238 bool ok; |
237 bool ok; |
239 QDeclarativeStringConverters::colorFromString(string, &ok); |
238 QDeclarativeStringConverters::colorFromString(string, &ok); |
240 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); |
239 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); |
241 } |
240 } |
242 break; |
241 break; |
243 #ifndef QT_NO_TEXTDATE |
242 #ifndef QT_NO_DATESTRING |
244 case QVariant::Date: |
243 case QVariant::Date: |
245 { |
244 { |
246 bool ok; |
245 bool ok; |
247 QDeclarativeStringConverters::dateFromString(string, &ok); |
246 QDeclarativeStringConverters::dateFromString(string, &ok); |
248 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); |
247 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); |
260 bool ok; |
259 bool ok; |
261 QDeclarativeStringConverters::dateTimeFromString(string, &ok); |
260 QDeclarativeStringConverters::dateTimeFromString(string, &ok); |
262 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); |
261 if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); |
263 } |
262 } |
264 break; |
263 break; |
265 #endif // QT_NO_TEXTDATE |
264 #endif // QT_NO_DATESTRING |
266 case QVariant::Point: |
265 case QVariant::Point: |
267 case QVariant::PointF: |
266 case QVariant::PointF: |
268 { |
267 { |
269 bool ok; |
268 bool ok; |
270 QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); |
269 QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); |
414 instr.type = QDeclarativeInstruction::StoreColor; |
413 instr.type = QDeclarativeInstruction::StoreColor; |
415 instr.storeColor.propertyIndex = prop.propertyIndex(); |
414 instr.storeColor.propertyIndex = prop.propertyIndex(); |
416 instr.storeColor.value = c.rgba(); |
415 instr.storeColor.value = c.rgba(); |
417 } |
416 } |
418 break; |
417 break; |
419 #ifndef QT_NO_TEXTDATE |
418 #ifndef QT_NO_DATESTRING |
420 case QVariant::Date: |
419 case QVariant::Date: |
421 { |
420 { |
422 QDate d = QDeclarativeStringConverters::dateFromString(string); |
421 QDate d = QDeclarativeStringConverters::dateFromString(string); |
423 instr.type = QDeclarativeInstruction::StoreDate; |
422 instr.type = QDeclarativeInstruction::StoreDate; |
424 instr.storeDate.propertyIndex = prop.propertyIndex(); |
423 instr.storeDate.propertyIndex = prop.propertyIndex(); |
560 If the environment variant QML_COMPILER_DUMP is set |
559 If the environment variant QML_COMPILER_DUMP is set |
561 (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr |
560 (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr |
562 on a successful compiler. |
561 on a successful compiler. |
563 */ |
562 */ |
564 bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, |
563 bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, |
565 QDeclarativeCompositeTypeData *unit, |
564 QDeclarativeTypeData *unit, |
566 QDeclarativeCompiledData *out) |
565 QDeclarativeCompiledData *out) |
567 { |
566 { |
568 exceptions.clear(); |
567 exceptions.clear(); |
569 |
568 |
570 Q_ASSERT(out); |
569 Q_ASSERT(out); |
571 reset(out); |
570 reset(out); |
572 |
571 |
573 output = out; |
572 output = out; |
574 |
573 |
575 // Compile types |
574 // Compile types |
576 for (int ii = 0; ii < unit->types.count(); ++ii) { |
575 const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); |
577 QDeclarativeCompositeTypeData::TypeReference &tref = unit->types[ii]; |
576 QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes(); |
|
577 |
|
578 for (int ii = 0; ii < resolvedTypes.count(); ++ii) { |
578 QDeclarativeCompiledData::TypeReference ref; |
579 QDeclarativeCompiledData::TypeReference ref; |
579 QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii); |
580 |
|
581 const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii); |
|
582 QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii); |
|
583 |
580 if (tref.type) { |
584 if (tref.type) { |
581 ref.type = tref.type; |
585 ref.type = tref.type; |
582 if (!ref.type->isCreatable()) { |
586 if (!ref.type->isCreatable()) { |
583 QString err = ref.type->noCreationReason(); |
587 QString err = ref.type->noCreationReason(); |
584 if (err.isEmpty()) |
588 if (err.isEmpty()) |
585 err = tr( "Element is not creatable."); |
589 err = tr( "Element is not creatable."); |
586 COMPILE_EXCEPTION(parserRef->refObjects.first(), err); |
590 COMPILE_EXCEPTION(parserRef->refObjects.first(), err); |
587 } |
591 } |
588 } else if (tref.unit) { |
592 } else if (tref.typeData) { |
589 ref.component = tref.unit->toComponent(engine); |
593 ref.component = tref.typeData->component(); |
590 |
594 ref.ref = tref.typeData; |
591 if (ref.component->isError()) { |
|
592 QDeclarativeError error; |
|
593 error.setUrl(output->url); |
|
594 error.setDescription(QLatin1String("Unable to create type ") + |
|
595 parserRef->name); |
|
596 if (!parserRef->refObjects.isEmpty()) { |
|
597 QDeclarativeParser::Object *parserObject = parserRef->refObjects.first(); |
|
598 error.setLine(parserObject->location.start.line); |
|
599 error.setColumn(parserObject->location.start.column); |
|
600 } |
|
601 |
|
602 exceptions << error; |
|
603 exceptions << ref.component->errors(); |
|
604 reset(out); |
|
605 return false; |
|
606 } |
|
607 ref.ref = tref.unit; |
|
608 ref.ref->addref(); |
595 ref.ref->addref(); |
609 } |
596 } |
610 ref.className = parserRef->name.toUtf8(); |
597 ref.className = parserRef->name.toUtf8(); |
611 out->types << ref; |
598 out->types << ref; |
612 } |
599 } |
613 |
600 |
614 Object *root = unit->data.tree(); |
601 Object *root = unit->parser().tree(); |
615 Q_ASSERT(root); |
602 Q_ASSERT(root); |
616 |
603 |
617 this->engine = engine; |
604 this->engine = engine; |
618 this->enginePrivate = QDeclarativeEnginePrivate::get(engine); |
605 this->enginePrivate = QDeclarativeEnginePrivate::get(engine); |
619 this->unit = unit; |
606 this->unit = unit; |
662 |
649 |
663 // Build global import scripts |
650 // Build global import scripts |
664 QHash<QString, Object::ScriptBlock> importedScripts; |
651 QHash<QString, Object::ScriptBlock> importedScripts; |
665 QStringList importedScriptIndexes; |
652 QStringList importedScriptIndexes; |
666 |
653 |
667 for (int ii = 0; ii < unit->scripts.count(); ++ii) { |
654 foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) { |
668 QString scriptCode = QString::fromUtf8(unit->scripts.at(ii).resource->data); |
655 QString scriptCode = script.script->scriptSource(); |
669 Object::ScriptBlock::Pragmas pragmas = QDeclarativeScriptParser::extractPragmas(scriptCode); |
656 Object::ScriptBlock::Pragmas pragmas = script.script->pragmas(); |
|
657 |
|
658 Q_ASSERT(!importedScripts.contains(script.qualifier)); |
670 |
659 |
671 if (!scriptCode.isEmpty()) { |
660 if (!scriptCode.isEmpty()) { |
672 Object::ScriptBlock &scriptBlock = importedScripts[unit->scripts.at(ii).qualifier]; |
661 Object::ScriptBlock &scriptBlock = importedScripts[script.qualifier]; |
673 |
662 |
674 scriptBlock.codes.append(scriptCode); |
663 scriptBlock.code = scriptCode; |
675 scriptBlock.lineNumbers.append(1); |
664 scriptBlock.file = script.script->finalUrl().toString(); |
676 scriptBlock.files.append(unit->scripts.at(ii).resource->url); |
665 scriptBlock.pragmas = pragmas; |
677 scriptBlock.pragmas.append(pragmas); |
|
678 } |
666 } |
679 } |
667 } |
680 |
668 |
681 for (QHash<QString, Object::ScriptBlock>::Iterator iter = importedScripts.begin(); |
669 for (QHash<QString, Object::ScriptBlock>::Iterator iter = importedScripts.begin(); |
682 iter != importedScripts.end(); ++iter) { |
670 iter != importedScripts.end(); ++iter) { |
701 output->importCache = new QDeclarativeTypeNameCache(engine); |
689 output->importCache = new QDeclarativeTypeNameCache(engine); |
702 |
690 |
703 for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) |
691 for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) |
704 output->importCache->add(importedScriptIndexes.at(ii), ii); |
692 output->importCache->add(importedScriptIndexes.at(ii), ii); |
705 |
693 |
706 unit->imports.cache(output->importCache, engine); |
694 unit->imports().populateCache(output->importCache, engine); |
707 |
695 |
708 Q_ASSERT(tree->metatype); |
696 Q_ASSERT(tree->metatype); |
709 |
697 |
710 if (tree->metadata.isEmpty()) { |
698 if (tree->metadata.isEmpty()) { |
711 output->root = tree->metatype; |
699 output->root = tree->metatype; |
984 id.setId.index = obj->idIndex; |
972 id.setId.index = obj->idIndex; |
985 output->bytecode << id; |
973 output->bytecode << id; |
986 } |
974 } |
987 |
975 |
988 // Begin the class |
976 // Begin the class |
989 if (obj->parserStatusCast != -1) { |
977 if (tr.type && obj->parserStatusCast != -1) { |
990 QDeclarativeInstruction begin; |
978 QDeclarativeInstruction begin; |
991 begin.type = QDeclarativeInstruction::BeginObject; |
979 begin.type = QDeclarativeInstruction::BeginObject; |
992 begin.begin.castValue = obj->parserStatusCast; |
980 begin.begin.castValue = obj->parserStatusCast; |
993 begin.line = obj->location.start.line; |
981 begin.line = obj->location.start.line; |
994 output->bytecode << begin; |
982 output->bytecode << begin; |
1400 COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); |
1389 COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); |
1401 } |
1390 } |
1402 |
1391 |
1403 QDeclarativeType *type = 0; |
1392 QDeclarativeType *type = 0; |
1404 QDeclarativeImportedNamespace *typeNamespace = 0; |
1393 QDeclarativeImportedNamespace *typeNamespace = 0; |
1405 enginePrivate->importDatabase.resolveType(unit->imports, prop->name, |
1394 unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); |
1406 &type, 0, 0, 0, &typeNamespace); |
|
1407 |
1395 |
1408 if (typeNamespace) { |
1396 if (typeNamespace) { |
1409 // ### We might need to indicate that this property is a namespace |
1397 // ### We might need to indicate that this property is a namespace |
1410 // for the DOM API |
1398 // for the DOM API |
1411 COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, |
1399 COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, |
1509 COMPILE_EXCEPTION(prop, tr("Not an attached property name")); |
1502 COMPILE_EXCEPTION(prop, tr("Not an attached property name")); |
1510 |
1503 |
1511 // Setup attached property data |
1504 // Setup attached property data |
1512 |
1505 |
1513 QDeclarativeType *type = 0; |
1506 QDeclarativeType *type = 0; |
1514 enginePrivate->importDatabase.resolveTypeInNamespace(ns, prop->name, &type, 0, 0, 0); |
1507 unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0); |
1515 |
1508 |
1516 if (!type || !type->attachedPropertiesType()) |
1509 if (!type || !type->attachedPropertiesType()) |
1517 COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); |
1510 COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); |
1518 |
1511 |
1519 if (!prop->value) |
1512 if (!prop->value) |
1769 { |
1762 { |
1770 Q_ASSERT(prop->type != 0); |
1763 Q_ASSERT(prop->type != 0); |
1771 Q_ASSERT(prop->index != -1); |
1764 Q_ASSERT(prop->index != -1); |
1772 |
1765 |
1773 if (QDeclarativeValueTypeFactory::isValueType(prop->type)) { |
1766 if (QDeclarativeValueTypeFactory::isValueType(prop->type)) { |
1774 QDeclarativeEnginePrivate *ep = |
1767 if (prop->type >= 0 /* QVariant == -1 */ && enginePrivate->valueTypes[prop->type]) { |
1775 static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine)); |
|
1776 if (prop->type >= 0 /* QVariant == -1 */ && ep->valueTypes[prop->type]) { |
|
1777 |
1768 |
1778 if (prop->values.count()) { |
1769 if (prop->values.count()) { |
1779 if (prop->values.at(0)->location < prop->value->location) { |
1770 if (prop->values.at(0)->location < prop->value->location) { |
1780 COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value")); |
1771 COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value")); |
1781 } else { |
1772 } else { |
1785 |
1776 |
1786 if (!obj->metaObject()->property(prop->index).isWritable()) { |
1777 if (!obj->metaObject()->property(prop->index).isWritable()) { |
1787 COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); |
1778 COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); |
1788 } |
1779 } |
1789 |
1780 |
1790 COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], |
1781 COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type], |
1791 prop->value, obj, ctxt.incr())); |
1782 prop->value, obj, ctxt.incr())); |
1792 obj->addValueTypeProperty(prop); |
1783 obj->addValueTypeProperty(prop); |
1793 } else { |
1784 } else { |
1794 COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); |
1785 COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); |
1795 } |
1786 } |
1823 foreach (Property *prop, obj->properties) { |
1814 foreach (Property *prop, obj->properties) { |
1824 int idx = type->metaObject()->indexOfProperty(prop->name.constData()); |
1815 int idx = type->metaObject()->indexOfProperty(prop->name.constData()); |
1825 if (idx == -1) |
1816 if (idx == -1) |
1826 COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); |
1817 COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); |
1827 QMetaProperty p = type->metaObject()->property(idx); |
1818 QMetaProperty p = type->metaObject()->property(idx); |
|
1819 if (!p.isScriptable()) |
|
1820 COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); |
1828 prop->index = idx; |
1821 prop->index = idx; |
1829 prop->type = p.userType(); |
1822 prop->type = p.userType(); |
1830 prop->isValueTypeSubProperty = true; |
1823 prop->isValueTypeSubProperty = true; |
1831 |
1824 |
1832 if (prop->value) |
1825 if (prop->value) |
2136 if (parts.count() != 2) |
2129 if (parts.count() != 2) |
2137 return true; |
2130 return true; |
2138 |
2131 |
2139 QString typeName = parts.at(0); |
2132 QString typeName = parts.at(0); |
2140 QDeclarativeType *type = 0; |
2133 QDeclarativeType *type = 0; |
2141 enginePrivate->importDatabase.resolveType(unit->imports, typeName.toUtf8(), |
2134 unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); |
2142 &type, 0, 0, 0, 0); |
|
2143 |
2135 |
2144 if (!type || obj->typeName != type->qmlTypeName()) |
2136 if (!type || obj->typeName != type->qmlTypeName()) |
2145 return true; |
2137 return true; |
2146 |
2138 |
2147 QString enumValue = parts.at(1); |
2139 QString enumValue = parts.at(1); |
2164 int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const |
2156 int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const |
2165 { |
2157 { |
2166 int dot = script.indexOf('.'); |
2158 int dot = script.indexOf('.'); |
2167 if (dot > 0) { |
2159 if (dot > 0) { |
2168 QDeclarativeType *type = 0; |
2160 QDeclarativeType *type = 0; |
2169 enginePrivate->importDatabase.resolveType(unit->imports, script.left(dot), &type, 0, 0, 0, 0); |
2161 unit->imports().resolveType(script.left(dot), &type, 0, 0, 0, 0); |
2170 if (!type) |
2162 if (!type) |
2171 return -1; |
2163 return -1; |
2172 const QMetaObject *mo = type->metaObject(); |
2164 const QMetaObject *mo = type->metaObject(); |
2173 const char *key = script.constData() + dot+1; |
2165 const char *key = script.constData() + dot+1; |
2174 int i = mo->enumeratorCount(); |
2166 int i = mo->enumeratorCount(); |
2212 } |
2203 } |
2213 |
2204 |
2214 if (propNames.contains(prop.name)) |
2205 if (propNames.contains(prop.name)) |
2215 COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); |
2206 COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); |
2216 |
2207 |
2217 if (QString::fromUtf8(prop.name).at(0).isUpper()) |
2208 QString propName = QString::fromUtf8(prop.name); |
|
2209 if (propName.at(0).isUpper()) |
2218 COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); |
2210 COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); |
2219 |
2211 |
2220 if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(prop.name)) |
2212 if (enginePrivate->globalClass->illegalNames().contains(propName)) |
2221 COMPILE_EXCEPTION(&prop, tr("Illegal property name")); |
2213 COMPILE_EXCEPTION(&prop, tr("Illegal property name")); |
2222 |
2214 |
2223 propNames.insert(prop.name); |
2215 propNames.insert(prop.name); |
2224 } |
2216 } |
2225 |
2217 |
2226 for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { |
2218 for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { |
2227 QByteArray name = obj->dynamicSignals.at(ii).name; |
2219 QByteArray name = obj->dynamicSignals.at(ii).name; |
2228 if (methodNames.contains(name)) |
2220 if (methodNames.contains(name)) |
2229 COMPILE_EXCEPTION(obj, tr("Duplicate signal name")); |
2221 COMPILE_EXCEPTION(obj, tr("Duplicate signal name")); |
2230 if (QString::fromUtf8(name).at(0).isUpper()) |
2222 QString nameStr = QString::fromUtf8(name); |
|
2223 if (nameStr.at(0).isUpper()) |
2231 COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter")); |
2224 COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter")); |
2232 if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name)) |
2225 if (enginePrivate->globalClass->illegalNames().contains(nameStr)) |
2233 COMPILE_EXCEPTION(obj, tr("Illegal signal name")); |
2226 COMPILE_EXCEPTION(obj, tr("Illegal signal name")); |
2234 methodNames.insert(name); |
2227 methodNames.insert(name); |
2235 } |
2228 } |
2236 for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { |
2229 for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { |
2237 QByteArray name = obj->dynamicSlots.at(ii).name; |
2230 QByteArray name = obj->dynamicSlots.at(ii).name; |
2238 if (methodNames.contains(name)) |
2231 if (methodNames.contains(name)) |
2239 COMPILE_EXCEPTION(obj, tr("Duplicate method name")); |
2232 COMPILE_EXCEPTION(obj, tr("Duplicate method name")); |
2240 if (QString::fromUtf8(name).at(0).isUpper()) |
2233 QString nameStr = QString::fromUtf8(name); |
|
2234 if (nameStr.at(0).isUpper()) |
2241 COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter")); |
2235 COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter")); |
2242 if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name)) |
2236 if (enginePrivate->globalClass->illegalNames().contains(nameStr)) |
2243 COMPILE_EXCEPTION(obj, tr("Illegal method name")); |
2237 COMPILE_EXCEPTION(obj, tr("Illegal method name")); |
2244 methodNames.insert(name); |
2238 methodNames.insert(name); |
2245 } |
2239 } |
2246 |
2240 |
2247 return true; |
2241 return true; |
2338 case Object::DynamicProperty::Custom: |
2332 case Object::DynamicProperty::Custom: |
2339 { |
2333 { |
2340 QByteArray customTypeName; |
2334 QByteArray customTypeName; |
2341 QDeclarativeType *qmltype = 0; |
2335 QDeclarativeType *qmltype = 0; |
2342 QUrl url; |
2336 QUrl url; |
2343 if (!enginePrivate->importDatabase.resolveType(unit->imports, p.customType, &qmltype, |
2337 if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0)) |
2344 &url, 0, 0, 0)) |
|
2345 COMPILE_EXCEPTION(&p, tr("Invalid property type")); |
2338 COMPILE_EXCEPTION(&p, tr("Invalid property type")); |
2346 |
2339 |
2347 if (!qmltype) { |
2340 if (!qmltype) { |
2348 QDeclarativeCompositeTypeData *tdata = enginePrivate->typeManager.get(url); |
2341 QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url); |
2349 Q_ASSERT(tdata); |
2342 Q_ASSERT(tdata); |
2350 Q_ASSERT(tdata->status == QDeclarativeCompositeTypeData::Complete); |
2343 Q_ASSERT(tdata->isComplete()); |
2351 |
2344 |
2352 QDeclarativeCompiledData *data = tdata->toCompiledComponent(engine); |
2345 QDeclarativeCompiledData *data = tdata->compiledData(); |
2353 customTypeName = data->root->className(); |
2346 customTypeName = data->root->className(); |
|
2347 data->release(); |
|
2348 tdata->release(); |
2354 } else { |
2349 } else { |
2355 customTypeName = qmltype->typeName(); |
2350 customTypeName = qmltype->typeName(); |
2356 } |
2351 } |
2357 |
2352 |
2358 if (p.type == Object::DynamicProperty::Custom) { |
2353 if (p.type == Object::DynamicProperty::Custom) { |
2414 dynamicData.append((char *)&propertyData, sizeof(propertyData)); |
2409 dynamicData.append((char *)&propertyData, sizeof(propertyData)); |
2415 |
2410 |
2416 builder.addSignal(p.name + "Changed()"); |
2411 builder.addSignal(p.name + "Changed()"); |
2417 QMetaPropertyBuilder propBuilder = |
2412 QMetaPropertyBuilder propBuilder = |
2418 builder.addProperty(p.name, type, builder.methodCount() - 1); |
2413 builder.addProperty(p.name, type, builder.methodCount() - 1); |
2419 propBuilder.setScriptable(true); |
|
2420 propBuilder.setWritable(!readonly); |
2414 propBuilder.setWritable(!readonly); |
2421 } |
2415 } |
2422 |
2416 |
2423 if (mode == ResolveAliases) { |
2417 for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { |
2424 for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { |
2418 const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); |
2425 const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); |
2419 |
2426 |
2420 if (p.type == Object::DynamicProperty::Alias) { |
2427 if (p.type == Object::DynamicProperty::Alias) { |
2421 if (mode == ResolveAliases) { |
2428 ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; |
2422 ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; |
2429 compileAlias(builder, dynamicData, obj, p); |
2423 compileAlias(builder, dynamicData, obj, p); |
|
2424 } else { |
|
2425 // Need a fake signal so that the metaobject remains consistent across |
|
2426 // the resolve and non-resolve alias runs |
|
2427 builder.addSignal(p.name + "Changed()"); |
2430 } |
2428 } |
2431 } |
2429 } |
2432 } |
2430 } |
2433 |
2431 |
2434 for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { |
2432 for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { |
2580 |
2578 |
2581 if (-1 == propIdx) |
2579 if (-1 == propIdx) |
2582 COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); |
2580 COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); |
2583 |
2581 |
2584 QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); |
2582 QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); |
|
2583 if (!aliasProperty.isScriptable()) |
|
2584 COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); |
|
2585 |
2585 writable = aliasProperty.isWritable(); |
2586 writable = aliasProperty.isWritable(); |
2586 |
2587 |
2587 if (aliasProperty.isEnumType()) |
2588 if (aliasProperty.isEnumType()) |
2588 typeName = "int"; // Avoid introducing a dependency on the aliased metaobject |
2589 typeName = "int"; // Avoid introducing a dependency on the aliased metaobject |
2589 else |
2590 else |
2616 data.append((const char *)&flags, sizeof(flags)); |
2617 data.append((const char *)&flags, sizeof(flags)); |
2617 |
2618 |
2618 builder.addSignal(prop.name + "Changed()"); |
2619 builder.addSignal(prop.name + "Changed()"); |
2619 QMetaPropertyBuilder propBuilder = |
2620 QMetaPropertyBuilder propBuilder = |
2620 builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); |
2621 builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); |
2621 propBuilder.setScriptable(true); |
|
2622 propBuilder.setWritable(writable); |
2622 propBuilder.setWritable(writable); |
2623 return true; |
2623 return true; |
2624 } |
2624 } |
2625 |
2625 |
2626 bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value, |
2626 bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value, |
2743 BindingReference &binding = *iter; |
2743 BindingReference &binding = *iter; |
2744 |
2744 |
2745 expr.context = binding.bindingContext.object; |
2745 expr.context = binding.bindingContext.object; |
2746 expr.property = binding.property; |
2746 expr.property = binding.property; |
2747 expr.expression = binding.expression; |
2747 expr.expression = binding.expression; |
2748 expr.imports = unit->imports; |
2748 expr.imports = unit->imports(); |
2749 |
2749 |
2750 int index = bindingCompiler.compile(expr, enginePrivate); |
2750 int index = bindingCompiler.compile(expr, enginePrivate); |
2751 if (index != -1) { |
2751 if (index != -1) { |
2752 binding.dataType = BindingReference::Experimental; |
2752 binding.dataType = BindingReference::Experimental; |
2753 binding.compiledIndex = index; |
2753 binding.compiledIndex = index; |