6#include <private/qv4staticvalue_p.h>
7#include <private/qv4compileddata_p.h>
8#include <private/qqmljsparser_p.h>
9#include <private/qqmljslexer_p.h>
10#include <private/qv4compilerscanfunctions_p.h>
11#include <QCoreApplication>
12#include <QCryptographicHash>
23#define COMPILE_EXCEPTION(location, desc) \
25 recordError(location, desc); \
29void Object::simplifyRequiredProperties() {
34 for (
auto it = this->requiredPropertyExtraDataBegin();
it != this->requiredPropertyExtraDataEnd(); ++
it)
35 required.insert(
it->nameIndex);
36 if (required.isEmpty())
38 for (
auto it = this->propertiesBegin();
it != this->propertiesEnd(); ++
it) {
39 auto requiredIt = required.find(
it->nameIndex);
40 if (requiredIt != required.end()) {
41 it->setIsRequired(
true);
42 required.erase(requiredIt);
46 auto current = this->requiredPropertyExtraDatas->first;
48 if (required.contains(current->nameIndex))
51 requiredPropertyExtraDatas->unlink(prev, current);
52 current = current->
next;
64 paramType->
set(listFlag, 0);
68 paramType->
set(listFlag, typeNameIndex);
72 static_cast<quint32>(builtinType));
79 static const struct TypeNameToType {
83 } propTypeNameToTypes[] = {
99 static const int propTypeNameToTypesCount =
sizeof(propTypeNameToTypes) /
100 sizeof(propTypeNameToTypes[0]);
102 for (
int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) {
103 const TypeNameToType *
t = propTypeNameToTypes + typeIndex;
122 properties =
pool->New<PoolList<Property> >();
123 aliases =
pool->New<PoolList<Alias> >();
124 qmlEnums =
pool->New<PoolList<Enum>>();
125 qmlSignals =
pool->New<PoolList<Signal> >();
126 bindings =
pool->New<PoolList<Binding> >();
127 functions =
pool->New<PoolList<Function> >();
129 inlineComponents =
pool->New<PoolList<InlineComponent>>();
130 requiredPropertyExtraDatas =
pool->New<PoolList<RequiredPropertyExtraData>>();
136 QSet<int> functionNames;
137 for (
auto functionit =
obj->functionsBegin(); functionit !=
obj->functionsEnd(); ++functionit) {
140 errorLocation->startColumn =
f->location.column();
141 if (functionNames.contains(
f->nameIndex))
142 return tr(
"Duplicate method name");
143 functionNames.insert(
f->nameIndex);
145 for (
auto signalit =
obj->signalsBegin(); signalit !=
obj->signalsEnd(); ++signalit) {
147 if (
s->nameIndex ==
f->nameIndex)
148 return tr(
"Duplicate method name");
152 if (
name.at(0).isUpper())
153 return tr(
"Method names cannot begin with an upper case letter");
155 return tr(
"Illegal method name");
166 for (
Enum *e = qmlEnums->first; e; e = e->next) {
167 if (e->nameIndex == enumeration->
nameIndex)
168 return tr(
"Duplicate scoped enum name");
171 target->qmlEnums->append(enumeration);
181 for (
Signal *
s = qmlSignals->first;
s;
s =
s->next) {
182 if (
s->nameIndex ==
signal->nameIndex)
183 return tr(
"Duplicate signal name");
198 return tr(
"Duplicate property name");
202 return tr(
"Property duplicates alias name");
205 return tr(
"Property names cannot begin with an upper case letter");
207 const int index =
target->properties->append(prop);
208 if (isDefaultProperty) {
209 if (
target->indexOfDefaultPropertyOrAlias != -1) {
210 *errorLocation = defaultToken;
211 return tr(
"Duplicate default property");
224 const auto aliasWithSameName = std::find_if(
target->aliases->begin(),
target->aliases->end(), [&alias](
const Alias &targetAlias){
225 return targetAlias.nameIndex() == alias->nameIndex();
227 if (aliasWithSameName !=
target->aliases->end())
228 return tr(
"Duplicate alias name");
230 const auto aliasSameAsProperty = std::find_if(
target->properties->begin(),
target->properties->end(), [&alias](
const Property &targetProp){
231 return targetProp.nameIndex == alias->nameIndex();
234 if (aliasSameAsProperty !=
target->properties->end())
235 return tr(
"Alias has same name as existing property");
237 if (aliasName.constData()->isUpper())
238 return tr(
"Alias names cannot begin with an upper case letter");
242 if (isDefaultProperty) {
243 if (
target->indexOfDefaultPropertyOrAlias != -1) {
244 *errorLocation = defaultToken;
245 return tr(
"Duplicate default property");
248 target->defaultPropertyIsAlias =
true;
260 functions->append(
f);
265 inlineComponents->append(ic);
270 requiredPropertyExtraDatas->append(extraData);
275 const bool bindingToDefaultProperty = (
b->propertyNameIndex ==
quint32(0));
277 && !bindingToDefaultProperty
283 && existing->isValueBinding() ==
b->isValueBinding()
285 return tr(
"Property value set multiple times");
288 if (bindingToDefaultProperty)
291 bindings->prepend(
b);
298 if (
b->propertyNameIndex == nameIndex)
306 bindings->insertAfter(insertionPoint,
b);
314 node = exprStmt->expression;
330 : jsModule(debugMode)
332 , jsGenerator(&jsModule)
338 ,
engine(&doc->jsParserEngine)
339 , jsGenerator(&doc->jsGenerator)
354 import->location.set(lineNumber,
column);
365 import->location.set(lineNumber,
column);
370 : illegalNames(illegalNames)
372 , _propertyDeclaration(
nullptr)
385 QQmlJS::Parser parser(&
output->jsParserEngine);
387 const bool parseResult = parser.parse();
388 const auto diagnosticMessages = parser.diagnosticMessages();
389 if (!parseResult || !diagnosticMessages.isEmpty()) {
430 int rootObjectIndex = -1;
439 for (
auto object:
output->objects)
440 object->simplifyRequiredProperties();
447 return QQmlJS::AST::Visitor::visit(ast);
468 lastId = lastId->
next;
469 bool isType = lastId->
name.
data()->isUpper();
512 auto inlineComponent = New<InlineComponent>();
514 inlineComponent->objectIndex = idx;
526 { location.startLine, location.startColumn }, node->
initializer)) {
551 if (
bindingsTarget()->findBinding(propertyNameIndex) !=
nullptr) {
556 QVarLengthArray<QQmlJS::AST::UiArrayMemberList *, 16> memberList;
559 memberList.append(member);
560 member = member->
next;
562 for (
int i = memberList.size() - 1;
i >= 0; --
i) {
563 member = memberList.at(
i);
569 appendBinding(qualifiedNameLocation,
name->identifierToken, propertyNameIndex, idx,
true);
578 return QQmlJS::AST::Visitor::visit(
list);
583 return QQmlJS::AST::Visitor::visit(ast);
588 return QQmlJS::AST::Visitor::visit(ast);
593 return QQmlJS::AST::Visitor::visit(ast);
598 return QQmlJS::AST::Visitor::visit(
id);
609 Object *declarationsOverride)
612 while (lastName->next)
613 lastName = lastName->next;
614 if (!lastName->name.constData()->isUpper()) {
615 recordError(lastName->identifierToken,
tr(
"Expected type name"));
647 if (!
error.isEmpty()) {
678 if (!qualifier.
at(0).isUpper()) {
722template<
typename Argument>
731 if (!isUnique(builder)) {
734 "QQmlParser",
"Multiple %1 pragmas found").arg(
name()));
738 pragma->type =
type();
743 "QQmlParser",
"Unknown %1 '%2' in pragma").arg(
name(), bad->value));
753 if constexpr (std::is_same_v<Argument, Pragma::ComponentBehaviorValue>) {
755 }
else if constexpr (std::is_same_v<Argument, Pragma::ListPropertyAssignBehaviorValue>) {
757 }
else if constexpr (std::is_same_v<Argument, Pragma::FunctionSignatureBehaviorValue>) {
759 }
else if constexpr (std::is_same_v<Argument, Pragma::NativeMethodBehaviorValue>) {
761 }
else if constexpr (std::is_same_v<Argument, Pragma::ValueTypeBehaviorValue>) {
773 if (!process(
i->value))
785 if constexpr (std::is_same_v<Argument, Pragma::ComponentBehaviorValue>) {
787 if (
value ==
"Unbound"_L1) {
791 if (
value ==
"Bound"_L1) {
797 }
else if constexpr (std::is_same_v<Argument, Pragma::ListPropertyAssignBehaviorValue>) {
799 if (
value ==
"Append"_L1) {
803 if (
value ==
"Replace"_L1) {
807 if (
value ==
"ReplaceIfNotDefault"_L1) {
813 }
else if constexpr (std::is_same_v<Argument, Pragma::FunctionSignatureBehaviorValue>) {
815 if (
value ==
"Ignored"_L1) {
819 if (
value ==
"Enforced"_L1) {
825 }
else if constexpr (std::is_same_v<Argument, Pragma::NativeMethodBehaviorValue>) {
827 if (
value ==
"AcceptThisObject"_L1) {
831 if (
value ==
"RejectThisObject"_L1) {
837 }
else if constexpr (std::is_same_v<Argument, Pragma::ValueTypeBehaviorValue>) {
838 pragma->valueTypeBehavior = Pragma::ValueTypeBehaviorValues().toInt();
841 pragma->valueTypeBehavior
842 = Pragma::ValueTypeBehaviorValues(pragma->valueTypeBehavior)
843 .setFlag(flag,
value).toInt();
846 if (
value ==
"Reference"_L1) {
850 if (
value ==
"Copy"_L1) {
855 if (
value ==
"Inaddressable"_L1) {
859 if (
value ==
"Addressable"_L1) {
864 if (
value ==
"Inassertable"_L1) {
868 if (
value ==
"Assertable"_L1) {
877 Q_UNREACHABLE_RETURN(
nullptr);
882 for (
const Pragma *prev : builder->_pragmas) {
883 if (prev->type ==
type())
893 return "list property assign behavior"_L1;
895 return "component behavior"_L1;
897 return "function signature behavior"_L1;
899 return "native method behavior"_L1;
901 return "value type behavior"_L1;
911 Pragma *pragma = New<Pragma>();
914 if (node->
name ==
"Singleton"_L1) {
916 }
else if (node->
name ==
"Strict"_L1) {
918 }
else if (node->
name ==
"ComponentBehavior"_L1) {
921 }
else if (node->
name ==
"ListPropertyAssignBehavior"_L1) {
924 }
else if (node->
name ==
"FunctionSignatureBehavior"_L1) {
927 }
else if (node->
name ==
"NativeMethodBehavior"_L1) {
930 }
else if (node->
name ==
"ValueTypeBehavior"_L1) {
933 }
else if (node->
name ==
"Translator"_L1) {
939 "QQmlParser",
"Unknown pragma '%1'").arg(node->
name));
944 "QQmlParser",
"Empty pragma found"));
974 Enum *enumeration = New<Enum>();
978 if (enumName.
at(0).isLower())
983 enumeration->
enumValues = New<PoolList<EnumValue>>();
988 QString member = e->member.toString();
990 if (member.
at(0).isLower())
994 if (std::modf(e->value, &part) != 0.0)
996 if (e->value > std::numeric_limits<qint32>::max() || e->value < std::numeric_limits<qint32>::min())
998 enumValue->value = e->value;
1000 enumValue->location.set(e->memberToken.startLine, e->memberToken.startColumn);
1007 if (!
error.isEmpty()) {
1026 signal->parameters = New<PoolList<Parameter> >();
1038 &
param->type, [
this](
const QString &
str) { return registerString(str); },
1041 errStr.append(
p->type->toString());
1049 for (
const QChar &
ch : signalName) {
1054 tr(
"Signal names cannot begin with an upper case letter"));
1062 if (!
error.isEmpty()) {
1073 Property *
property = New<Property>();
1080 property->setCommonType(builtinPropertyType);
1086 property->setIsList(
true);
1087 }
else if (!typeModifier.
isEmpty()) {
1102 error =
tr(
"Illegal property name");
1106 if (!
error.isEmpty()) {
1107 if (errorLocation.startLine == 0)
1136 "QQmlParser",
"Function declaration inside grouped property"));
1141 foe->node = funDecl;
1142 foe->parentNode = funDecl;
1155 &
f->returnType, idGenerator,
1156 funDecl->typeAnnotation ? funDecl->typeAnnotation->type :
nullptr);
1159 int formalsCount = formals.size();
1160 f->formals.allocate(
pool, formalsCount);
1163 for (
const auto &
arg : formals) {
1167 &functionParameter->type, idGenerator,
1168 arg.typeAnnotation.isNull() ?
nullptr :
arg.typeAnnotation->type);
1181 auto extraData = New<RequiredPropertyExtraData>();
1211 if (
string.isEmpty())
1247 binding->
value.b =
true;
1250 binding->
value.b =
false;
1260 }
else if (QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression *>(expr)) {
1267 }
else if (QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr)) {
1269 binding->
value.nullMarker = 0;
1278 expr->
node = statement;
1290 nodeForString = exprStmt->expression;
1304 const auto finalizeTranslationData = [&](
1324 Object *
object =
nullptr;
1339 Object *
object =
nullptr;
1350 Binding *binding = New<Binding>();
1352 binding->
offset = nameLocation.offset;
1353 binding->
location.
set(nameLocation.startLine, nameLocation.startColumn);
1357 if (!
error.isEmpty()) {
1365 recordError(nameLocation,
tr(
"Invalid component id specification"));
1369 Binding *binding = New<Binding>();
1371 binding->
offset = nameLocation.offset;
1372 binding->
location.
set(nameLocation.startLine, nameLocation.startColumn);
1393 binding->
value.objectIndex = objectIndex;
1395 if (!
error.isEmpty()) {
1402 Alias *alias = New<Alias>();
1431 if (aliasReference.isEmpty()) {
1433 COMPILE_EXCEPTION(rhsLoc,
tr(
"Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
1439 COMPILE_EXCEPTION(rhsLoc,
tr(
"Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
1442 if (aliasReference.size() < 1 || aliasReference.size() > 3)
1443 COMPILE_EXCEPTION(rhsLoc,
tr(
"Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
1447 QString propertyValue = aliasReference.value(1);
1448 if (aliasReference.size() == 3)
1449 propertyValue +=
QLatin1Char(
'.') + aliasReference.at(2);
1456 error =
tr(
"Illegal property name");
1460 if (!
error.isEmpty()) {
1461 if (errorLocation.startLine == 0)
1489 node = stmt->expression;
1499 if (
ch.isLetter() && !
ch.isLower())
1503 if (!
ch.isLetter() &&
ch != u)
1506 for (
int ii = 1; ii <
str.
size(); ++ii) {
1508 if (!
ch.isLetterOrNumber() &&
ch != u)
1529 if (qualifiedIdElement->name ==
QLatin1String(
"id") && qualifiedIdElement->next)
1530 COMPILE_EXCEPTION(qualifiedIdElement->identifierToken,
tr(
"Invalid use of id property"));
1533 QString currentName = qualifiedIdElement->name.toString();
1534 if (qualifiedIdElement->next) {
1537 &&
stringAt(import->qualifierIndex) == currentName) {
1538 qualifiedIdElement = qualifiedIdElement->next;
1539 currentName +=
QLatin1Char(
'.') + qualifiedIdElement->name;
1541 if (!qualifiedIdElement->name.data()->isUpper())
1549 while (qualifiedIdElement->next) {
1551 const bool isAttachedProperty = qualifiedIdElement->name.data()->isUpper();
1553 Binding *binding = (*object)->findBinding(propertyNameIndex);
1555 if (isAttachedProperty) {
1563 binding = New<Binding>();
1565 binding->
offset = qualifiedIdElement->identifierToken.offset;
1566 binding->
location.
set(qualifiedIdElement->identifierToken.startLine,
1567 qualifiedIdElement->identifierToken.startColumn);
1568 binding->
valueLocation.
set(qualifiedIdElement->next->identifierToken.startLine,
1569 qualifiedIdElement->next->identifierToken.startColumn);
1575 if (isAttachedProperty)
1583 binding->
value.objectIndex = objIndex;
1585 QString error = (*object)->appendBinding(binding,
false);
1586 if (!
error.isEmpty()) {
1596 qualifiedIdElement = qualifiedIdElement->next;
1597 if (qualifiedIdElement)
1598 currentName = qualifiedIdElement->name.toString();
1600 *nameToResolve = qualifiedIdElement;
1608 error.message = description;
1616 if (QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expr))
1622 else if (QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expr))
1627 if (QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(unaryMinus->expression)) {
1645 return QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr);
1652 output.jsGenerator.stringTable.registerString(
output.jsModule.fileName);
1653 output.jsGenerator.stringTable.registerString(
output.jsModule.finalUrl);
1655 Unit *jsUnit =
nullptr;
1657 if (!
output.javaScriptCompilationUnit)
1661 if (
output.javaScriptCompilationUnit->unitData()) {
1662 jsUnit =
const_cast<Unit *
>(
output.javaScriptCompilationUnit->unitData());
1663 output.javaScriptCompilationUnit->dynamicStrings
1664 =
output.jsGenerator.stringTable.allStrings();
1667 jsUnit = createdUnit =
output.jsGenerator.generateUnit();
1673 createdUnit->flags |= Unit::IsSingleton;
1676 createdUnit->flags |= Unit::IsStrict;
1680 switch (
p->componentBehavior) {
1682 createdUnit->flags |= Unit::ComponentsBound;
1690 switch (
p->listPropertyAssignBehavior) {
1692 createdUnit->flags |= Unit::ListPropertyAssignReplace;
1695 createdUnit->flags |= Unit::ListPropertyAssignReplaceIfNotDefault;
1703 switch (
p->functionSignatureBehavior) {
1707 createdUnit->flags |= Unit::FunctionSignaturesIgnored;
1712 switch (
p->nativeMethodBehavior) {
1714 createdUnit->flags |= Unit::NativeMethodsAcceptThisObject;
1722 if (Pragma::ValueTypeBehaviorValues(
p->valueTypeBehavior)
1724 createdUnit->flags |= Unit::ValueTypesCopied;
1726 if (Pragma::ValueTypeBehaviorValues(
p->valueTypeBehavior)
1728 createdUnit->flags |= Unit::ValueTypesAddressable;
1730 if (Pragma::ValueTypeBehaviorValues(
p->valueTypeBehavior)
1732 createdUnit->flags |= Unit::ValueTypesAssertable;
1736 if (createdUnit->translationTableSize)
1738 *
index =
p->translationContextIndex;
1743 if (dependencyHasher) {
1745 if (
checksum.size() ==
sizeof(createdUnit->dependencyMD5Checksum)) {
1746 memcpy(createdUnit->dependencyMD5Checksum,
checksum.constData(),
1747 sizeof(createdUnit->dependencyMD5Checksum));
1751 createdUnit->sourceFileIndex =
output.jsGenerator.stringTable.getStringId(
output.jsModule.fileName);
1752 createdUnit->finalUrlIndex =
output.jsGenerator.stringTable.getStringId(
output.jsModule.finalUrl);
1756 output.jsGenerator.stringTable.freeze();
1761 QHash<const Object*, quint32> objectOffsets;
1764 uint nextOffset = objectOffset + objectOffsetTableSize;
1766 objectOffsets.insert(
o, nextOffset);
1769 int signalTableSize = 0;
1770 for (
const Signal *
s =
o->firstSignal();
s;
s =
s->next)
1773 nextOffset += signalTableSize;
1775 int enumTableSize = 0;
1776 for (
const Enum *e =
o->firstEnum(); e; e = e->next)
1779 nextOffset += enumTableSize;
1782 const uint totalSize = nextOffset;
1783 char *
data = (
char*)malloc(totalSize);
1784 memset(
data, 0, totalSize);
1795 *importToWrite = *imp;
1801 for (
int i = 0;
i <
output.objects.size(); ++
i) {
1803 char *
const objectPtr =
data + objectOffsets.value(
o);
1804 *objectTable++ = objectOffsets.value(
o);
1808 objectToWrite->indexOfDefaultPropertyOrAlias =
o->indexOfDefaultPropertyOrAlias;
1809 objectToWrite->setHasAliasAsDefaultProperty(
o->defaultPropertyIsAlias);
1810 objectToWrite->setFlags(QV4::CompiledData::Object::Flags(
o->flags));
1811 objectToWrite->idNameIndex =
o->idNameIndex;
1812 objectToWrite->setObjectId(
o->id);
1813 objectToWrite->location =
o->location;
1814 objectToWrite->locationOfIdProperty =
o->locationOfIdProperty;
1818 objectToWrite->nFunctions =
o->functionCount();
1819 objectToWrite->offsetToFunctions = nextOffset;
1820 nextOffset += objectToWrite->nFunctions *
sizeof(
quint32);
1822 objectToWrite->nProperties =
o->propertyCount();
1823 objectToWrite->offsetToProperties = nextOffset;
1826 objectToWrite->nAliases =
o->aliasCount();
1827 objectToWrite->offsetToAliases = nextOffset;
1830 objectToWrite->nEnums =
o->enumCount();
1831 objectToWrite->offsetToEnums = nextOffset;
1832 nextOffset += objectToWrite->nEnums *
sizeof(
quint32);
1834 objectToWrite->nSignals =
o->signalCount();
1835 objectToWrite->offsetToSignals = nextOffset;
1836 nextOffset += objectToWrite->nSignals *
sizeof(
quint32);
1838 objectToWrite->nBindings =
o->bindingCount();
1839 objectToWrite->offsetToBindings = nextOffset;
1842 objectToWrite->nNamedObjectsInComponent =
o->namedObjectsInComponent.size();
1843 objectToWrite->offsetToNamedObjectsInComponent = nextOffset;
1844 nextOffset += objectToWrite->nNamedObjectsInComponent *
sizeof(
quint32);
1846 objectToWrite->nInlineComponents =
o->inlineComponentCount();
1847 objectToWrite->offsetToInlineComponents = nextOffset;
1850 objectToWrite->nRequiredPropertyExtraData =
o->requiredPropertyExtraDataCount();
1851 objectToWrite->offsetToRequiredPropertyExtraData = nextOffset;
1854 quint32_le *functionsTable =
reinterpret_cast<quint32_le *
>(objectPtr + objectToWrite->offsetToFunctions);
1855 for (
const Function *
f =
o->firstFunction();
f;
f =
f->next)
1856 *functionsTable++ =
o->runtimeFunctionIndices.at(
f->index);
1858 char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties;
1859 for (
const Property *
p =
o->firstProperty();
p;
p =
p->next) {
1861 *propertyToWrite = *
p;
1865 char *aliasesPtr = objectPtr + objectToWrite->offsetToAliases;
1866 for (
const Alias *
a =
o->firstAlias();
a;
a =
a->next) {
1872 char *bindingPtr = objectPtr + objectToWrite->offsetToBindings;
1880 quint32_le *signalOffsetTable =
reinterpret_cast<quint32_le *
>(objectPtr + objectToWrite->offsetToSignals);
1882 char *signalPtr = objectPtr + nextOffset;
1883 for (
const Signal *
s =
o->firstSignal();
s;
s =
s->next) {
1884 *signalOffsetTable++ = signalPtr - objectPtr;
1888 signalToWrite->location =
s->location;
1889 signalToWrite->nParameters =
s->parameters->count;
1893 *parameterToWrite = *
param;
1896 signalTableSize +=
size;
1899 nextOffset += signalTableSize;
1901 quint32_le *enumOffsetTable =
reinterpret_cast<quint32_le*
>(objectPtr + objectToWrite->offsetToEnums);
1902 char *enumPtr = objectPtr + nextOffset;
1903 for (
const Enum *e =
o->firstEnum(); e; e = e->next) {
1904 *enumOffsetTable++ = enumPtr - objectPtr;
1908 enumToWrite->location = e->location;
1909 enumToWrite->nEnumValues = e->enumValues->count;
1912 for (
EnumValue *enumValue = e->enumValues->
first; enumValue; enumValue = enumValue->next, ++enumValueToWrite)
1913 *enumValueToWrite = *enumValue;
1919 quint32_le *namedObjectInComponentPtr =
reinterpret_cast<quint32_le *
>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent);
1920 for (
int i = 0;
i <
o->namedObjectsInComponent.size(); ++
i) {
1921 *namedObjectInComponentPtr++ =
o->namedObjectsInComponent.at(
i);
1924 char *inlineComponentPtr = objectPtr + objectToWrite->offsetToInlineComponents;
1925 for (
auto it =
o->inlineComponentsBegin();
it !=
o->inlineComponentsEnd(); ++
it) {
1932 char *requiredPropertyExtraDataPtr = objectPtr + objectToWrite->offsetToRequiredPropertyExtraData;
1933 for (
auto it =
o->requiredPropertyExtraDataBegin();
it !=
o->requiredPropertyExtraDataEnd(); ++
it) {
1936 *extraDataToWrite = *extraData;
1941 if (!
output.javaScriptCompilationUnit->unitData()) {
1945 jsUnit->unitSize += totalSize;
1946 memcpy(jsUnit->qmlUnit(), qmlUnit, totalSize);
1949 qmlUnit = jsUnit->qmlUnit();
1954 qDebug() <<
"Generated QML unit that is" << totalSize <<
"bytes big contains:";
1955 qDebug() <<
" " << jsUnit->functionTableSize <<
"functions";
1956 qDebug() <<
" " << jsUnit->unitSize <<
"for JS unit";
1957 qDebug() <<
" " << importSize <<
"for imports";
1958 qDebug() <<
" " << nextOffset - objectOffset - objectOffsetTableSize <<
"for" << qmlUnit->
nObjects <<
"objects";
1959 quint32 totalBindingCount = 0;
1962 qDebug() <<
" " << totalBindingCount <<
"bindings";
1964 for (
quint32 i = 0;
i < jsUnit->functionTableSize; ++
i)
1965 totalCodeSize += jsUnit->functionAt(
i)->codeSize;
1966 qDebug() <<
" " << totalCodeSize <<
"bytes total byte code";
1967 qDebug() <<
" " << jsUnit->stringTableSize <<
"strings";
1969 for (
quint32 i = 0;
i < jsUnit->stringTableSize; ++
i)
1971 qDebug() <<
" " << totalStringSize <<
"bytes total strings";
1974 output.javaScriptCompilationUnit->setUnitData(
1975 jsUnit, qmlUnit,
output.jsModule.fileName,
output.jsModule.finalUrl);
1978char *QmlUnitGenerator::writeBindings(
char *bindingPtr,
const Object *
o, BindingFilter
filter)
const
1980 for (
const Binding *
b =
o->firstBinding();
b;
b =
b->next) {
1984 *bindingToWrite = *
b;
1986 bindingToWrite->
value.compiledScriptIndex =
o->runtimeFunctionIndices.at(
b->value.compiledScriptIndex);
1994 bool storeSourceLocations)
1995 :
QV4::Compiler::Codegen(&document->jsGenerator,
false, iface,
1996 storeSourceLocations),
2000 _module = &document->jsModule;
2005 const QList<CompiledFunctionOrExpression> &functions)
2008 if (
c.nameIndex != 0)
2013 QVector<int> runtimeFunctionIndices(functions.size());
2020 auto function =
f.node->asFunctionDefinition();
2035 scan(function ? function->body :
f.node);
2041 return QVector<int>();
2045 for (
int i = 0;
i < functions.size(); ++
i) {
2054 name = function->name.toString();
2056 name = qmlName(qmlFunction);
2060 body = function->body;
2076 function ? function->formals :
nullptr, body);
2077 runtimeFunctionIndices[
i] = idx;
2080 return runtimeFunctionIndices;
2085 if (
object->functionsAndExpressions->count == 0)
2088 QList<QmlIR::CompiledFunctionOrExpression> functionsToCompile;
2089 functionsToCompile.reserve(
object->functionsAndExpressions->count);
2092 functionsToCompile << *foe;
2100 runtimeFunctionIndices);
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
qsizetype size() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
void append(parameter_type t)
virtual SourceLocation firstSourceLocation() const =0
void accept(BaseVisitor *visitor)
virtual Statement * statementCast()
virtual SourceLocation lastSourceLocation() const =0
virtual ExpressionNode * expressionCast()
virtual FunctionExpression * asFunctionDefinition()
@ Kind_IdentifierExpression
@ Kind_FieldMemberExpression
UiQualifiedId * qualifiedId
UiArrayMemberList * members
UiEnumMemberList * members
UiVersionSpecifier * version
SourceLocation importIdToken
UiQualifiedId * importUri
SourceLocation fileNameToken
SourceLocation importToken
SourceLocation firstSourceLocation() const override
UiObjectDefinition * component
UiQualifiedId * qualifiedTypeNameId
UiQualifiedId * qualifiedId
UiObjectInitializer * initializer
UiQualifiedId * qualifiedTypeNameId
UiObjectInitializer * initializer
SourceLocation firstSourceLocation() const override=0
UiPragmaValueList * values
SourceLocation pragmaToken
SourceLocation semicolonToken
UiParameterList * parameters
SourceLocation identifierToken
SourceLocation firstSourceLocation() const override
enum QQmlJS::AST::UiPublicMember::@662 type
SourceLocation defaultToken() const
bool isDefaultMember() const
SourceLocation typeModifierToken
UiQualifiedId * memberType
SourceLocation firstSourceLocation() const override
SourceLocation identifierToken
UiQualifiedId * qualifiedId
SourceLocation firstSourceLocation() const override
void setCode(const QString &code, int lineno, bool qmlMode=true, CodeContinuation codeContinuation=CodeContinuation::Reset)
bool contains(const T &value) const
iterator insert(const T &value)
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
const_pointer data() const noexcept
QString toString() const
Returns a deep copy of this string view's data as a QString.
constexpr bool isNull() const noexcept
Returns whether this string view is null - that is, whether {data() == nullptr}.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
qsizetype size() const noexcept
Returns the number of characters in this string.
QString first(qsizetype n) const &
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
QString & append(QChar c)
static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
Produces a QTypeRevision from the given majorVersion with an invalid minor version.
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
Produces a QTypeRevision from the given majorVersion and minorVersion, both of which need to be a val...
QSet< QString > m_globalNames
virtual int defineFunction(const QString &name, QQmlJS::AST::Node *ast, QQmlJS::AST::FormalParameterList *formals, QQmlJS::AST::StatementList *body)
void enterQmlFunction(QQmlJS::AST::FunctionExpression *ast)
void handleTopLevelFunctionFormals(QQmlJS::AST::FunctionExpression *node)
void enterEnvironment(QQmlJS::AST::Node *node, ContextType compilationMode, const QString &name)
void enterGlobalEnvironment(ContextType compilationMode)
void importFile(const QString &jsfile, const QString &module, int lineNumber, int column) override
void importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) override
void pragmaLibrary() override
ScriptDirectivesCollector(QmlIR::Document *doc)
QSet< QString >::iterator it
std::function< QByteArray()> DependentTypesHasher
void tryGeneratingTranslationBindingBase(QStringView base, QQmlJS::AST::ArgumentList *args, RegisterMainString registerMainString, RegisterCommentString registerCommentString, RegisterContextString registerContextString, FinalizeTranslationData finalizeTranslationData)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static quint32 checksum(const QByteArray &table)
static bool isScript(QStringView tag)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum const GLint * param
GLenum GLenum GLsizei void GLsizei void * column
GLenum GLenum GLenum input
GLsizei const GLchar *const * string
[0]
static qreal dot(const QPointF &a, const QPointF &b)
static const quint32 emptyStringIndex
#define COMPILE_EXCEPTION(location, desc)
static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
static int toInt(const QChar &qc, int R)
QT_BEGIN_NAMESPACE typedef uchar * output
QUrl url("example.com")
[constructor-url-reference]
char * toString(const MyType &t)
[31]
static bool run(IRBuilder *builder, QQmlJS::AST::UiPragma *node, Pragma *pragma)
\inmodule QtCore \reentrant
Location referenceLocation
quint32_le propertyNameIndex
void setNameIndex(quint32 nameIndex)
void setIdIndex(quint32 idIndex)
union QV4::CompiledData::Binding::@548 value
quint32_le propertyNameIndex
bool isSignalHandler() const
bool isAttachedProperty() const
bool isGroupProperty() const
bool isValueBindingNoAlias() const
bool isValueBindingToAlias() const
@ InitializerForReadOnlyDeclaration
static int calculateSize(int nEnumValues)
void set(quint32 line, quint32 column)
quint32_le inheritedTypeNameIndex
@ IsPartOfInlineComponent
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
void set(Flags flags, quint32 typeNameIndexOrCommonType)
quint32_le offsetToObjects
const Object * objectAt(int idx) const
quint32_le offsetToImports
static int calculateSize(int nParameters)
static int calculateSize(const QString &str)
quint32_le offsetToQmlUnit
static void generateUnitChecksum(CompiledData::Unit *unit)
int registerTranslation(const CompiledData::TranslationData &translation)
QString stringForIndex(int index) const
int registerConstant(ReturnedValue v)
int registerString(const QString &str)
QString stringForIndex(int index) const
QQmlJS::AST::Node * parentNode
QQmlJS::AST::UiProgram * program
QString stringAt(int index) const
QV4::Compiler::Module jsModule
QV4::Compiler::JSUnitGenerator jsGenerator
QList< const QV4::CompiledData::Import * > imports
QQmlJS::Engine jsParserEngine
QV4::CompiledData::Location location
PoolList< EnumValue > * enumValues
QV4::CompiledData::Location location
QVector< Object * > _objects
bool resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, Object **object, bool onAssignment=false)
QList< const QV4::CompiledData::Import * > _imports
QList< Pragma * > _pragmas
bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QV4::CompiledData::Location &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride=nullptr)
QStringView asStringRef(QQmlJS::AST::Node *node)
static QTypeRevision extractVersion(QStringView string)
Object * bindingsTarget() const
IRBuilder(const QSet< QString > &illegalNames)
bool setId(const QQmlJS::SourceLocation &idLocation, QQmlJS::AST::Statement *value)
static bool isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement)
void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode)
QString stringAt(int index) const
void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode)
QQmlJS::MemoryPool * pool
void accept(QQmlJS::AST::Node *node)
bool visit(QQmlJS::AST::UiArrayMemberList *ast) override
Property * _propertyDeclaration
bool generateFromQml(const QString &code, const QString &url, Document *output)
QList< QQmlJS::DiagnosticMessage > errors
bool insideInlineComponent
static bool isStatementNodeScript(QQmlJS::AST::Statement *statement)
QV4::Compiler::JSUnitGenerator * jsGenerator
bool appendAlias(QQmlJS::AST::UiPublicMember *node)
quint32 registerString(const QString &str) const
QSet< QString > inlineComponentsNames
void tryGeneratingTranslationBinding(QStringView base, QQmlJS::AST::ArgumentList *args, QV4::CompiledData::Binding *binding)
static QString asString(QQmlJS::AST::UiQualifiedId *node)
void recordError(const QQmlJS::SourceLocation &location, const QString &description)
QString sanityCheckFunctionNames(Object *obj, const QSet< QString > &illegalNames, QQmlJS::SourceLocation *errorLocation)
QSet< QString > illegalNames
QStringView textRefAt(const QQmlJS::SourceLocation &loc) const
bool generateRuntimeFunctions(QmlIR::Object *object)
JSCodeGen(Document *document, const QSet< QString > &globalNames, QV4::Compiler::CodegenWarningInterface *iface=QV4::Compiler::defaultCodegenWarningInterface(), bool storeSourceLocations=false)
QVector< int > generateJSCodeForFunctionsAndBindings(const QList< CompiledFunctionOrExpression > &functions)
int indexOfDefaultPropertyOrAlias
QString appendEnum(Enum *enumeration)
void appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData)
void insertSorted(Binding *b)
QString appendBinding(Binding *b, bool isListBinding)
void appendInlineComponent(InlineComponent *ic)
bool defaultPropertyIsAlias
QString appendSignal(Signal *signal)
QString bindingAsString(Document *doc, int scriptIndex) const
void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QV4::CompiledData::Location &location)
Object * declarationsOverride
QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation)
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation)
PoolList< CompiledFunctionOrExpression > * functionsAndExpressions
void appendFunction(QmlIR::Function *f)
quint32 inheritedTypeNameIndex
QV4::CompiledData::Location locationOfIdProperty
Binding * findBinding(quint32 nameIndex) const
static bool initType(QV4::CompiledData::ParameterType *type, const IdGenerator &idGenerator, const QQmlJS::AST::Type *annotation)
static QV4::CompiledData::CommonType stringToBuiltinType(const QString &typeName)
@ FunctionSignatureBehavior
@ ListPropertyAssignBehavior
void generate(Document &output, const QV4::CompiledData::DependentTypesHasher &dependencyHasher=QV4::CompiledData::DependentTypesHasher())
PoolList< Parameter > * parameters
QStringList parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const