338 static_assert(
sizeof(Object) == 84,
"Update objectContentEqual when Object layout changes");
339 if (oldObj.nNamedObjectsInComponent != newObj.nNamedObjectsInComponent)
342 const quint32_le *oldNamed = oldObj.namedObjectsInComponentTable();
343 const quint32_le *newNamed = newObj.namedObjectsInComponentTable();
344 for (quint32 i = 0; i < oldObj.nNamedObjectsInComponent; ++i) {
345 if (oldNamed[i] != newNamed[i])
349 if (oldObj.nFunctions != newObj.nFunctions)
352 const quint32_le *oldFuncs = oldObj.functionOffsetTable();
353 const quint32_le *newFuncs = newObj.functionOffsetTable();
354 for (quint32 i = 0; i < oldObj.nFunctions; ++i) {
355 if (oldFuncs[i] != newFuncs[i])
357 if (!functionContentEqual(*oldUnit->functionAt(oldFuncs[i]),
358 *newUnit->functionAt(newFuncs[i]))) {
363 return stringsEqual(oldObj.inheritedTypeNameIndex, newObj.inheritedTypeNameIndex)
364 && stringsEqual(oldObj.idNameIndex, newObj.idNameIndex)
365 && oldObj.flags() == newObj.flags()
366 && oldObj.hasAliasAsDefaultProperty() == newObj.hasAliasAsDefaultProperty()
367 && oldObj.objectId() == newObj.objectId()
368 && oldObj.indexOfDefaultPropertyOrAlias == newObj.indexOfDefaultPropertyOrAlias;
446 static_assert(
sizeof(Binding) == 24,
"Update bindingContentEqual when Binding layout changes");
447 static_assert(
sizeof(TranslationData) == 16,
"Update bindingContentEqual when TranslationData layout changes");
448 if (oldBinding.type() != newBinding.type() || oldBinding.flags() != newBinding.flags())
451 if (!stringsEqual(oldBinding.propertyNameIndex, newBinding.propertyNameIndex))
454 switch (oldBinding.type()) {
455 case Binding::Type_Invalid:
457 case Binding::Type_Boolean:
458 return oldBinding.valueAsBoolean() == newBinding.valueAsBoolean();
459 case Binding::Type_Number: {
460 const uint oldIdx = oldBinding.value.constantValueIndex;
461 const uint newIdx = newBinding.value.constantValueIndex;
462 Q_ASSERT(oldIdx < oldUnit->constantTableSize);
463 Q_ASSERT(newIdx < newUnit->constantTableSize);
464 return oldIdx == newIdx && oldUnit->constants()[oldIdx] == newUnit->constants()[newIdx];
466 case Binding::Type_String:
467 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex);
468 case Binding::Type_Null:
470 case Binding::Type_Translation:
471 case Binding::Type_TranslationById: {
472 const auto &oldTrans = oldUnit->translations()[oldBinding.value.translationDataIndex];
473 const auto &newTrans = newUnit->translations()[newBinding.value.translationDataIndex];
477 const bool oldHasCtx = oldTrans.contextIndex != TranslationData::NoContextIndex;
478 const bool newHasCtx = newTrans.contextIndex != TranslationData::NoContextIndex;
480 if (oldHasCtx != newHasCtx)
483 if (oldHasCtx && !stringsEqual(oldTrans.contextIndex, newTrans.contextIndex))
486 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex)
487 && stringsEqual(oldTrans.stringIndex, newTrans.stringIndex)
488 && stringsEqual(oldTrans.commentIndex, newTrans.commentIndex)
489 && oldTrans.number == newTrans.number;
491 case Binding::Type_Script: {
492 if (oldBinding.value.compiledScriptIndex != newBinding.value.compiledScriptIndex)
494 const auto *oldFunc = oldUnit->functionAt(oldBinding.value.compiledScriptIndex);
495 const auto *newFunc = newUnit->functionAt(newBinding.value.compiledScriptIndex);
496 return oldFunc->nFormals == newFunc->nFormals && oldFunc->codeSize == newFunc->codeSize
497 && std::memcmp(oldFunc->code(), newFunc->code(), oldFunc->codeSize) == 0;
499 case Binding::Type_Object:
500 case Binding::Type_AttachedProperty:
501 case Binding::Type_GroupProperty:
502 return oldBinding.value.objectIndex == newBinding.value.objectIndex
503 && objectContentEqual(
504 *oldUnit->qmlUnit()->objectAt(oldBinding.value.objectIndex),
505 *newUnit->qmlUnit()->objectAt(newBinding.value.objectIndex));
730 const QmlUnit *oldQml = oldUnit->qmlUnit();
731 const QmlUnit *newQml = newUnit->qmlUnit();
733 if (!oldQml || !newQml)
740 change.data = extractData(*newUnit);
741 changes.append(change);
744 compareIndexedElements<Object>(
746 [oldQml](quint32 i) ->
const Object & {
return *oldQml->objectAt(i); },
749 [newQml](quint32 i) ->
const Object & {
return *newQml->objectAt(i); },
751 [
this](
const Object &a,
const Object &b) {
return objectContentEqual(a, b); });
754 const quint32 commonCount = std::min(oldQml->nObjects, newQml->nObjects);
755 for (quint32 objectIndex = 0; objectIndex < commonCount; ++objectIndex) {
757 const Object *oldObj = oldQml->objectAt(objectIndex);
758 const Object *newObj = newQml->objectAt(objectIndex);
760 compareObjectProperties(oldObj, newObj);
761 compareObjectAliases(oldObj, newObj);
762 compareObjectEnums(oldObj, newObj);
763 compareObjectSignals(oldObj, newObj);
764 compareObjectInlineComponents(oldObj, newObj);
765 compareObjectRequiredPropertyExtraData(oldObj, newObj);
766 compareObjectBindings(oldObj, newObj);
769 compareIndexedElements<quint64_le>(
770 IndexedElements{ [
this](quint32 i) {
return oldUnit->constants()[i]; },
771 oldUnit->constantTableSize },
772 IndexedElements{ [
this](quint32 i) {
return newUnit->constants()[i]; },
773 newUnit->constantTableSize },
774 [](
const quint64_le &a,
const quint64_le &b) {
return a == b; });
776 compareIndexedElements<QString>(
777 IndexedElements{ [
this](quint32 i) {
return oldUnit->stringAtInternal(i); },
778 oldUnit->stringTableSize },
779 IndexedElements{ [
this](quint32 i) {
return newUnit->stringAtInternal(i); },
780 newUnit->stringTableSize },
781 [](
const QString &a,
const QString &b) {
return a == b; });
783 compareIndexedElements<Lookup>(
784 IndexedElements{ [
this](quint32 i) {
return oldUnit->lookupTable()[i]; },
785 oldUnit->lookupTableSize },
786 IndexedElements{ [
this](quint32 i) {
return newUnit->lookupTable()[i]; },
787 newUnit->lookupTableSize },
788 [
this](
const Lookup &a,
const Lookup &b) {
789 return a.type() == b.type() && a.mode() == b.mode()
790 && stringsEqual(a.nameIndex(), b.nameIndex());
793 compareIndexedElements<Import>(
794 IndexedElements{ [oldQml](quint32 i) {
return *oldQml->importAt(i); },
796 IndexedElements{ [newQml](quint32 i) {
return *newQml->importAt(i); },
798 [
this](
const Import &a,
const Import &b) {
799 return a.type == b.type && stringsEqual(a.uriIndex, b.uriIndex)
800 && stringsEqual(a.qualifierIndex, b.qualifierIndex)
801 && a.version == b.version;
804 compareIndexedElements<Function>(IndexedElements{ [
this](quint32 i) ->
const Function & {
805 return *oldUnit->functionAt(i);
807 oldUnit->functionTableSize },
808 IndexedElements{ [
this](quint32 i) ->
const Function & {
809 return *newUnit->functionAt(i);
811 newUnit->functionTableSize },
812 [
this](
const Function &a,
const Function &b) {
813 return functionContentEqual(a, b);
816 compareIndexedElements<TranslationData>(
817 IndexedElements{ [
this](quint32 i) {
return oldUnit->translations()[i]; },
818 oldUnit->translationTableSize },
819 IndexedElements{ [
this](quint32 i) {
return newUnit->translations()[i]; },
820 newUnit->translationTableSize },
821 [
this](
const TranslationData &a,
const TranslationData &b) {
822 return translationContentEqual(a, b);
825 compareIndexedElements<RegExp>(
827 [
this](quint32 i) ->
const RegExp & {
return *oldUnit->regexpAt(i); },
828 oldUnit->regexpTableSize },
830 [
this](quint32 i) ->
const RegExp & {
return *newUnit->regexpAt(i); },
831 newUnit->regexpTableSize },
832 [
this](
const RegExp &a,
const RegExp &b) {
833 return a.flags() == b.flags() && stringsEqual(a.stringIndex(), b.stringIndex());
836 compareIndexedElements<Class>(
838 [
this](quint32 i) ->
const Class & {
return *oldUnit->classAt(i); },
839 oldUnit->classTableSize },
841 [
this](quint32 i) ->
const Class & {
return *newUnit->classAt(i); },
842 newUnit->classTableSize },
843 [
this](
const Class &a,
const Class &b) {
return classContentEqual(a, b); });
845 compareIndexedElements<TemplateObject>(
846 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
847 return *oldUnit->templateObjectAt(i);
849 oldUnit->templateObjectTableSize },
850 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
851 return *newUnit->templateObjectAt(i);
853 newUnit->templateObjectTableSize },
854 [
this](
const TemplateObject &a,
const TemplateObject &b) {
855 return templateObjectContentEqual(a, b);
859 auto jsClassFromUnit = [](
const Unit *unit, quint32 idx) ->
const JSClass & {
860 const quint32_le *offsetTable =
reinterpret_cast<
const quint32_le *>(
861 reinterpret_cast<
const char *>(unit) + unit->offsetToJSClassTable);
862 return *
reinterpret_cast<
const JSClass *>(
reinterpret_cast<
const char *>(unit)
865 compareIndexedElements<JSClass>(
866 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
867 return jsClassFromUnit(oldUnit, i);
869 oldUnit->jsClassTableSize },
870 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
871 return jsClassFromUnit(newUnit, i);
873 newUnit->jsClassTableSize },
874 [
this](
const JSClass &a,
const JSClass &b) {
875 return jsClassContentEqual(a, b);
879 compareIndexedElements<Block>(
881 [
this](quint32 i) ->
const Block & {
return *oldUnit->blockAt(i); },
882 oldUnit->blockTableSize },
884 [
this](quint32 i) ->
const Block & {
return *newUnit->blockAt(i); },
885 newUnit->blockTableSize },
886 [
this](
const Block &a,
const Block &b) {
return blockContentEqual(a, b); });
888 return CompilationUnitDiff{ std::move(changes),
true };