Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4executablecompilationunit.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qml/qqmlprivate.h"
5#include "qv4engine_p.h"
7
8#include <private/qv4engine_p.h>
9#include <private/qv4regexp_p.h>
10#include <private/qv4lookup_p.h>
11#include <private/qv4qmlcontext_p.h>
12#include <private/qv4identifiertable_p.h>
13#include <private/qv4objectproto_p.h>
14#include <private/qqmlengine_p.h>
15#include <private/qv4qobjectwrapper_p.h>
16#include <private/qqmlvaluetypewrapper_p.h>
17#include <private/qqmlscriptdata_p.h>
18#include <private/qv4module_p.h>
19#include <private/qv4compilationunitmapper_p.h>
20#include <private/qqmltypewrapper_p.h>
21#include <private/qv4resolvedtypereference_p.h>
22#include <private/qv4objectiterator_p.h>
23
24#include <QtQml/qqmlpropertymap.h>
25
26#include <QtCore/qfileinfo.h>
27#include <QtCore/qcryptographichash.h>
28
30
31namespace QV4 {
32
33ExecutableCompilationUnit::ExecutableCompilationUnit() = default;
34
35ExecutableCompilationUnit::ExecutableCompilationUnit(
36 QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit)
37 : m_compilationUnit(std::move(compilationUnit))
38{
39 constants = m_compilationUnit->constants;
40}
41
42ExecutableCompilationUnit::~ExecutableCompilationUnit()
43{
44 if (engine)
45 clear();
46}
47
49{
50 Value val = Value::fromReturnedValue(v);
52 if (val.isInt32())
53 result = QLatin1String("int ");
54 else if (val.isDouble())
55 result = QLatin1String("double ");
56 if (val.isEmpty())
57 result += QLatin1String("empty");
58 else
59 result += val.toQStringNoThrow();
60 return result;
61}
62
63static void dumpConstantTable(const StaticValue *constants, uint count)
64{
65 QDebug d = qDebug();
66 d.nospace() << Qt::right;
67 for (uint i = 0; i < count; ++i) {
68 d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
69 << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
70 }
71}
72
73void ExecutableCompilationUnit::populate()
74{
75 /* In general, we should use QV4::Scope whenever we allocate heap objects, and employ write barriers
76 for member variables pointing to heap objects. However, ExecutableCompilationUnit is special, as it
77 is always part of the root set. So instead of using scopde allocations and write barriers, we use a
78 slightly different approach: We temporarily block the gc from running. Afterwards, at the end of the
79 function we check whether the gc was already running, and mark the ExecutableCompilationUnit. This
80 ensures that all the newly allocated objects of the compilation unit will be marked in turn.
81 If the gc was not running, we don't have to do anything, because everything will be marked when the
82 gc starts marking the root set at the start of a run.
83 */
84 const CompiledData::Unit *data = m_compilationUnit->data;
85 GCCriticalSection<ExecutableCompilationUnit> criticalSection(engine, this);
86
87 Q_ASSERT(!runtimeStrings);
90 const quint32 stringCount = totalStringCount();
91 runtimeStrings = (QV4::Heap::String **)calloc(stringCount, sizeof(QV4::Heap::String*));
92 for (uint i = 0; i < stringCount; ++i)
93 runtimeStrings[i] = engine->newString(stringAt(i));
94
95 runtimeRegularExpressions
96 = new QV4::Value[data->regexpTableSize];
97 for (uint i = 0; i < data->regexpTableSize; ++i) {
98 const CompiledData::RegExp *re = data->regexpAt(i);
99 uint f = re->flags();
101 runtimeRegularExpressions[i] = QV4::RegExp::create(
102 engine, stringAt(re->stringIndex()), flags);
103 }
104
105 if (data->lookupTableSize) {
106 runtimeLookups = new QV4::Lookup[data->lookupTableSize];
107 memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
108 const CompiledData::Lookup *compiledLookups = data->lookupTable();
109 for (uint i = 0; i < data->lookupTableSize; ++i) {
110 QV4::Lookup *l = runtimeLookups + i;
111
113 = CompiledData::Lookup::Type(uint(compiledLookups[i].type()));
114 if (type == CompiledData::Lookup::Type_Getter)
116 else if (type == CompiledData::Lookup::Type_Setter)
118 else if (type == CompiledData::Lookup::Type_GlobalGetter)
120 else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
121 l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
122 l->forCall = compiledLookups[i].mode() == CompiledData::Lookup::Mode_ForCall;
123 l->nameIndex = compiledLookups[i].nameIndex();
124 }
125 }
126
127 if (data->jsClassTableSize) {
128 runtimeClasses
129 = (QV4::Heap::InternalClass **)calloc(data->jsClassTableSize,
130 sizeof(QV4::Heap::InternalClass *));
131
132 for (uint i = 0; i < data->jsClassTableSize; ++i) {
133 int memberCount = 0;
134 const CompiledData::JSClassMember *member
135 = data->jsClassAt(i, &memberCount);
136 runtimeClasses[i]
137 = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
138 for (int j = 0; j < memberCount; ++j, ++member)
139 runtimeClasses[i]
140 = runtimeClasses[i]->addMember(
141 engine->identifierTable->asPropertyKey(
142 runtimeStrings[member->nameOffset()]),
143 member->isAccessor()
146 }
147 }
148
149 runtimeFunctions.resize(data->functionTableSize);
150 static bool ignoreAotCompiledFunctions
151 = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER")
152 || !(engine->diskCacheOptions() & ExecutionEngine::DiskCache::AotNative);
153
154 const QQmlPrivate::AOTCompiledFunction *aotFunction
155 = ignoreAotCompiledFunctions ? nullptr : m_compilationUnit->aotCompiledFunctions;
156
157 auto advanceAotFunction = [&](int i) -> const QQmlPrivate::AOTCompiledFunction * {
158 if (aotFunction) {
159 if (aotFunction->functionPtr) {
160 if (aotFunction->functionIndex == i)
161 return aotFunction++;
162 } else {
163 aotFunction = nullptr;
164 }
165 }
166 return nullptr;
167 };
168
169 for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
170 const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
171 runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction,
172 advanceAotFunction(i));
173 }
174
175 Scope scope(engine);
176 Scoped<InternalClass> ic(scope);
177
178 runtimeBlocks.resize(data->blockTableSize);
179 for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
180 const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
181 ic = engine->internalClasses(EngineBase::Class_CallContext);
182
183 // first locals
184 const quint32_le *localsIndices = compiledBlock->localsTable();
185 for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
186 ic = ic->addMember(
187 engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]),
189 runtimeBlocks[i] = ic->d();
190 }
191
192 static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
193 if (showCode) {
194 qDebug() << "=== Constant table";
195 dumpConstantTable(constants, data->constantTableSize);
196 qDebug() << "=== String table";
197 for (uint i = 0, end = totalStringCount(); i < end; ++i)
198 qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
199 qDebug() << "=== Closure table";
200 for (uint i = 0; i < data->functionTableSize; ++i)
201 qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
202 qDebug() << "root function at index "
203 << (data->indexOfRootFunction != -1
204 ? data->indexOfRootFunction : 0);
205 }
206}
207
208Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const
209{
210 const CompiledData::Unit *data = m_compilationUnit->data;
211 Q_ASSERT(data);
213
214 Q_ASSERT(index < int(data->templateObjectTableSize));
215 if (!templateObjects.size())
216 templateObjects.resize(data->templateObjectTableSize);
217 Heap::Object *o = templateObjects.at(index);
218 if (o)
219 return o;
220
221 // create the template object
222 Scope scope(engine);
223 const CompiledData::TemplateObject *t = data->templateObjectAt(index);
224 Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
225 Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
226 ScopedValue s(scope);
227 for (uint i = 0; i < t->size; ++i) {
228 s = runtimeStrings[t->stringIndexAt(i)];
229 a->arraySet(i, s);
230 s = runtimeStrings[t->rawStringIndexAt(i)];
231 raw->arraySet(i, s);
232 }
233
234 ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
235 a->defineReadonlyProperty(QStringLiteral("raw"), raw);
236 ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
237
238 templateObjects[index] = a->objectValue()->d();
239 return templateObjects.at(index);
240}
241
242void ExecutableCompilationUnit::clear()
243{
244 delete [] imports;
245 imports = nullptr;
246
247 if (runtimeLookups) {
248 const uint lookupTableSize = unitData()->lookupTableSize;
249 for (uint i = 0; i < lookupTableSize; ++i)
250 runtimeLookups[i].releasePropertyCache();
251 }
252
253 delete [] runtimeLookups;
254 runtimeLookups = nullptr;
255
256 for (QV4::Function *f : std::as_const(runtimeFunctions))
257 f->destroy();
258 runtimeFunctions.clear();
259
260 free(runtimeStrings);
261 runtimeStrings = nullptr;
262 delete [] runtimeRegularExpressions;
263 runtimeRegularExpressions = nullptr;
264 free(runtimeClasses);
265 runtimeClasses = nullptr;
266}
267
268void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack) const
269{
270 const CompiledData::Unit *data = m_compilationUnit->data;
271
272 if (runtimeStrings) {
273 for (uint i = 0, end = totalStringCount(); i < end; ++i)
274 if (runtimeStrings[i])
275 runtimeStrings[i]->mark(markStack);
276 }
277 if (runtimeRegularExpressions) {
278 for (uint i = 0; i < data->regexpTableSize; ++i)
279 Value::fromStaticValue(runtimeRegularExpressions[i]).mark(markStack);
280 }
281 if (runtimeClasses) {
282 for (uint i = 0; i < data->jsClassTableSize; ++i)
283 if (runtimeClasses[i])
284 runtimeClasses[i]->mark(markStack);
285 }
286 for (QV4::Function *f : std::as_const(runtimeFunctions))
287 if (f && f->internalClass)
288 f->internalClass->mark(markStack);
289 for (QV4::Heap::InternalClass *c : std::as_const(runtimeBlocks))
290 if (c)
291 c->mark(markStack);
292
293 for (QV4::Heap::Object *o : std::as_const(templateObjects))
294 if (o)
295 o->mark(markStack);
296
297 if (runtimeLookups) {
298 for (uint i = 0; i < data->lookupTableSize; ++i)
299 runtimeLookups[i].markObjects(markStack);
300 }
301
302 if (auto mod = module())
303 mod->mark(markStack);
304}
305
306IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
307{
308 IdentifierHash namedObjectCache(engine);
309 const CompiledData::Object *component = objectAt(componentObjectIndex);
310 const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
311 for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
312 const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
313 namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->objectId());
314 }
315 Q_ASSERT(!namedObjectCache.isEmpty());
316 return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
317}
318
319QQmlRefPointer<ExecutableCompilationUnit> ExecutableCompilationUnit::create(
320 QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit, ExecutionEngine *engine)
321{
322 auto result = QQmlRefPointer<ExecutableCompilationUnit>(
323 new ExecutableCompilationUnit(std::move(compilationUnit)),
325 result->engine = engine;
326 return result;
327}
328
329Heap::Module *ExecutableCompilationUnit::instantiate()
330{
331 const CompiledData::Unit *data = m_compilationUnit->data;
332
333 if (isESModule() && module())
334 return module();
335
336 if (data->indexOfRootFunction < 0)
337 return nullptr;
338
340 if (!runtimeStrings)
341 populate();
342
343 Scope scope(engine);
344 Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
345
346 if (isESModule())
347 setModule(module->d());
348
349 const QStringList moduleRequests = m_compilationUnit->moduleRequests();
350 for (const QString &request: moduleRequests) {
351 const QUrl url(request);
352 const auto dependentModuleUnit = engine->loadModule(url, this);
353 if (engine->hasException)
354 return nullptr;
355 if (dependentModuleUnit.compiled)
356 dependentModuleUnit.compiled->instantiate();
357 }
358
359 ScopedString importName(scope);
360
361 const uint importCount = data->importEntryTableSize;
362 if (importCount > 0) {
363 imports = new const StaticValue *[importCount];
364 memset(imports, 0, importCount * sizeof(StaticValue *));
365 }
366 for (uint i = 0; i < importCount; ++i) {
367 const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
368 QUrl url = urlAt(entry.moduleRequest);
369 importName = runtimeStrings[entry.importName];
370
371 const auto module = engine->loadModule(url, this);
372 if (module.compiled) {
373 const Value *valuePtr = module.compiled->resolveExport(importName);
374 if (!valuePtr) {
375 QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
376 referenceErrorMessage += importName->toQString();
377 engine->throwReferenceError(
378 referenceErrorMessage, fileName(),
379 entry.location.line(), entry.location.column());
380 return nullptr;
381 }
382 imports[i] = valuePtr;
383 } else if (Value *value = module.native) {
384 const QString name = importName->toQString();
385 if (value->isNullOrUndefined()) {
387 errorMessage += QStringLiteral(" from ");
389 errorMessage += QStringLiteral(" is null");
391 return nullptr;
392 }
393
394 if (name == QStringLiteral("default")) {
395 imports[i] = value;
396 } else {
398 const auto fragment = engine->moduleForUrl(url, this);
399 if (fragment.native) {
400 imports[i] = fragment.native;
401 } else {
402 Scope scope(this->engine);
403 ScopedObject o(scope, value);
404 if (!o) {
405 QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
406 referenceErrorMessage += name;
407 referenceErrorMessage += QStringLiteral(" because ");
408 referenceErrorMessage += url.toString(QUrl::RemoveFragment);
409 referenceErrorMessage += QStringLiteral(" is not an object");
410 engine->throwReferenceError(
411 referenceErrorMessage, fileName(),
412 entry.location.line(), entry.location.column());
413 return nullptr;
414 }
415
417 const ScopedValue result(scope, o->get(key));
418 imports[i] = engine->registerNativeModule(url, result);
419 }
420 }
421 }
422 }
423
424 const auto throwReferenceError = [&](const CompiledData::ExportEntry &entry, const QString &importName) {
425 QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
426 referenceErrorMessage += importName;
427 engine->throwReferenceError(
428 referenceErrorMessage, fileName(),
429 entry.location.line(), entry.location.column());
430 };
431
432 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
433 const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
434 auto dependentModule = engine->loadModule(urlAt(entry.moduleRequest), this);
435 ScopedString importName(scope, runtimeStrings[entry.importName]);
436 if (const auto dependentModuleUnit = dependentModule.compiled) {
437 if (!dependentModuleUnit->resolveExport(importName)) {
438 throwReferenceError(entry, importName->toQString());
439 return nullptr;
440 }
441 } else if (const auto native = dependentModule.native) {
442 ScopedObject o(scope, native);
443 const ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(importName));
444 const ScopedValue result(scope, o->get(key));
445 if (result->isUndefined()) {
446 throwReferenceError(entry, importName->toQString());
447 return nullptr;
448 }
449 }
450 }
451
452 return module->d();
453}
454
455const Value *ExecutableCompilationUnit::resolveExportRecursively(
456 QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
457{
458 if (!module())
459 return nullptr;
460
461 for (const auto &entry: *resolveSet)
462 if (entry.module == this && entry.exportName->isEqualTo(exportName))
464
465 (*resolveSet) << ResolveSetEntry(this, exportName);
466
467 if (exportName->toQString() == QLatin1String("*"))
468 return &module()->self;
469
470 const CompiledData::Unit *data = m_compilationUnit->data;
471
472 Q_ASSERT(data);
474
475 Scope scope(engine);
476
477 if (auto localExport = lookupNameInExportTable(
478 data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
479 ScopedString localName(scope, runtimeStrings[localExport->localName]);
480 uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
481 if (index == UINT_MAX)
482 return nullptr;
483 if (index >= module()->scope->locals.size)
484 return &(imports[index - module()->scope->locals.size]->asValue<Value>());
485 return &module()->scope->locals[index];
486 }
487
488 if (auto indirectExport = lookupNameInExportTable(
489 data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
490 QUrl request = urlAt(indirectExport->moduleRequest);
491 auto dependentModule = engine->loadModule(request, this);
492 ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
493 if (dependentModule.compiled) {
494 return dependentModule.compiled->resolveExportRecursively(importName, resolveSet);
495 } else if (dependentModule.native) {
496 if (exportName->toQString() == QLatin1String("*"))
497 return dependentModule.native;
498 if (exportName->toQString() == QLatin1String("default"))
499 return nullptr;
500
501 request.setFragment(importName->toQString());
502 const auto fragment = engine->moduleForUrl(request);
503 if (fragment.native)
504 return fragment.native;
505
506 ScopedObject o(scope, dependentModule.native);
507 if (o)
508 return engine->registerNativeModule(request, o->get(importName));
509
510 return nullptr;
511 } else {
512 return nullptr;
513 }
514 }
515
516 if (exportName->toQString() == QLatin1String("default"))
517 return nullptr;
518
519 const Value *starResolution = nullptr;
520
521 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
522 const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
523 QUrl request = urlAt(entry.moduleRequest);
524 auto dependentModule = engine->loadModule(request, this);
525 const Value *resolution = nullptr;
526 if (dependentModule.compiled) {
527 resolution = dependentModule.compiled->resolveExportRecursively(
528 exportName, resolveSet);
529 } else if (dependentModule.native) {
530 if (exportName->toQString() == QLatin1String("*")) {
531 resolution = dependentModule.native;
532 } else if (exportName->toQString() != QLatin1String("default")) {
533 request.setFragment(exportName->toQString());
534 const auto fragment = engine->moduleForUrl(request);
535 if (fragment.native) {
536 resolution = fragment.native;
537 } else {
538 ScopedObject o(scope, dependentModule.native);
539 if (o)
540 resolution = engine->registerNativeModule(request, o->get(exportName));
541 }
542 }
543 }
544
545 // ### handle ambiguous
546 if (resolution) {
547 if (!starResolution) {
548 starResolution = resolution;
549 continue;
550 }
551 if (resolution != starResolution)
552 return nullptr;
553 }
554 }
555
556 return starResolution;
557}
558
559const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable(
560 const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
561{
562 const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
563 auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
564 return stringAt(lhs.exportName) < name->toQString();
565 });
566 if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
567 return nullptr;
568 return matchingExport;
569}
570
571void ExecutableCompilationUnit::getExportedNamesRecursively(
572 QStringList *names, QVector<const ExecutableCompilationUnit*> *exportNameSet,
573 bool includeDefaultExport) const
574{
575 if (exportNameSet->contains(this))
576 return;
577 exportNameSet->append(this);
578
579 const auto append = [names, includeDefaultExport](const QString &name) {
580 if (!includeDefaultExport && name == QLatin1String("default"))
581 return;
582 names->append(name);
583 };
584
585 const CompiledData::Unit *data = m_compilationUnit->data;
586
587 Q_ASSERT(data);
589
590 for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
591 const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
592 append(stringAt(entry.exportName));
593 }
594
595 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
596 const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
597 append(stringAt(entry.exportName));
598 }
599
600 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
601 const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
602 auto dependentModule = engine->loadModule(urlAt(entry.moduleRequest), this);
603 if (dependentModule.compiled) {
604 dependentModule.compiled->getExportedNamesRecursively(
605 names, exportNameSet, /*includeDefaultExport*/false);
606 } else if (dependentModule.native) {
607 Scope scope(engine);
608 ScopedObject o(scope, dependentModule.native);
609 ObjectIterator iterator(scope, o, ObjectIterator::EnumerableOnly);
610 while (true) {
611 ScopedValue val(scope, iterator.nextPropertyNameAsString());
612 if (val->isNull())
613 break;
614 append(val->toQString());
615 }
616 }
617 }
618}
619
620void ExecutableCompilationUnit::evaluate()
621{
623
624 QV4::Scope scope(engine);
625 QV4::Scoped<Module> mod(scope, module());
626 mod->evaluate();
627}
628
629void ExecutableCompilationUnit::evaluateModuleRequests()
630{
632
633 const QStringList moduleRequests = m_compilationUnit->moduleRequests();
634 for (const QString &request: moduleRequests) {
635 auto dependentModule = engine->loadModule(QUrl(request), this);
636 if (dependentModule.native)
637 continue;
638
639 if (engine->hasException)
640 return;
641
642 Q_ASSERT(dependentModule.compiled);
643 dependentModule.compiled->evaluate();
644 if (engine->hasException)
645 return;
646 }
647}
648
649QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
650{
651#if QT_CONFIG(translation)
652 using namespace CompiledData;
653 bool byId = false;
654 switch (binding->type()) {
655 case Binding::Type_TranslationById:
656 byId = true;
658 case Binding::Type_Translation: {
659 return translateFrom({ binding->value.translationDataIndex, byId });
660 }
661 default:
662 break;
663 }
664#endif
665 return m_compilationUnit->bindingValueAsString(binding);
666}
667
668QString ExecutableCompilationUnit::translateFrom(TranslationDataIndex index) const
669{
670#if !QT_CONFIG(translation)
671 return QString();
672#else
673 const CompiledData::TranslationData &translation = unitData()->translations()[index.index];
674
675 if (index.byId) {
676 QByteArray id = stringAt(translation.stringIndex).toUtf8();
677 return qtTrId(id.constData(), translation.number);
678 }
679
680 const auto fileContext = [this]() {
681 // This code must match that in the qsTr() implementation
682 const QString &path = fileName();
683 int lastSlash = path.lastIndexOf(QLatin1Char('/'));
684
685 QStringView context = (lastSlash > -1)
686 ? QStringView{ path }.mid(lastSlash + 1, path.size() - lastSlash - 5)
687 : QStringView();
688 return context.toUtf8();
689 };
690
691 const bool hasContext
694 if (hasContext) {
695 context = stringAt(translation.contextIndex).toUtf8();
696 } else {
697 auto pragmaTranslationContext = unitData()->translationContextIndex();
698 context = stringAt(*pragmaTranslationContext).toUtf8();
699 context = context.isEmpty() ? fileContext() : context;
700 }
701
702 QByteArray comment = stringAt(translation.commentIndex).toUtf8();
703 QByteArray text = stringAt(translation.stringIndex).toUtf8();
704 return QCoreApplication::translate(context, text, comment, translation.number);
705#endif
706}
707
708} // namespace QV4
709
\inmodule QtCore
Definition qbytearray.h:57
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtCore
void throwError(const QString &message)
Throws a run-time error (exception) with the given message.
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
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
Definition qstring.h:129
QByteArray toUtf8() const &
Definition qstring.h:634
\inmodule QtCore
Definition qurl.h:94
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
Definition qurl.cpp:2648
@ RemoveFragment
Definition qurl.h:112
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
#define this
Definition dialogs.cpp:9
b clear()
QString text
list append(new Employee("Blackpool", "Stephen"))
typename C::iterator iterator
Combined button and popup list for selecting options.
static void dumpConstantTable(const StaticValue *constants, uint count)
quint64 ReturnedValue
Scoped< Object > ScopedObject
Scoped< String > ScopedString
@ Attr_NotConfigurable
@ Attr_Data
@ Attr_Accessor
QTextStream & right(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight) on stream and returns stream.
static void * context
#define Q_FALLTHROUGH()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:164
GLsizei const GLfloat * v
[13]
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum type
GLbitfield flags
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint GLfloat * val
GLuint GLuint * names
GLuint entry
GLdouble GLdouble t
Definition qopenglext.h:243
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
static qreal component(const QPointF &point, unsigned int i)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QTextStreamManipulator qSetFieldWidth(int width)
Q_CORE_EXPORT QString qtTrId(const char *id, int n=-1)
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
Definition qurl.cpp:3517
if(qFloatDistance(a, b)<(1<< 7))
[0]
QUrl url("example.com")
[constructor-url-reference]
QObject::connect nullptr
QNetworkRequest request(url)
char * toString(const MyType &t)
[31]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
union QV4::CompiledData::Binding::@540 value
IdentifierTable * identifierTable
static Function * create(ExecutionEngine *engine, ExecutableCompilationUnit *unit, const CompiledData::Function *function, const QQmlPrivate::AOTCompiledFunction *aotFunction)
PropertyKey asPropertyKey(const Heap::String *str)
ReturnedValue(* globalGetter)(Lookup *l, ExecutionEngine *engine)
Definition qv4lookup_p.h:41
ReturnedValue(* qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject)
Definition qv4lookup_p.h:42
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
Definition qv4lookup_p.h:40
static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
Definition qv4lookup_p.h:43
static Heap::RegExp * create(ExecutionEngine *engine, const QString &pattern, uint flags=CompiledData::RegExp::RegExp_NoFlags)
ExecutionEngine * engine
QString toQString() const