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
qv4engine.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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#include <qv4engine_p.h>
4
5#include <private/qv4compileddata_p.h>
6#include <private/qv4codegen_p.h>
7#include <private/qqmljsdiagnosticmessage_p.h>
8
9#include <QtCore/QTextStream>
10#include <QDateTime>
11#include <QDir>
12#include <QFileInfo>
13#include <QLoggingCategory>
14#if QT_CONFIG(regularexpression)
15#include <QRegularExpression>
16#endif
17#include <QtCore/QTimeZone>
18#include <QtCore/qiterable.h>
19
20#include <qv4qmlcontext_p.h>
21#include <qv4value_p.h>
22#include <qv4object_p.h>
23#include <qv4objectproto_p.h>
24#include <qv4objectiterator_p.h>
25#include <qv4setiterator_p.h>
26#include <qv4mapiterator_p.h>
27#include <qv4arrayiterator_p.h>
28#include <qv4arrayobject_p.h>
29#include <qv4booleanobject_p.h>
30#include <qv4globalobject_p.h>
31#include <qv4errorobject_p.h>
32#include <qv4functionobject_p.h>
33#include "qv4function_p.h"
34#include <qv4mathobject_p.h>
35#include <qv4numberobject_p.h>
36#include <qv4regexpobject_p.h>
37#include <qv4regexp_p.h>
38#include "qv4symbol_p.h"
39#include "qv4setobject_p.h"
40#include "qv4mapobject_p.h"
41#include <qv4variantobject_p.h>
42#include <qv4runtime_p.h>
43#include <private/qv4mm_p.h>
45#include <qv4dateobject_p.h>
46#include <qv4jsonobject_p.h>
47#include <qv4stringobject_p.h>
49#include "qv4debugging_p.h"
50#include "qv4profiling_p.h"
52#include "qv4iterator_p.h"
53#include "qv4stringiterator_p.h"
55#include "qv4reflect_p.h"
56#include "qv4proxy_p.h"
57#include "qv4stackframe_p.h"
58#include "qv4stacklimits_p.h"
59#include "qv4atomics_p.h"
60#include "qv4urlobject_p.h"
61#include "qv4variantobject_p.h"
62#include "qv4sequenceobject_p.h"
63#include "qv4qobjectwrapper_p.h"
65#include "qv4memberdata_p.h"
66#include "qv4arraybuffer_p.h"
67#include "qv4dataview_p.h"
68#include "qv4promiseobject_p.h"
69#include "qv4typedarray_p.h"
70#include <private/qjsvalue_p.h>
71#include <private/qqmltypewrapper_p.h>
72#include <private/qqmlvaluetypewrapper_p.h>
73#include <private/qqmlvaluetype_p.h>
74#include <private/qqmllistwrapper_p.h>
75#include <private/qqmllist_p.h>
76#include <private/qqmltypeloader_p.h>
77#include <private/qqmlbuiltinfunctions_p.h>
78#if QT_CONFIG(qml_locale)
79#include <private/qqmllocale_p.h>
80#endif
81#if QT_CONFIG(qml_xml_http_request)
82#include <private/qv4domerrors_p.h>
83#include <private/qqmlxmlhttprequest_p.h>
84#endif
85#include <private/qv4sqlerrors_p.h>
86#include <qqmlfile.h>
87#include <qmetatype.h>
88#include <qsequentialiterable.h>
89
90#include <private/qqmlengine_p.h>
91
92#ifdef V4_USE_VALGRIND
93#include <valgrind/memcheck.h>
94#endif
95
97
98DEFINE_BOOL_CONFIG_OPTION(disableDiskCache, QML_DISABLE_DISK_CACHE);
99DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE);
100
101using namespace QV4;
102
103// While engineSerial is odd the statics haven't been initialized. The engine that receives ID 1
104// initializes the statics and sets engineSerial to 2 afterwards.
105// Each engine does engineSerial.fetchAndAddOrdered(2) on creation. Therefore engineSerial stays
106// odd while the statics are being initialized, and stays even afterwards.
107// Any further engines created while the statics are being initialized busy-wait until engineSerial
108// is even.
110int ExecutionEngine::s_maxCallDepth = -1;
111int ExecutionEngine::s_jitCallCountThreshold = 3;
112int ExecutionEngine::s_maxJSStackSize = 4 * 1024 * 1024;
113int ExecutionEngine::s_maxGCStackSize = 2 * 1024 * 1024;
114
116{
117 return b->engine()->throwTypeError();
118}
119
120
121template <typename ReturnType>
123{
124 const QVariant variant = value.toVariant();
125 return variant.metaType() == QMetaType::fromType<QJSValue>()
126 ? ReturnType()
127 : variant.value<ReturnType>();
128}
129
134
135namespace {
136void createNewIteratorIfNonExisting(void **iterator) {
137 if (*iterator == nullptr)
138 *iterator = new JSArrayIterator;
139}
140}
141
143{
144 // set up some functions so that non-array QSequentialIterables do not crash
145 // but instead appear as an empty sequence
146
147 using namespace QtMetaContainerPrivate;
149 iface.sizeFn = [](const void *) { return qsizetype(0); };
150 iface.valueAtIndexFn = [](const void *, qsizetype, void *) {};
151 iface.createIteratorFn = [](void *, QMetaSequenceInterface::Position) -> void * {
152 return nullptr;
153 };
154 iface.advanceIteratorFn = [](void *, qsizetype) {};
155 iface.compareIteratorFn = [](const void *, const void *) {
156 return true; /*all iterators are nullptr*/
157 };
158 iface.destroyIteratorFn = [](const void *) {};
159 iface.copyIteratorFn = [](void *, const void *) {};
160 iface.diffIteratorFn = [](const void *, const void *) { return qsizetype(0); };
161 return iface;
162}
163
165{
166 using namespace QtMetaContainerPrivate;
168 iface.valueMetaType = QtPrivate::qMetaTypeInterfaceForType<QVariant>();
169 iface.iteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability;
170 iface.addRemoveCapabilities = CanAddAtEnd;
171 iface.sizeFn = [](const void *p) -> qsizetype {
172 return static_cast<QJSValue const *>(p)->property(QString::fromLatin1("length")).toInt();
173 };
174
175 /* Lifetime management notes:
176 * valueAtIndexFn and valueAtIteratorFn return a pointer to a JSValue allocated via
177 * QMetaType::create Because we set QVariantConstructionFlags::ShouldDeleteVariantData,
178 * QSequentialIterable::at and QSequentialIterable::operator*() will free that memory
179 */
180
181 iface.valueAtIndexFn = [](const void *iterable, qsizetype index, void *dataPtr) -> void {
182 auto *data = static_cast<QVariant *>(dataPtr);
183 *data = static_cast<QJSValue const *>(iterable)->property(quint32(index)).toVariant();
184 };
185 iface.createIteratorFn = [](void *iterable, QMetaSequenceInterface::Position pos) {
186 void *iterator = nullptr;
187 createNewIteratorIfNonExisting(&iterator);
188 auto jsArrayIterator = static_cast<JSArrayIterator *>(iterator);
189 jsArrayIterator->index = 0;
190 jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
191 if (pos == QMetaSequenceInterface::AtEnd) {
192 auto length = static_cast<QJSValue const *>(iterable)->property(
193 QString::fromLatin1("length")).toInt();
194 jsArrayIterator->index = quint32(length);
195 }
196 return iterator;
197 };
198 iface.createConstIteratorFn = [](const void *iterable, QMetaSequenceInterface::Position pos) {
199 void *iterator = nullptr;
200 createNewIteratorIfNonExisting(&iterator);
201 auto jsArrayIterator = static_cast<JSArrayIterator *>(iterator);
202 jsArrayIterator->index = 0;
203 jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
204 if (pos == QMetaSequenceInterface::AtEnd) {
205 auto length = static_cast<QJSValue const *>(iterable)->property(
206 QString::fromLatin1("length")).toInt();
207 jsArrayIterator->index = quint32(length);
208 }
209 return iterator;
210 };
211 iface.advanceIteratorFn = [](void *iterator, qsizetype advanceBy) {
212 static_cast<JSArrayIterator *>(iterator)->index += quint32(advanceBy);
213 };
214 iface.advanceConstIteratorFn = [](void *iterator, qsizetype advanceBy) {
215 static_cast<JSArrayIterator *>(iterator)->index += quint32(advanceBy);
216 };
217 iface.valueAtIteratorFn = [](const void *iterator, void *dataPtr) -> void {
218 const auto *arrayIterator = static_cast<const JSArrayIterator *>(iterator);
219 const QJSValue *jsArray = arrayIterator->data;
220 auto *data = static_cast<QVariant *>(dataPtr);
221 *data = jsArray->property(arrayIterator->index).toVariant();
222 };
223 iface.valueAtConstIteratorFn = [](const void *iterator, void *dataPtr) -> void {
224 const auto *arrayIterator = static_cast<const JSArrayIterator *>(iterator);
225 const QJSValue *jsArray = arrayIterator->data;
226 auto *data = static_cast<QVariant *>(dataPtr);
227 *data = jsArray->property(arrayIterator->index).toVariant();
228 };
229 iface.destroyIteratorFn = [](const void *iterator) {
230 delete static_cast<const JSArrayIterator *>(iterator);
231 };
232 iface.destroyConstIteratorFn = [](const void *iterator) {
233 delete static_cast<const JSArrayIterator *>(iterator);
234 };
235 iface.compareIteratorFn = [](const void *p, const void *other) {
236 auto this_ = static_cast<const JSArrayIterator *>(p);
237 auto that_ = static_cast<const JSArrayIterator *>(other);
238 return this_->index == that_->index && this_->data == that_->data;
239 };
240 iface.compareConstIteratorFn = [](const void *p, const void *other) {
241 auto this_ = static_cast<const JSArrayIterator *>(p);
242 auto that_ = static_cast<const JSArrayIterator *>(other);
243 return this_->index == that_->index && this_->data == that_->data;
244 };
245 iface.copyIteratorFn = [](void *iterator, const void *otherIterator) {
246 auto *otherIter = (static_cast<JSArrayIterator const *>(otherIterator));
247 static_cast<JSArrayIterator *>(iterator)->index = otherIter->index;
248 static_cast<JSArrayIterator *>(iterator)->data = otherIter->data;
249 };
250 iface.copyConstIteratorFn = [](void *iterator, const void *otherIterator) {
251 auto *otherIter = (static_cast<JSArrayIterator const *>(otherIterator));
252 static_cast<JSArrayIterator *>(iterator)->index = otherIter->index;
253 static_cast<JSArrayIterator *>(iterator)->data = otherIter->data;
254 };
255 iface.diffIteratorFn = [](const void *iterator, const void *otherIterator) -> qsizetype {
256 const auto *self = static_cast<const JSArrayIterator *>(iterator);
257 const auto *other = static_cast<const JSArrayIterator *>(otherIterator);
258 return self->index - other->index;
259 };
260 iface.diffConstIteratorFn = [](const void *iterator, const void *otherIterator) -> qsizetype {
261 const auto *self = static_cast<const JSArrayIterator *>(iterator);
262 const auto *other = static_cast<const JSArrayIterator *>(otherIterator);
263 return self->index - other->index;
264 };
265 iface.addValueFn = [](void *iterable, const void *data, QMetaSequenceInterface::Position) {
266 auto *jsvalue = static_cast<QJSValue *>(iterable);
267 QV4::Scope scope(QJSValuePrivate::engine(jsvalue));
268 QV4::ScopedArrayObject a(scope, QJSValuePrivate::asManagedType<QV4::ArrayObject>(jsvalue));
269 QV4::ScopedValue v(scope, scope.engine->fromVariant(*static_cast<const QVariant *>(data)));
270 if (!a)
271 return;
272 int len = a->getLength();
273 a->setIndexed(len, v, QV4::Object::DoNotThrow);
274 };
275 return iface;
276}
277
279 using namespace QtMetaTypePrivate;
280 using namespace QtMetaContainerPrivate;
281
282
283 if (!value.isArray()) {
284 static QMetaSequenceInterface emptySequence = emptySequenceInterface();
285 return QSequentialIterable(QMetaSequence(&emptySequence), nullptr);
286 }
287
288 static QMetaSequenceInterface sequence = sequenceInterface();
289 return QSequentialIterable(QMetaSequence(&sequence), &value);
290}
291
292void ExecutionEngine::initializeStaticMembers()
293{
294 bool ok = false;
295
296 const int envMaxJSStackSize = qEnvironmentVariableIntValue("QV4_JS_MAX_STACK_SIZE", &ok);
297 if (ok && envMaxJSStackSize > 0)
298 s_maxJSStackSize = envMaxJSStackSize;
299
300 const int envMaxGCStackSize = qEnvironmentVariableIntValue("QV4_GC_MAX_STACK_SIZE", &ok);
301 if (ok && envMaxGCStackSize > 0)
302 s_maxGCStackSize = envMaxGCStackSize;
303
304 if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) {
305 s_maxCallDepth = std::numeric_limits<qint32>::max();
306 } else {
307 ok = false;
308 s_maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
309 if (!ok || s_maxCallDepth <= 0)
310 s_maxCallDepth = -1;
311 }
312
313 ok = false;
314 s_jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
315 if (!ok)
316 s_jitCallCountThreshold = 3;
317 if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
318 s_jitCallCountThreshold = std::numeric_limits<int>::max();
319
320 qMetaTypeId<QJSValue>();
321 qMetaTypeId<QList<int> >();
322
323 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
324 QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
325 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
326 QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
327 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
328 QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
329 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QSequentialIterable>())
330 QMetaType::registerConverter<QJSValue, QSequentialIterable>(jsvalueToSequence);
331}
332
334 : executableAllocator(new QV4::ExecutableAllocator)
335 , regExpAllocator(new QV4::ExecutableAllocator)
336 , bumperPointerAllocator(new WTF::BumpPointerAllocator)
337 , jsStack(new WTF::PageAllocation)
338 , gcStack(new WTF::PageAllocation)
339 , globalCode(nullptr)
340 , publicEngine(jsEngine)
341 , m_engineId(engineSerial.fetchAndAddOrdered(2))
342 , regExpCache(nullptr)
343 , m_multiplyWrappedQObjects(nullptr)
344#if QT_CONFIG(qml_jit)
345 , m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
346#endif
347#if QT_CONFIG(qml_xml_http_request)
348 , m_xmlHttpRequestData(nullptr)
349#endif
350 , m_qmlEngine(nullptr)
351{
352 if (m_engineId == 1) {
353 initializeStaticMembers();
354 engineSerial.storeRelease(2); // make it even
355 } else if (Q_UNLIKELY(m_engineId & 1)) {
356 // This should be rare. You usually don't create lots of engines at the same time.
357 while (engineSerial.loadAcquire() & 1) {
359 }
360 }
361
362 if (s_maxCallDepth < 0) {
363 const StackProperties stack = stackProperties();
364 cppStackBase = stack.base;
365 cppStackLimit = stack.softLimit;
366 } else {
367 callDepth = 0;
368 }
369
370 // We allocate guard pages around our stacks.
371 const size_t guardPages = 2 * WTF::pageSize();
372
374 // we don't want to run the gc while the initial setup is not done; not even in aggressive mode
375 GCCriticalSection gcCriticalSection(this);
376 // reserve space for the JS stack
377 // we allow it to grow to a bit more than m_maxJSStackSize, as we can overshoot due to ScopedValues
378 // allocated outside of JIT'ed methods.
379 *jsStack = WTF::PageAllocation::allocate(
380 s_maxJSStackSize + 256*1024 + guardPages, WTF::OSAllocator::JSVMStackPages,
381 /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
382 jsStackBase = (Value *)jsStack->base();
383#ifdef V4_USE_VALGRIND
384 VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, m_maxJSStackSize + 256*1024);
385#endif
386
388
389 *gcStack = WTF::PageAllocation::allocate(
390 s_maxGCStackSize + guardPages, WTF::OSAllocator::JSVMStackPages,
391 /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
392
395 globalObject = static_cast<Object *>(jsAlloca(1));
401
402 // set up stack limits
403 jsStackLimit = jsStackBase + s_maxJSStackSize/sizeof(Value);
404
406
407 memset(classes, 0, sizeof(classes));
409 classes[Class_Empty]->init(this);
410
411 classes[Class_MemberData] = classes[Class_Empty]->changeVTable(QV4::MemberData::staticVTable());
412 classes[Class_SimpleArrayData] = classes[Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
413 classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
414 classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
415 classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
416 classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable());
417
418 Scope scope(this);
419 Scoped<InternalClass> ic(scope);
420 ic = classes[Class_Empty]->changeVTable(QV4::Object::staticVTable());
422 classes[Class_Object] = ic->changePrototype(objectPrototype()->d());
423 classes[Class_QmlContextWrapper] = classes[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
424
425 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
426 jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic->d(), /*init =*/ false);
427 classes[Class_String] = classes[Class_Empty]->changeVTable(QV4::String::staticVTable())->changePrototype(stringPrototype()->d());
428 Q_ASSERT(stringPrototype()->d() && classes[Class_String]->prototype);
429
431 classes[Class_Symbol] = classes[EngineBase::Class_Empty]->changeVTable(QV4::Symbol::staticVTable())->changePrototype(symbolPrototype()->d());
432
483
484 jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
485 jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
486 jsSymbols[Symbol_iterator] = Symbol::create(this, QStringLiteral("@Symbol.iterator"));
487 jsSymbols[Symbol_match] = Symbol::create(this, QStringLiteral("@Symbol.match"));
488 jsSymbols[Symbol_replace] = Symbol::create(this, QStringLiteral("@Symbol.replace"));
489 jsSymbols[Symbol_search] = Symbol::create(this, QStringLiteral("@Symbol.search"));
490 jsSymbols[Symbol_species] = Symbol::create(this, QStringLiteral("@Symbol.species"));
491 jsSymbols[Symbol_split] = Symbol::create(this, QStringLiteral("@Symbol.split"));
492 jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
493 jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
494 jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
495 jsSymbols[Symbol_revokableProxy] = Symbol::create(this, QStringLiteral("@Proxy.revokableProxy"));
496
497 ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
498 Q_ASSERT(ic->d()->prototype);
499 ic = ic->addMember(id_length()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
500 Q_ASSERT(ic->d()->prototype);
502 classes[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d());
504
505 Scoped<InternalClass> argsClass(scope);
506 argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype());
507 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
508 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
510 argsClass = newInternalClass(StrictArgumentsObject::staticVTable(), objectPrototype());
511 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
512 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
514
515 *static_cast<Value *>(globalObject) = newObject();
518
519 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
520 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly);
521 classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
522 Q_ASSERT(classes[Class_StringObject]->verifyIndex(id_length()->propertyKey(), Heap::StringObject::LengthPropertyIndex));
523
524 classes[Class_SymbolObject] = newInternalClass(QV4::SymbolObject::staticVTable(), symbolPrototype());
525
529
530#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
531 InternalClassEntry *index = nullptr;
532#else
533 InternalClassEntry _index;
534 auto *index = &_index;
535#endif
536 ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
537 auto addProtoHasInstance = [&] {
538 // Add an invalid prototype slot, so that all function objects have the same layout
539 // This helps speed up instanceof operations and other things where we need to query
540 // prototype property (as we always know it's location)
541 ic = ic->addMember(id_prototype()->propertyKey(), Attr_Invalid, index);
542 Q_ASSERT(index->index == Heap::FunctionObject::Index_Prototype);
543 // add an invalid @hasInstance slot, so that we can quickly track whether the
544 // hasInstance method has been reimplemented. This is required for a fast
545 // instanceof implementation
546 ic = ic->addMember(symbol_hasInstance()->propertyKey(), Attr_Invalid, index);
547 Q_ASSERT(index->index == Heap::FunctionObject::Index_HasInstance);
548 };
549 addProtoHasInstance();
551 ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
552 addProtoHasInstance();
553 classes[Class_FunctionObject] = ic->d();
554 ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, index);
556 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, index);
558 classes[Class_ArrowFunction] = ic->changeVTable(ArrowFunction::staticVTable());
559 ic = ic->changeVTable(MemberFunction::staticVTable());
560 classes[Class_MemberFunction] = ic->d();
561 ic = ic->changeVTable(GeneratorFunction::staticVTable());
563 ic = ic->changeVTable(MemberGeneratorFunction::staticVTable());
565
566 ic = ic->changeMember(id_prototype()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
567 ic = ic->changeVTable(ScriptFunction::staticVTable());
568 classes[Class_ScriptFunction] = ic->d();
569 ic = ic->changeVTable(ConstructorFunction::staticVTable());
571
573 Q_ASSERT(index->index == Heap::FunctionObject::Index_ProtoConstructor);
574
576 classes[Class_GeneratorObject] = newInternalClass(QV4::GeneratorObject::staticVTable(), generatorPrototype());
577
578 ScopedString str(scope);
579 classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
580 ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
581 ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, index);
584 classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
585
588 classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, index);
590
591 ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
592 ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, index);
595 ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
597 ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
598 classes[Class_ErrorObject] = ic->d();
602 ic = newInternalClass(Object::staticVTable(), objectPrototype());
603 ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
605 ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
607 classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
609
610 classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
611 classes[Class_ProxyFunctionObject] = classes[Class_Empty]->changeVTable(ProxyFunctionObject::staticVTable());
612
614
623
625 Q_ASSERT(variantPrototype()->getPrototypeOf() == objectPrototype()->d());
626
627 ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this));
629
648
649 ic = newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype());
651 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
653 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
655 ic = newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype());
657 ic = newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype());
659
660 //
661 // url
662 //
663
668
669 str = newString(QStringLiteral("get [Symbol.species]"));
671
672 static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
673 static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
674 static_cast<SymbolPrototype *>(symbolPrototype())->init(this, symbolCtor());
675 static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
676 static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
677 static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
679 static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
680 static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
682 static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
683 static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
684 static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
688 static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
689 static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
690 static_cast<UrlPrototype *>(urlPrototype())->init(this, urlCtor());
692
693 static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
694 static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
695 static_cast<MapIteratorPrototype *>(mapIteratorPrototype())->init(this);
696 static_cast<SetIteratorPrototype *>(setIteratorPrototype())->init(this);
697 static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this);
699
700 static_cast<VariantPrototype *>(variantPrototype())->init();
701
703
706 static_cast<WeakMapPrototype *>(weakMapPrototype())->init(this, weakMapCtor());
707
710 static_cast<MapPrototype *>(mapPrototype())->init(this, mapCtor());
711
714 static_cast<WeakSetPrototype *>(weakSetPrototype())->init(this, weakSetCtor());
715
718 static_cast<SetPrototype *>(setPrototype())->init(this, setCtor());
719
720 //
721 // promises
722 //
723
726 static_cast<PromisePrototype *>(promisePrototype())->init(this, promiseCtor());
727
728 // typed arrays
729
733
737
740 static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
741 jsObjects[ValueTypeProto] = (Heap::Base *) nullptr;
744
748 ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
749
750 for (int i = 0; i < NTypedArrayTypes; ++i) {
751 static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(this, Heap::TypedArray::Type(i));
752 static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
753 typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
754 }
755
756 //
757 // set up the global object
758 //
759 rootContext()->d()->activation.set(scope.engine, globalObject->d());
761
765 FunctionObject *numberObject = numberCtor();
766 globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
782
790
791 for (int i = 0; i < NTypedArrayTypes; ++i)
793 ScopedObject o(scope);
799
801 globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN()));
803
804
807
808 // ES6: 20.1.2.12 & 20.1.2.13:
809 // parseInt and parseFloat must be the same FunctionObject on the global &
810 // Number object.
811 {
812 QString piString(QStringLiteral("parseInt"));
813 QString pfString(QStringLiteral("parseFloat"));
814 Scope scope(this);
815 ScopedString pi(scope, newIdentifier(piString));
816 ScopedString pf(scope, newIdentifier(pfString));
819 globalObject->defineDefaultProperty(piString, parseIntFn);
820 globalObject->defineDefaultProperty(pfString, parseFloatFn);
821 numberObject->defineDefaultProperty(piString, parseIntFn);
822 numberObject->defineDefaultProperty(pfString, parseFloatFn);
823 }
824
833
835 scope,
837 t->defineReadonlyProperty(id_length(), Value::fromInt32(0));
838 t->setInternalClass(t->internalClass()->cryopreserved());
840
841 ScopedProperty pd(scope);
842 pd->value = thrower();
843 pd->set = thrower();
846
848
849 m_delayedCallQueue.init(this);
850 isInitialized = true;
851}
852
854{
855 for (auto val : nativeModules) {
857 }
858 nativeModules.clear();
859 qDeleteAll(m_extensionData);
862 delete identifierTable;
863 delete memoryManager;
864
865 for (const auto &cu : std::as_const(m_compilationUnits)) {
866 Q_ASSERT(cu->engine == this);
867 cu->clear();
868 cu->engine = nullptr;
869 }
870 m_compilationUnits.clear();
871
873 delete regExpCache;
874 delete regExpAllocator;
875 delete executableAllocator;
876 jsStack->deallocate();
877 delete jsStack;
878 gcStack->deallocate();
879 delete gcStack;
880
881#if QT_CONFIG(qml_xml_http_request)
882 qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
883 m_xmlHttpRequestData = nullptr;
884#endif
885}
886
887#if QT_CONFIG(qml_debug)
889{
890 Q_ASSERT(!m_debugger);
891 m_debugger.reset(debugger);
892}
893
895{
896 Q_ASSERT(!m_profiler);
897 m_profiler.reset(profiler);
898}
899#endif // QT_CONFIG(qml_debug)
900
902{
903 Scope scope(this);
904 Scoped<ExecutionContext> r(scope, memoryManager->allocManaged<ExecutionContext>());
905 r->d_unchecked()->init(Heap::ExecutionContext::Type_GlobalContext);
906 r->d()->activation.set(this, globalObject->d());
909 jsObjects[IntegerNull] = Encode((int)0);
910}
911
918
920{
921 Scope scope(this);
922 Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable));
923 return ic->changePrototype(prototype ? prototype->d() : nullptr);
924}
925
927{
928 return memoryManager->allocate<Object>();
929}
930
932{
933 return memoryManager->allocObject<Object>(internalClass);
934}
935
940
942{
943 Scope scope(this);
945 s->toPropertyKey();
946 return s->d();
947}
948
949Heap::Object *ExecutionEngine::newStringObject(const String *string)
950{
952}
953
958
960{
962}
963
965{
967}
968
970{
971 Scope scope(this);
973
974 if (count) {
975 if (count < 0x1000)
976 object->arrayReserve(count);
977 object->setArrayLengthUnchecked(count);
978 }
979 return object->d();
980}
981
983{
984 Scope scope(this);
986
987 if (length) {
988 size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
990 d->init();
991 d->type = Heap::ArrayData::Simple;
992 d->offset = 0;
993 d->values.alloc = length;
994 d->values.size = length;
995 // this doesn't require a write barrier, things will be ok, when the new array data gets inserted into
996 // the parent object
997 memcpy(&d->values.values, values, length*sizeof(Value));
998 a->d()->arrayData.set(this, d);
999 a->setArrayLengthUnchecked(length);
1000 }
1001 return a->d();
1002}
1003
1008
1013
1018
1023
1025{
1027}
1028
1030{
1032}
1033
1035 QDate date, Heap::Object *parent, int index, uint flags)
1036{
1038 date, parent, index, Heap::ReferenceObject::Flags(flags));
1039}
1040
1042 QTime time, Heap::Object *parent, int index, uint flags)
1043{
1045 time, parent, index, Heap::ReferenceObject::Flags(flags));
1046}
1047
1049 QDateTime dateTime, Heap::Object *parent, int index, uint flags)
1050{
1052 dateTime, parent, index, Heap::ReferenceObject::Flags(flags));
1053}
1054
1056{
1057 Scope scope(this);
1058 Scoped<RegExp> re(scope, RegExp::create(this, pattern, static_cast<CompiledData::RegExp::Flags>(flags)));
1059 return newRegExpObject(re);
1060}
1061
1063{
1064 return memoryManager->allocate<RegExpObject>(re);
1065}
1066
1067#if QT_CONFIG(regularexpression)
1068Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
1069{
1070 return memoryManager->allocate<RegExpObject>(re);
1071}
1072#endif
1073
1075{
1076 return memoryManager->allocate<UrlObject>();
1077}
1078
1080{
1081 Scope scope(this);
1082 Scoped<UrlObject> urlObject(scope, newUrlObject());
1083 urlObject->setUrl(url);
1084 return urlObject->d();
1085}
1086
1087Heap::UrlSearchParamsObject *ExecutionEngine::newUrlSearchParamsObject()
1088{
1090}
1091
1093{
1094 return ErrorObject::create<ErrorObject>(this, value, errorCtor());
1095}
1096
1098{
1099 return ErrorObject::create<ErrorObject>(this, message);
1100}
1101
1103{
1104 return ErrorObject::create<SyntaxErrorObject>(this, message);
1105}
1106
1108{
1109 return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
1110}
1111
1112
1114{
1115 return ErrorObject::create<ReferenceErrorObject>(this, message);
1116}
1117
1119{
1120 return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
1121}
1122
1123
1125{
1126 return ErrorObject::create<TypeErrorObject>(this, message);
1127}
1128
1130{
1131 return ErrorObject::create<RangeErrorObject>(this, message);
1132}
1133
1135{
1136 return ErrorObject::create<URIErrorObject>(this, message, uRIErrorCtor());
1137}
1138
1140{
1141 if (!m_reactionHandler) {
1142 m_reactionHandler.reset(new Promise::ReactionHandler);
1143 }
1144
1145 Scope scope(this);
1146 Scoped<PromiseObject> object(scope, memoryManager->allocate<PromiseObject>(this));
1147 return object->d();
1148}
1149
1150Heap::Object *ExecutionEngine::newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability)
1151{
1152 if (!m_reactionHandler) {
1153 m_reactionHandler.reset(new Promise::ReactionHandler);
1154 }
1155
1156 Scope scope(this);
1157 Scoped<CapabilitiesExecutorWrapper> executor(scope, memoryManager->allocate<CapabilitiesExecutorWrapper>());
1158 executor->d()->capabilities.set(this, capability->d());
1160
1161 ScopedObject object(scope, thisObject->callAsConstructor(executor, 1));
1162 return object->d();
1163}
1164
1166{
1167 Q_ASSERT(m_reactionHandler);
1168 return m_reactionHandler.data();
1169}
1170
1172{
1173 return ErrorObject::create<URIErrorObject>(this, message);
1174}
1175
1177{
1178 return ErrorObject::create<EvalErrorObject>(this, message);
1179}
1180
1181Heap::Object *ExecutionEngine::newVariantObject(const QMetaType type, const void *data)
1182{
1184}
1185
1187{
1188 Scope scope(this);
1190 return obj->d();
1191}
1192
1194{
1195 return memoryManager->allocate<MapIteratorObject>(o->d(), this);
1196}
1197
1199{
1200 return memoryManager->allocate<SetIteratorObject>(o->d(), this);
1201}
1202
1204{
1205 return memoryManager->allocate<ArrayIteratorObject>(o->d(), this);
1206}
1207
1208Heap::QmlContext *ExecutionEngine::qmlContext() const
1209{
1210 return currentStackFrame
1211 ? static_cast<Heap::QmlContext *>(qmlContext(currentContext()->d()))
1212 : nullptr;
1213}
1214
1216{
1217 Heap::QmlContext *ctx = qmlContext();
1218 if (!ctx)
1219 return nullptr;
1220
1221 return ctx->qml()->scopeObject;
1222}
1223
1224QQmlRefPointer<QQmlContextData> ExecutionEngine::callingQmlContext() const
1225{
1226 Heap::QmlContext *ctx = qmlContext();
1227 if (!ctx)
1228 return nullptr;
1229
1230 return ctx->qml()->context;
1231}
1232
1234{
1235 StackTrace stack;
1236
1238 while (f && frameLimit) {
1240 frame.source = f->source();
1241 frame.function = f->function();
1242 frame.line = f->lineNumber();
1243
1244 stack.append(frame);
1245 if (f->isJSTypesFrame()) {
1246 if (static_cast<JSTypesStackFrame *>(f)->isTailCalling()) {
1248 frame.function = QStringLiteral("[elided tail calls]");
1249 stack.append(frame);
1250 }
1251 }
1252 --frameLimit;
1253 f = f->parentFrame();
1254 }
1255
1256 return stack;
1257}
1258
1259/* Helper and "C" linkage exported function to format a GDBMI stacktrace for
1260 * invocation by a debugger.
1261 * Sample GDB invocation: print qt_v4StackTrace((void*)0x7fffffffb290)
1262 * Sample CDB invocation: .call Qt5Qmld!qt_v4StackTrace(0x7fffffffb290) ; gh
1263 * Note: The helper is there to suppress MSVC warning 4190 about anything
1264 * with UDT return types in a "C" linkage function. */
1265
1266static inline char *v4StackTrace(const ExecutionContext *context)
1267{
1270 str << "stack=[";
1271 if (context && context->engine()) {
1272 const QVector<StackFrame> stackTrace = context->engine()->stackTrace(20);
1273 for (int i = 0; i < stackTrace.size(); ++i) {
1274 if (i)
1275 str << ',';
1276 const QUrl url(stackTrace.at(i).source);
1278 str << "frame={level=\"" << i << "\",func=\"" << stackTrace.at(i).function
1279 << "\",file=\"" << fileName << "\",fullname=\"" << fileName
1280 << "\",line=\"" << qAbs(stackTrace.at(i).line) << "\",language=\"js\"}";
1281 }
1282 }
1283 str << ']';
1284 return qstrdup(result.toLocal8Bit().constData());
1285}
1286
1287extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
1288{
1289 return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
1290}
1291
1292extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
1293{
1294 auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
1295 return v4StackTrace(engine->currentContext());
1296}
1297
1299{
1300 QUrl src(file);
1301 if (!src.isRelative())
1302 return src;
1303
1304 QUrl base;
1306 while (f) {
1307 if (f->v4Function) {
1308 base = f->v4Function->finalUrl();
1309 break;
1310 }
1311 f = f->parentFrame();
1312 }
1313
1314 if (base.isEmpty() && globalCode)
1316
1317 if (base.isEmpty())
1318 return src;
1319
1320 return base.resolved(src);
1321}
1322
1324{
1325 for (int i = 0; i < NClasses; ++i) {
1327 c->mark(markStack);
1328 }
1329
1330 identifierTable->markObjects(markStack);
1331
1332 for (const auto &compilationUnit : std::as_const(m_compilationUnits))
1333 compilationUnit->markObjects(markStack);
1334}
1335
1337{
1338 // we can get in here with an exception already set, as the runtime
1339 // doesn't check after every operation that can throw.
1340 // in this case preserve the first exception to give correct error
1341 // information
1342 if (hasException)
1343 return Encode::undefined();
1344
1345 hasException = true;
1347 QV4::Scope scope(this);
1349 if (!!error)
1350 exceptionStackTrace = *error->d()->stackTrace;
1351 else
1353
1355 debug->aboutToThrow();
1356
1357 return Encode::undefined();
1358}
1359
1371
1373{
1374 Scope scope(this);
1375 ScopedValue v(scope, newString(message));
1376 v = newErrorObject(v);
1377 return throwError(v);
1378}
1379
1386
1393
1394
1396{
1397 Scope scope(this);
1398 ScopedObject error(scope, newTypeErrorObject(QStringLiteral("Type error")));
1399 return throwError(error);
1400}
1401
1408
1410{
1411 Scope scope(this);
1412 QString msg = name + QLatin1String(" is not defined");
1414 return throwError(error);
1415}
1416
1418{
1419 Scope scope(this);
1420 ScopedString s(scope, value.toString(this));
1421 QString msg = s->toQString() + QLatin1String(" is not defined");
1423 return throwError(error);
1424}
1425
1433
1440
1442{
1443 Scope scope(this);
1444 ScopedString s(scope, value.toString(this));
1445 QString msg = s->toQString() + QLatin1String(" out of range");
1447 return throwError(error);
1448}
1449
1451{
1452 Scope scope(this);
1454 return throwError(error);
1455}
1456
1458{
1459 Scope scope(this);
1460 ScopedValue v(scope, newString(QLatin1String("Unimplemented ") + message));
1461 v = newErrorObject(v);
1462 return throwError(v);
1463}
1464
1465
1467{
1469 QV4::Scope scope(this);
1470 QV4::ScopedValue exception(scope, catchException(&trace));
1472 if (!trace.isEmpty()) {
1473 QV4::StackFrame frame = trace.constFirst();
1474 error.setUrl(QUrl(frame.source));
1475 error.setLine(qAbs(frame.line));
1476 error.setColumn(frame.column);
1477 }
1478 QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
1479 error.setDescription(exception->toQStringNoThrow());
1480 return error;
1481}
1482
1483// Variant conversion code
1484
1485typedef QSet<QV4::Heap::Object *> V4ObjectSet;
1487static QVariant toVariant(
1488 const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior,
1489 V4ObjectSet *visitedObjects);
1490static QObject *qtObjectFromJS(const QV4::Value &value);
1491static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr,
1493static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result);
1496{
1497 return v4->metaTypeToJS(value.metaType(), value.constData());
1498}
1499
1501 V4ObjectSet *visitedObjects)
1502{
1503 Q_ASSERT (!value.isEmpty());
1504
1506 return v->d()->data();
1507
1508 if (metaType == QMetaType::fromType<bool>())
1509 return QVariant(value.toBoolean());
1510
1511 if (metaType == QMetaType::fromType<double>())
1512 return QVariant(value.toNumber());
1513
1514 if (metaType == QMetaType::fromType<float>())
1515 return QVariant(float(value.toNumber()));
1516
1517 if (metaType == QMetaType::fromType<QJsonValue>())
1519
1520 if (metaType == QMetaType::fromType<QJSValue>())
1522
1523 if (const QV4::Object *o = value.as<QV4::Object>()) {
1524 QV4::Scope scope(o->engine());
1525 QV4::ScopedObject object(scope, o);
1526 if (metaType == QMetaType::fromType<QJsonObject>()
1527 && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
1530 return QVariant::fromValue<QObject *>(wrapper->object());
1531 } else if (object->as<QV4::QQmlContextWrapper>()) {
1532 return QVariant();
1534 return w->toVariant();
1536 return v->toVariant();
1537 } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
1538 return l->toVariant();
1539 } else if (QV4::Sequence *s = object->as<QV4::Sequence>()) {
1541 }
1542 }
1543
1544 if (const QV4::ArrayObject *o = value.as<ArrayObject>()) {
1545 QV4::Scope scope(o->engine());
1546 QV4::ScopedArrayObject a(scope, o);
1547 if (metaType == QMetaType::fromType<QList<QObject *>>()) {
1548 QList<QObject *> list;
1549 uint length = a->getLength();
1550 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
1551 for (uint ii = 0; ii < length; ++ii) {
1552 qobjectWrapper = a->get(ii);
1553 if (!!qobjectWrapper) {
1554 list << qobjectWrapper->object();
1555 } else {
1556 list << 0;
1557 }
1558 }
1559
1560 return QVariant::fromValue<QList<QObject*> >(list);
1561 } else if (metaType == QMetaType::fromType<QJsonArray>()) {
1563 }
1564
1566 if (retn.isValid())
1567 return retn;
1568
1569 if (metaType.isValid()) {
1570 retn = QVariant(metaType, nullptr);
1571 auto retnAsIterable = retn.value<QSequentialIterable>();
1572 if (retnAsIterable.metaContainer().canAddValue()) {
1573 QMetaType valueMetaType = retnAsIterable.metaContainer().valueMetaType();
1574 auto const length = a->getLength();
1575 QV4::ScopedValue arrayValue(scope);
1576 for (qint64 i = 0; i < length; ++i) {
1577 arrayValue = a->get(i);
1579 arrayValue, valueMetaType);
1580 if (asVariant.isValid()) {
1581 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1582 continue;
1583 }
1584
1585 if (QMetaType::canConvert(QMetaType::fromType<QJSValue>(), valueMetaType)) {
1586 // before attempting a conversion from the concrete types,
1587 // check if there exists a conversion from QJSValue -> out type
1588 // prefer that one for compatibility reasons
1590 arrayValue->asReturnedValue()));
1591 if (asVariant.convert(valueMetaType)) {
1592 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1593 continue;
1594 }
1595 }
1596
1597 asVariant = toVariant(arrayValue, valueMetaType, JSToQVariantConversionBehavior::Never, visitedObjects);
1598 if (valueMetaType == QMetaType::fromType<QVariant>()) {
1599 retnAsIterable.metaContainer().addValue(retn.data(), &asVariant);
1600 } else {
1601 auto originalType = asVariant.metaType();
1602 bool couldConvert = asVariant.convert(valueMetaType);
1603 if (!couldConvert && originalType.isValid()) {
1604 // If the original type was void, we're converting a "hole" in a sparse
1605 // array. There is no point in warning about that.
1606 qWarning().noquote()
1607 << QLatin1String("Could not convert array value "
1608 "at position %1 from %2 to %3")
1610 QString::fromUtf8(originalType.name()),
1611 QString::fromUtf8(valueMetaType.name()));
1612 }
1613 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1614 }
1615 }
1616 return retn;
1617 }
1618 }
1619 }
1620
1621 if (value.isUndefined())
1622 return QVariant();
1623 if (value.isNull())
1624 return QVariant::fromValue(nullptr);
1625 if (value.isBoolean())
1626 return value.booleanValue();
1627 if (value.isInteger())
1628 return value.integerValue();
1629 if (value.isNumber())
1630 return value.asDouble();
1631 if (String *s = value.stringValue()) {
1632 const QString &str = s->toQString();
1633 // QChars are stored as a strings
1634 if (metaType == QMetaType::fromType<QChar>() && str.size() == 1)
1635 return str.at(0);
1636 return str;
1637 }
1638 if (const QV4::DateObject *d = value.as<DateObject>()) {
1639 // NOTE: since we convert QTime to JS Date,
1640 // round trip will change the variant type (to QDateTime)!
1641
1642 if (metaType == QMetaType::fromType<QDate>())
1643 return DateObject::dateTimeToDate(d->toQDateTime());
1644
1645 if (metaType == QMetaType::fromType<QTime>())
1646 return d->toQDateTime().time();
1647
1648 if (metaType == QMetaType::fromType<QString>())
1649 return d->toString();
1650
1651 return d->toQDateTime();
1652 }
1653 if (const QV4::UrlObject *d = value.as<UrlObject>())
1654 return d->toQUrl();
1655 if (const ArrayBuffer *d = value.as<ArrayBuffer>())
1656 return d->asByteArray();
1657 if (const Symbol *symbol = value.as<Symbol>()) {
1658 return conversionBehavior == JSToQVariantConversionBehavior::Never
1660 : symbol->descriptiveString();
1661 }
1662
1663 const QV4::Object *object = value.as<QV4::Object>();
1664 Q_ASSERT(object);
1665 QV4::Scope scope(object->engine());
1666 QV4::ScopedObject o(scope, object);
1667
1668#if QT_CONFIG(regularexpression)
1669 if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
1670 return re->toQRegularExpression();
1671#endif
1672
1673 if (metaType.isValid() && !(metaType.flags() & QMetaType::PointerToQObject)) {
1675 if (result.isValid())
1676 return result;
1677 }
1678
1679 if (conversionBehavior == JSToQVariantConversionBehavior::Never)
1680 return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue()));
1681
1682 return objectToVariant(o, visitedObjects, conversionBehavior);
1683}
1684
1689
1691 const Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols)
1692{
1693 auto behavior = createJSValueForObjectsAndSymbols ? JSToQVariantConversionBehavior::Never
1695 return ::toVariant(value, typeHint, behavior, nullptr);
1696}
1697
1699 JSToQVariantConversionBehavior conversionBehvior)
1700{
1702 QV4::Scope scope(o->engine());
1704 QV4::ScopedValue name(scope);
1705 QV4::ScopedValue val(scope);
1706 while (1) {
1707 name = it.nextPropertyNameAsString(val);
1708 if (name->isNull())
1709 break;
1710
1711 QString key = name->toQStringNoThrow();
1713 val, /*type hint*/ QMetaType {},
1714 conversionBehvior, visitedObjects));
1715 }
1716 return map;
1717}
1718
1719static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects,
1720 JSToQVariantConversionBehavior conversionBehvior)
1721{
1722 Q_ASSERT(o);
1723
1724 V4ObjectSet recursionGuardSet;
1725 if (!visitedObjects) {
1726 visitedObjects = &recursionGuardSet;
1727 } else if (visitedObjects->contains(o->d())) {
1728 // Avoid recursion.
1729 // For compatibility with QVariant{List,Map} conversion, we return an
1730 // empty object (and no error is thrown).
1731 if (o->as<ArrayObject>())
1732 return QVariantList();
1733 return QVariantMap();
1734 }
1735 visitedObjects->insert(o->d());
1736
1738
1739 if (o->as<ArrayObject>()) {
1740 QV4::Scope scope(o->engine());
1741 QV4::ScopedArrayObject a(scope, o->asReturnedValue());
1742 QV4::ScopedValue v(scope);
1744
1745 int length = a->getLength();
1746 for (int ii = 0; ii < length; ++ii) {
1747 v = a->get(ii);
1748 list << ::toVariant(v, QMetaType {}, conversionBehvior,
1749 visitedObjects);
1750 }
1751
1752 result = list;
1753 } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()
1754 || (conversionBehvior == JSToQVariantConversionBehavior::Aggressive &&
1755 !o->as<QV4::FunctionObject>())) {
1756 /* FunctionObject is excluded for historical reasons, even though
1757 objects with a custom prototype risk losing information
1758 But the Aggressive path is used only in QJSValue::toVariant
1759 which is documented to be lossy
1760 */
1761 result = objectToVariantMap(o, visitedObjects, conversionBehvior);
1762 } else {
1763 // If it's not a plain object, we can only save it as QJSValue.
1765 }
1766
1767 visitedObjects->remove(o->d());
1768 return result;
1769}
1770
1777 QMetaType metaType, const void *ptr,
1778 QV4::Heap::Object *container, int property, uint flags)
1779{
1780 const auto createSequence = [&](const QMetaSequence metaSequence) {
1781 QV4::Scope scope(this);
1782 QV4::Scoped<Sequence> sequence(scope);
1783 if (container) {
1785 this, metaType, metaSequence, ptr,
1786 container, property, Heap::ReferenceObject::Flags(flags));
1787 } else {
1788 return QV4::SequencePrototype::fromData(this, metaType, metaSequence, ptr);
1789 }
1790 };
1791
1792 const int type = metaType.id();
1793 if (type < QMetaType::User) {
1794 switch (QMetaType::Type(type)) {
1796 case QMetaType::Void:
1797 return QV4::Encode::undefined();
1798 case QMetaType::Nullptr:
1799 case QMetaType::VoidStar:
1800 return QV4::Encode::null();
1801 case QMetaType::Bool:
1802 return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
1803 case QMetaType::Int:
1804 return QV4::Encode(*reinterpret_cast<const int*>(ptr));
1805 case QMetaType::UInt:
1806 return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
1807 case QMetaType::Long:
1808 return QV4::Encode((double)*reinterpret_cast<const long *>(ptr));
1809 case QMetaType::ULong:
1810 return QV4::Encode((double)*reinterpret_cast<const ulong *>(ptr));
1811 case QMetaType::LongLong:
1812 return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
1813 case QMetaType::ULongLong:
1814 return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
1815 case QMetaType::Double:
1816 return QV4::Encode(*reinterpret_cast<const double*>(ptr));
1817 case QMetaType::QString:
1818 return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
1819 case QMetaType::QByteArray:
1820 return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue();
1821 case QMetaType::Float:
1822 return QV4::Encode(*reinterpret_cast<const float*>(ptr));
1823 case QMetaType::Short:
1824 return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
1825 case QMetaType::UShort:
1826 return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
1827 case QMetaType::Char:
1828 return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
1829 case QMetaType::UChar:
1830 return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
1831 case QMetaType::SChar:
1832 return QV4::Encode((int)*reinterpret_cast<const signed char*>(ptr));
1833 case QMetaType::QChar:
1834 return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue();
1835 case QMetaType::Char16:
1836 return newString(QChar(*reinterpret_cast<const char16_t *>(ptr)))->asReturnedValue();
1837 case QMetaType::QDateTime:
1839 *reinterpret_cast<const QDateTime *>(ptr),
1840 container, property, flags));
1841 case QMetaType::QDate:
1843 *reinterpret_cast<const QDate *>(ptr),
1844 container, property, flags));
1845 case QMetaType::QTime:
1847 *reinterpret_cast<const QTime *>(ptr),
1848 container, property, flags));
1849#if QT_CONFIG(regularexpression)
1850 case QMetaType::QRegularExpression:
1851 return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
1852#endif
1853 case QMetaType::QObjectStar:
1854 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1855 case QMetaType::QStringList:
1856 return createSequence(QMetaSequence::fromContainer<QStringList>());
1857 case QMetaType::QVariantList:
1858 return createSequence(QMetaSequence::fromContainer<QVariantList>());
1859 case QMetaType::QVariantMap:
1860 return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr));
1861 case QMetaType::QJsonValue:
1862 return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
1863 case QMetaType::QJsonObject:
1864 return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr));
1865 case QMetaType::QJsonArray:
1866 return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr));
1867 case QMetaType::QPixmap:
1868 case QMetaType::QImage:
1869 // Scarce value types
1870 return QV4::Encode(newVariantObject(metaType, ptr));
1871 default:
1872 break;
1873 }
1874 }
1875
1876 if (metaType.flags() & QMetaType::IsEnumeration)
1877 return fromData(metaType.underlyingType(), ptr, container, property, flags);
1878
1879 QV4::Scope scope(this);
1880 if (metaType == QMetaType::fromType<QQmlListReference>()) {
1881 typedef QQmlListReferencePrivate QDLRP;
1882 QDLRP *p = QDLRP::get((QQmlListReference*)const_cast<void *>(ptr));
1883 if (p->object)
1884 return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType);
1885 else
1886 return QV4::Encode::null();
1887 } else if (auto flags = metaType.flags(); flags & QMetaType::IsQmlList) {
1888 // casting to QQmlListProperty<QObject> is slightly nasty, but it's the
1889 // same QQmlListReference does.
1890 const auto *p = static_cast<const QQmlListProperty<QObject> *>(ptr);
1891 if (p->object)
1892 return QV4::QmlListWrapper::create(scope.engine, *p, metaType);
1893 else
1894 return QV4::Encode::null();
1895 } else if (metaType == QMetaType::fromType<QJSValue>()) {
1897 this, *reinterpret_cast<const QJSValue *>(ptr));
1898 } else if (metaType == QMetaType::fromType<QList<QObject *> >()) {
1899 // XXX Can this be made more by using Array as a prototype and implementing
1900 // directly against QList<QObject*>?
1901 const QList<QObject *> &list = *(const QList<QObject *>*)ptr;
1903 a->arrayReserve(list.size());
1904 QV4::ScopedValue v(scope);
1905 for (int ii = 0; ii < list.size(); ++ii)
1906 a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(this, list.at(ii))));
1907 a->setArrayLengthUnchecked(list.size());
1908 return a.asReturnedValue();
1909 } else if (auto flags = metaType.flags(); flags & QMetaType::PointerToQObject) {
1910 if (flags.testFlag(QMetaType::IsConst))
1911 return QV4::QObjectWrapper::wrapConst(this, *reinterpret_cast<QObject* const *>(ptr));
1912 else
1913 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1914 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
1915 const QJSPrimitiveValue *primitive = static_cast<const QJSPrimitiveValue *>(ptr);
1916 switch (primitive->type()) {
1918 return Encode(primitive->asBoolean());
1920 return Encode(primitive->asInteger());
1922 return newString(primitive->asString())->asReturnedValue();
1924 return Encode::undefined();
1926 return Encode::null();
1928 return Encode(primitive->asDouble());
1929 }
1930 }
1931
1932 if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(metaType)) {
1933 if (container) {
1935 this, ptr, vtmo, metaType,
1936 container, property, Heap::ReferenceObject::Flags(flags));
1937 } else {
1938 return QV4::QQmlValueTypeWrapper::create(this, ptr, vtmo, metaType);
1939 }
1940 }
1941
1942 const QQmlType listType = QQmlMetaType::qmlListType(metaType);
1943 if (listType.isSequentialContainer())
1944 return createSequence(listType.listMetaSequence());
1945
1946 QSequentialIterable iterable;
1947 if (QMetaType::convert(metaType, ptr, QMetaType::fromType<QSequentialIterable>(), &iterable)) {
1948
1949 // If the resulting iterable is useful for anything, turn it into a QV4::Sequence.
1950 const QMetaSequence sequence = iterable.metaContainer();
1951 if (sequence.hasSize() && sequence.canGetValueAtIndex())
1952 return createSequence(sequence);
1953
1954 // As a last resort, try to read the contents of the container via an iterator
1955 // and build a JS array from them.
1956 if (sequence.hasConstIterator() && sequence.canGetValueAtConstIterator()) {
1958 for (auto it = iterable.constBegin(), end = iterable.constEnd(); it != end; ++it)
1959 a->push_back(fromVariant(*it));
1960 return a.asReturnedValue();
1961 }
1962 }
1963
1964 return QV4::Encode(newVariantObject(metaType, ptr));
1965}
1966
1971
1973 const QVariant &variant, Heap::Object *parent, int property, uint flags)
1974{
1975 return fromData(variant.metaType(), variant.constData(), parent, property, flags);
1976}
1977
1979{
1980 Q_ASSERT(o);
1981 V4ObjectSet visitedObjects;
1982 visitedObjects.insert(o->d());
1984}
1985
1986// Converts a QVariantMap to JS.
1987// The result is a new Object object with property names being
1988// the keys of the QVariantMap, and values being the values of
1989// the QVariantMap converted to JS, recursively.
1991{
1992 QV4::Scope scope(v4);
1993 QV4::ScopedObject o(scope, v4->newObject());
1994 QV4::ScopedString s(scope);
1996 QV4::ScopedValue v(scope);
1997 for (QVariantMap::const_iterator it = vmap.constBegin(), cend = vmap.constEnd(); it != cend; ++it) {
1998 s = v4->newIdentifier(it.key());
1999 key = s->propertyKey();
2000 v = variantToJS(v4, it.value());
2001 if (key->isArrayIndex())
2002 o->arraySet(key->asArrayIndex(), v);
2003 else
2004 o->insertMember(s, v);
2005 }
2006 return o.asReturnedValue();
2007}
2008
2009// Converts the meta-type defined by the given type and data to JS.
2010// Returns the value if conversion succeeded, an empty handle otherwise.
2012{
2013 Q_ASSERT(data != nullptr);
2014
2015 if (type == QMetaType::fromType<QVariant>()) {
2016 // unwrap it: this is tested in QJSEngine, and makes the most sense for
2017 // end-user code too.
2018 return fromVariant(*reinterpret_cast<const QVariant*>(data));
2019 } else if (type == QMetaType::fromType<QUrl>()) {
2020 // Create a proper URL object here, rather than a variant.
2021 return newUrlObject(*reinterpret_cast<const QUrl *>(data))->asReturnedValue();
2022 }
2023
2024 return fromData(type, data);
2025}
2026
2028{
2029 return s_maxJSStackSize;
2030}
2031
2033{
2034 return s_maxGCStackSize;
2035}
2036
2044{
2045 if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max())) {
2046 throwRangeError(QStringLiteral("Invalid array length."));
2047 return 0;
2048 }
2049 if (len64 > qint64(this->jsStackLimit - this->jsStackTop)) {
2050 throwRangeError(QStringLiteral("Array too large for apply()."));
2051 return 0;
2052 }
2053 return len64;
2054}
2055
2060
2061QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const QUrl &url)
2062{
2064 const DiskCacheOptions options = diskCacheOptions();
2065 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (options & DiskCache::Aot)
2067 url,
2068 (options & DiskCache::AotByteCode)
2071 &cacheError)
2072 : nullptr) {
2074 QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>(
2075 cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, url.fileName(),
2076 url.toString()));
2077 }
2078
2080 if (!f.open(QIODevice::ReadOnly)) {
2081 throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString()));
2082 return nullptr;
2083 }
2084
2085 const QDateTime timeStamp = QFileInfo(f).lastModified();
2086
2087 const QString sourceCode = QString::fromUtf8(f.readAll());
2088 f.close();
2089
2090 return compileModule(url, sourceCode, timeStamp);
2091}
2092
2093
2094QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(
2095 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
2096{
2097 QList<QQmlJS::DiagnosticMessage> diagnostics;
2098 auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
2099 sourceCode, sourceTimeStamp, &diagnostics);
2100 for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
2101 if (m.isError()) {
2102 throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
2103 return nullptr;
2104 } else {
2105 qWarning() << url << ':' << m.loc.startLine << ':' << m.loc.startColumn
2106 << ": warning: " << m.message;
2107 }
2108 }
2109
2110 return insertCompilationUnit(std::move(unit));
2111}
2112
2113QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compilationUnitForUrl(const QUrl &url) const
2114{
2115 // Gives the _most recently inserted_ CU of that URL. That's what we want.
2116 return m_compilationUnits.value(url);
2117}
2118
2119QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::executableCompilationUnit(
2120 QQmlRefPointer<CompiledData::CompilationUnit> &&unit)
2121{
2122 const QUrl url = unit->finalUrl();
2123 auto [begin, end] = std::as_const(m_compilationUnits).equal_range(url);
2124
2125 for (auto it = begin; it != end; ++it) {
2126 if ((*it)->baseCompilationUnit() == unit)
2127 return *it;
2128 }
2129
2130 auto executableUnit = m_compilationUnits.insert(
2131 url, ExecutableCompilationUnit::create(std::move(unit), this));
2132 // runtime data should not be initialized yet, so we don't need to mark the CU
2133 Q_ASSERT(!(*executableUnit)->runtimeStrings);
2134 return *executableUnit;
2135}
2136
2137QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::insertCompilationUnit(QQmlRefPointer<CompiledData::CompilationUnit> &&unit) {
2138 QUrl url = unit->finalUrl();
2139 auto executableUnit = ExecutableCompilationUnit::create(std::move(unit), this);
2140 /* Compilation Units stored in the engine are part of the gc roots,
2141 so we don't trigger any write-barrier when they are added. Use
2142 markCustom to make sure they are still marked when we insert them */
2143 QV4::WriteBarrier::markCustom(this, [&executableUnit](QV4::MarkStack *ms) {
2144 executableUnit->markObjects(ms);
2145 });
2146 return *m_compilationUnits.insert(std::move(url), std::move(executableUnit));
2147}
2148
2150{
2151 for (auto it = m_compilationUnits.begin(); it != m_compilationUnits.end();) {
2152 if ((*it)->count() == 1)
2153 it = m_compilationUnits.erase(it);
2154 else
2155 ++it;
2156 }
2157}
2158
2160 const QUrl &url, const ExecutableCompilationUnit *referrer) const
2161{
2162 const auto nativeModule = nativeModules.find(url);
2163 if (nativeModule != nativeModules.end())
2164 return Module { nullptr, *nativeModule };
2165
2166 const QUrl resolved = referrer
2167 ? referrer->finalUrl().resolved(QQmlTypeLoader::normalize(url))
2169 auto existingModule = m_compilationUnits.find(resolved);
2170 if (existingModule == m_compilationUnits.end())
2171 return Module { nullptr, nullptr };
2172 return Module { *existingModule, nullptr };
2173}
2174
2176{
2177 const auto nativeModule = nativeModules.constFind(url);
2178 if (nativeModule != nativeModules.cend())
2179 return Module { nullptr, *nativeModule };
2180
2181 const QUrl resolved = referrer
2182 ? referrer->finalUrl().resolved(QQmlTypeLoader::normalize(url))
2184 auto existingModule = m_compilationUnits.constFind(resolved);
2185 if (existingModule != m_compilationUnits.cend())
2186 return Module { *existingModule, nullptr };
2187
2188 auto newModule = compileModule(resolved);
2189 Q_ASSERT(!newModule || m_compilationUnits.contains(resolved, newModule));
2190
2191 return Module { newModule, nullptr };
2192}
2193
2195{
2196 const auto existingModule = nativeModules.constFind(url);
2197 if (existingModule != nativeModules.cend())
2198 return nullptr;
2199
2201 *val = module.asReturnedValue();
2202 nativeModules.insert(url, val);
2203
2204 // Make sure the type loader doesn't try to resolve the script anymore.
2205 if (m_qmlEngine)
2206 QQmlEnginePrivate::get(m_qmlEngine)->typeLoader.injectScript(url, *val);
2207
2208 return val;
2209}
2210
2211static ExecutionEngine::DiskCacheOptions transFormDiskCache(const char *v)
2212{
2213 using DiskCache = ExecutionEngine::DiskCache;
2214
2215 if (v == nullptr)
2216 return DiskCache::Enabled;
2217
2218 ExecutionEngine::DiskCacheOptions result = DiskCache::Disabled;
2219 const QList<QByteArray> options = QByteArray(v).split(',');
2220 for (const QByteArray &option : options) {
2221 if (option == "aot-bytecode")
2222 result |= DiskCache::AotByteCode;
2223 else if (option == "aot-native")
2224 result |= DiskCache::AotNative;
2225 else if (option == "aot")
2226 result |= DiskCache::Aot;
2227 else if (option == "qmlc-read")
2228 result |= DiskCache::QmlcRead;
2229 else if (option == "qmlc-write")
2230 result |= DiskCache::QmlcWrite;
2231 else if (option == "qmlc")
2232 result |= DiskCache::Qmlc;
2233 else
2234 qWarning() << "Ignoring unknown option to QML_DISK_CACHE:" << option;
2235 }
2236
2237 return result;
2238}
2239
2240ExecutionEngine::DiskCacheOptions ExecutionEngine::diskCacheOptions() const
2241{
2242 if (forceDiskCache())
2243 return DiskCache::Enabled;
2244 if (disableDiskCache() || debugger())
2245 return DiskCache::Disabled;
2246 static const DiskCacheOptions options = qmlGetConfigOption<
2247 DiskCacheOptions, transFormDiskCache>("QML_DISK_CACHE");
2248 return options;
2249}
2250
2252 QV4::ExecutionContext *context, int argc, void **args,
2254{
2255 if (!args) {
2256 Q_ASSERT(argc == 0);
2257 void *dummyArgs[] = { nullptr };
2258 QMetaType dummyTypes[] = { QMetaType::fromType<void>() };
2259 function->call(self, dummyArgs, dummyTypes, argc, context);
2260 return;
2261 }
2262 Q_ASSERT(types); // both args and types must be present
2263 // implicitly sets the return value, which is args[0]
2264 function->call(self, args, types, argc, context);
2265}
2266
2268 QV4::ExecutionContext *context, int argc,
2269 const QV4::Value *argv)
2270{
2271 QV4::Scope scope(this);
2272 QV4::ScopedObject jsSelf(scope, QV4::QObjectWrapper::wrap(this, self));
2273 Q_ASSERT(jsSelf);
2274 return function->call(jsSelf, argv, argc, context);
2275}
2276
2282
2284{
2286
2288
2289#if QT_CONFIG(qml_locale)
2293#endif
2294
2295#if QT_CONFIG(qml_xml_http_request)
2297 m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
2298#endif
2299
2301
2302 {
2303 for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
2304 if (globalObject->internalClass()->nameMap.at(i).isString()) {
2306 m_illegalNames.insert(id.toQString());
2307 }
2308 }
2309 }
2310}
2311
2313{
2314 QV4::Scope scope(this);
2315 QtObject *qtObject = new QtObject(this);
2317
2318 QV4::ScopedObject qtObjectWrapper(
2319 scope, QV4::QObjectWrapper::wrap(this, qtObject));
2320 QV4::ScopedObject qtNamespaceWrapper(
2321 scope, QV4::QMetaObjectWrapper::create(this, &Qt::staticMetaObject));
2322 QV4::ScopedObject qtObjectProtoWrapper(
2323 scope, qtObjectWrapper->getPrototypeOf());
2324
2325 qtNamespaceWrapper->setPrototypeOf(qtObjectProtoWrapper);
2326 qtObjectWrapper->setPrototypeOf(qtNamespaceWrapper);
2327
2328 globalObject->defineDefaultProperty(QStringLiteral("Qt"), qtObjectWrapper);
2329}
2330
2331const QSet<QString> &ExecutionEngine::illegalNames() const
2332{
2333 return m_illegalNames;
2334}
2335
2337{
2338 // Second stage of initialization. We're updating some more prototypes here.
2339 isInitialized = false;
2340 m_qmlEngine = engine;
2342 isInitialized = true;
2343}
2344
2346{
2348 return;
2349
2350 QV4::Scope scope(v4);
2351
2352 bool instanceOfObject = false;
2353 QV4::ScopedObject p(scope, object->getPrototypeOf());
2354 while (p) {
2355 if (p->d() == v4->objectPrototype()->d()) {
2356 instanceOfObject = true;
2357 break;
2358 }
2359 p = p->getPrototypeOf();
2360 }
2361 if (!instanceOfObject)
2362 return;
2363
2364 Heap::InternalClass *frozen = object->internalClass()->frozen();
2365 object->setInternalClass(frozen); // Immediately assign frozen to prevent it from getting GC'd
2366
2367 QV4::ScopedObject o(scope);
2368 for (uint i = 0; i < frozen->size; ++i) {
2369 if (!frozen->nameMap.at(i).isStringOrSymbol())
2370 continue;
2371 o = *object->propertyData(i);
2372 if (o)
2373 freeze_recursive(v4, o);
2374 }
2375}
2376
2378{
2379 QV4::Scope scope(this);
2380 QV4::ScopedObject o(scope, value);
2381 freeze_recursive(this, o);
2382}
2383
2385{
2386 QV4::Scope scope(this);
2387 ScopedObject object(scope, value);
2388 if (!object)
2389 return;
2390
2391 std::vector<Heap::Object *> stack { object->d() };
2392
2393 // Methods meant to be overridden
2394 const PropertyKey writableMembers[] = {
2399 };
2400 const auto writableBegin = std::begin(writableMembers);
2401 const auto writableEnd = std::end(writableMembers);
2402
2403 while (!stack.empty()) {
2404 object = stack.back();
2405 stack.pop_back();
2406
2408 continue;
2409
2410 Scoped<InternalClass> locked(scope, object->internalClass()->locked());
2411 QV4::ScopedObject member(scope);
2412
2413 // Taking this copy is cheap. It's refcounted. This avoids keeping a reference
2414 // to the original IC.
2415 const SharedInternalClassData<PropertyKey> nameMap = locked->d()->nameMap;
2416
2417 for (uint i = 0, end = locked->d()->size; i < end; ++i) {
2418 const PropertyKey key = nameMap.at(i);
2419 if (!key.isStringOrSymbol())
2420 continue;
2421 if ((member = *object->propertyData(i))) {
2422 stack.push_back(member->d());
2423 if (std::find(writableBegin, writableEnd, key) == writableEnd) {
2424 PropertyAttributes attributes = locked->d()->find(key).attributes;
2425 attributes.setConfigurable(false);
2426 attributes.setWritable(false);
2427 locked = locked->changeMember(key, attributes);
2428 }
2429 }
2430 }
2431
2432 object->setInternalClass(locked->d());
2433 }
2434}
2435
2437{
2438 if (!m_time.isValid())
2439 m_time.start();
2440 m_startedTimers[timerName] = m_time.elapsed();
2441}
2442
2443qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
2444{
2445 if (!m_startedTimers.contains(timerName)) {
2446 *wasRunning = false;
2447 return 0;
2448 }
2449 *wasRunning = true;
2450 qint64 startedAt = m_startedTimers.take(timerName);
2451 return m_time.elapsed() - startedAt;
2452}
2453
2455{
2457 int number = m_consoleCount.value(key, 0);
2458 number++;
2459 m_consoleCount.insert(key, number);
2460 return number;
2461}
2462
2464{
2465 if (m_extensionData.size() <= index)
2466 m_extensionData.resize(index + 1);
2467
2468 if (m_extensionData.at(index))
2469 delete m_extensionData.at(index);
2470
2471 m_extensionData[index] = data;
2472}
2473
2474template<typename Source>
2475bool convertToIterable(QMetaType metaType, void *data, Source *sequence)
2476{
2477 QSequentialIterable iterable;
2478 if (!QMetaType::view(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
2479 return false;
2480
2481 const QMetaType elementMetaType = iterable.valueMetaType();
2482 for (qsizetype i = 0, end = sequence->getLength(); i < end; ++i) {
2483 QVariant element(elementMetaType);
2484 ExecutionEngine::metaTypeFromJS(sequence->get(i), elementMetaType, element.data());
2485 iterable.addValue(element, QSequentialIterable::AtEnd);
2486 }
2487 return true;
2488}
2489
2499{
2500 // check if it's one of the types we know
2501 switch (metaType.id()) {
2502 case QMetaType::Bool:
2503 *reinterpret_cast<bool*>(data) = value.toBoolean();
2504 return true;
2505 case QMetaType::Int:
2506 *reinterpret_cast<int*>(data) = value.toInt32();
2507 return true;
2508 case QMetaType::UInt:
2509 *reinterpret_cast<uint*>(data) = value.toUInt32();
2510 return true;
2511 case QMetaType::Long:
2512 *reinterpret_cast<long*>(data) = long(value.toInteger());
2513 return true;
2514 case QMetaType::ULong:
2515 *reinterpret_cast<ulong*>(data) = ulong(value.toInteger());
2516 return true;
2517 case QMetaType::LongLong:
2518 *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
2519 return true;
2520 case QMetaType::ULongLong:
2521 *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
2522 return true;
2523 case QMetaType::Double:
2524 *reinterpret_cast<double*>(data) = value.toNumber();
2525 return true;
2526 case QMetaType::QString:
2527 if (value.isUndefined())
2528 *reinterpret_cast<QString*>(data) = QStringLiteral("undefined");
2529 else if (value.isNull())
2530 *reinterpret_cast<QString*>(data) = QStringLiteral("null");
2531 else
2532 *reinterpret_cast<QString*>(data) = value.toQString();
2533 return true;
2534 case QMetaType::QByteArray:
2535 if (const ArrayBuffer *ab = value.as<ArrayBuffer>()) {
2536 *reinterpret_cast<QByteArray*>(data) = ab->asByteArray();
2537 } else if (const String *string = value.as<String>()) {
2538 *reinterpret_cast<QByteArray*>(data) = string->toQString().toUtf8();
2539 } else if (const ArrayObject *ao = value.as<ArrayObject>()) {
2540 // Since QByteArray is sequentially iterable, we have to construct it from a JS Array.
2542 const qint64 length = ao->getLength();
2543 result.reserve(length);
2544 for (qint64 i = 0; i < length; ++i) {
2545 char value = 0;
2546 ExecutionEngine::metaTypeFromJS(ao->get(i), QMetaType::fromType<char>(), &value);
2547 result.push_back(value);
2548 }
2549 *reinterpret_cast<QByteArray*>(data) = std::move(result);
2550 } else {
2551 *reinterpret_cast<QByteArray*>(data) = QByteArray();
2552 }
2553 return true;
2554 case QMetaType::Float:
2555 *reinterpret_cast<float*>(data) = value.toNumber();
2556 return true;
2557 case QMetaType::Short:
2558 *reinterpret_cast<short*>(data) = short(value.toInt32());
2559 return true;
2560 case QMetaType::UShort:
2561 *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
2562 return true;
2563 case QMetaType::Char:
2564 *reinterpret_cast<char*>(data) = char(value.toInt32());
2565 return true;
2566 case QMetaType::UChar:
2567 *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
2568 return true;
2569 case QMetaType::SChar:
2570 *reinterpret_cast<signed char*>(data) = (signed char)(value.toInt32());
2571 return true;
2572 case QMetaType::QChar:
2573 if (String *s = value.stringValue()) {
2574 QString str = s->toQString();
2575 *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
2576 } else {
2577 *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
2578 }
2579 return true;
2580 case QMetaType::QDateTime:
2581 if (const QV4::DateObject *d = value.as<DateObject>()) {
2582 *reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
2583 return true;
2584 } break;
2585 case QMetaType::QDate:
2586 if (const QV4::DateObject *d = value.as<DateObject>()) {
2587 *reinterpret_cast<QDate *>(data) = DateObject::dateTimeToDate(d->toQDateTime());
2588 return true;
2589 } break;
2590 case QMetaType::QTime:
2591 if (const QV4::DateObject *d = value.as<DateObject>()) {
2592 *reinterpret_cast<QTime *>(data) = d->toQDateTime().time();
2593 return true;
2594 } break;
2595 case QMetaType::QUrl:
2596 if (String *s = value.stringValue()) {
2597 *reinterpret_cast<QUrl *>(data) = QUrl(s->toQString());
2598 return true;
2599 } else if (const QV4::UrlObject *d = value.as<UrlObject>()) {
2600 *reinterpret_cast<QUrl *>(data) = d->toQUrl();
2601 return true;
2602 } else if (const QV4::VariantObject *d = value.as<VariantObject>()) {
2603 const QVariant *variant = &d->d()->data();
2604 if (variant->metaType() == QMetaType::fromType<QUrl>()) {
2605 *reinterpret_cast<QUrl *>(data)
2606 = *reinterpret_cast<const QUrl *>(variant->constData());
2607 return true;
2608 }
2609 }
2610 break;
2611#if QT_CONFIG(regularexpression)
2612 case QMetaType::QRegularExpression:
2613 if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
2614 *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
2615 return true;
2616 } break;
2617#endif
2618 case QMetaType::QObjectStar: {
2619 if (value.isNull()) {
2620 *reinterpret_cast<QObject* *>(data) = nullptr;
2621 return true;
2622 }
2623 if (value.as<QV4::QObjectWrapper>()) {
2624 *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
2625 return true;
2626 }
2627 break;
2628 }
2629 case QMetaType::QStringList: {
2631 if (a) {
2632 *reinterpret_cast<QStringList *>(data) = a->toQStringList();
2633 return true;
2634 }
2635 break;
2636 }
2637 case QMetaType::QVariantList: {
2639 if (a) {
2640 *reinterpret_cast<QVariantList *>(data) = ExecutionEngine::toVariant(
2641 *a, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false)
2642 .toList();
2643 return true;
2644 }
2645 break;
2646 }
2647 case QMetaType::QVariantMap: {
2648 const QV4::Object *o = value.as<QV4::Object>();
2649 if (o) {
2650 *reinterpret_cast<QVariantMap *>(data) = o->engine()->variantMapFromJS(o);
2651 return true;
2652 }
2653 break;
2654 }
2656 if (value.as<QV4::Managed>()) {
2657 *reinterpret_cast<QVariant*>(data) = ExecutionEngine::toVariant(
2658 value, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false);
2659 } else if (value.isNull()) {
2660 *reinterpret_cast<QVariant*>(data) = QVariant::fromValue(nullptr);
2661 } else if (value.isUndefined()) {
2662 *reinterpret_cast<QVariant*>(data) = QVariant();
2663 } else if (value.isBoolean()) {
2664 *reinterpret_cast<QVariant*>(data) = QVariant(value.booleanValue());
2665 } else if (value.isInteger()) {
2666 *reinterpret_cast<QVariant*>(data) = QVariant(value.integerValue());
2667 } else if (value.isDouble()) {
2668 *reinterpret_cast<QVariant*>(data) = QVariant(value.doubleValue());
2669 }
2670 return true;
2671 case QMetaType::QJsonValue:
2672 *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
2673 return true;
2674 case QMetaType::QJsonObject: {
2675 *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.as<Object>());
2676 return true;
2677 }
2678 case QMetaType::QJsonArray: {
2680 if (a) {
2681 *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
2682 return true;
2683 }
2684 break;
2685 }
2686 default:
2687 break;
2688 }
2689
2690 if (metaType.flags() & QMetaType::IsEnumeration) {
2691 *reinterpret_cast<int *>(data) = value.toInt32();
2692 return true;
2693 }
2694
2696 if (metaType == QMetaType::fromType<QQmlListReference>()) {
2697 *reinterpret_cast<QQmlListReference *>(data) = wrapper->toListReference();
2698 return true;
2699 }
2700
2701 const auto wrapperPrivate = wrapper->d();
2702 if (wrapperPrivate->propertyType() == metaType) {
2703 *reinterpret_cast<QQmlListProperty<QObject> *>(data) = *wrapperPrivate->property();
2704 return true;
2705 }
2706 }
2707
2708 if (const QQmlValueTypeWrapper *vtw = value.as<QQmlValueTypeWrapper>()) {
2709 const QMetaType valueType = vtw->type();
2710 if (valueType == metaType)
2711 return vtw->toGadget(data);
2712
2713 Heap::QQmlValueTypeWrapper *d = vtw->d();
2714 if (d->isReference())
2715 d->readReference();
2716
2717 if (void *gadgetPtr = d->gadgetPtr()) {
2718 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, gadgetPtr))
2719 return true;
2720 if (QMetaType::canConvert(valueType, metaType))
2721 return QMetaType::convert(valueType, gadgetPtr, metaType, data);
2722 } else {
2723 QVariant empty(valueType);
2724 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, empty.data()))
2725 return true;
2726 if (QMetaType::canConvert(valueType, metaType))
2727 return QMetaType::convert(valueType, empty.data(), metaType, data);
2728 }
2729 }
2730
2731 // Try to use magic; for compatibility with qjsvalue_cast.
2732
2733 if (convertToNativeQObject(value, metaType, reinterpret_cast<void **>(data)))
2734 return true;
2735
2736 const bool isPointer = (metaType.flags() & QMetaType::IsPointer);
2737 const QV4::VariantObject *variantObject = value.as<QV4::VariantObject>();
2738 if (variantObject) {
2739 // Actually a reference, because we're poking it for its data() below and we want
2740 // the _original_ data, not some copy.
2741 QVariant &var = variantObject->d()->data();
2742
2743 if (var.metaType() == metaType) {
2744 metaType.destruct(data);
2745 metaType.construct(data, var.data());
2746 return true;
2747 }
2748
2749 if (isPointer) {
2750 const QByteArray pointedToTypeName = QByteArray(metaType.name()).chopped(1);
2751 const QMetaType valueType = QMetaType::fromName(pointedToTypeName);
2752
2753 if (valueType == var.metaType()) {
2754 // ### Qt7: Remove this. Returning pointers to potentially gc'd data is crazy.
2755 // We have T t, T* is requested, so return &t.
2756 *reinterpret_cast<const void **>(data) = var.data();
2757 return true;
2758 } else if (Object *o = value.objectValue()) {
2759 // Look in the prototype chain.
2760 QV4::Scope scope(o->engine());
2761 QV4::ScopedObject proto(scope, o->getPrototypeOf());
2762 while (proto) {
2763 bool canCast = false;
2764 if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
2765 const QVariant &v = vo->d()->data();
2766 canCast = (metaType == v.metaType());
2767 }
2768 else if (proto->as<QV4::QObjectWrapper>()) {
2769 QV4::ScopedObject p(scope, proto.getPointer());
2770 if (QObject *qobject = qtObjectFromJS(p)) {
2771 if (const QMetaObject *metaObject = metaType.metaObject())
2772 canCast = metaObject->cast(qobject) != nullptr;
2773 else
2774 canCast = qobject->qt_metacast(pointedToTypeName);
2775 }
2776 }
2777 if (canCast) {
2778 const QMetaType varType = var.metaType();
2779 if (varType.flags() & QMetaType::IsPointer) {
2780 *reinterpret_cast<const void **>(data)
2781 = *reinterpret_cast<void *const *>(var.data());
2782 } else {
2783 *reinterpret_cast<const void **>(data) = var.data();
2784 }
2785 return true;
2786 }
2787 proto = proto->getPrototypeOf();
2788 }
2789 }
2791 metaType, data, var.metaType(), var.data())) {
2792 return true;
2793 }
2794 } else if (value.isNull() && isPointer) {
2795 *reinterpret_cast<void* *>(data) = nullptr;
2796 return true;
2797 } else if (metaType == QMetaType::fromType<QJSValue>()) {
2798 QJSValuePrivate::setValue(reinterpret_cast<QJSValue*>(data), value.asReturnedValue());
2799 return true;
2800 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
2801 *reinterpret_cast<QJSPrimitiveValue *>(data) = createPrimitive(&value);
2802 return true;
2803 } else if (!isPointer) {
2805 return true;
2806 }
2807
2808 if (const QV4::Sequence *sequence = value.as<Sequence>()) {
2810 if (result.metaType() == metaType) {
2811 metaType.destruct(data);
2812 metaType.construct(data, result.constData());
2813 return true;
2814 }
2815
2816 if (convertToIterable(metaType, data, sequence))
2817 return true;
2818 }
2819
2820 if (const QV4::ArrayObject *array = value.as<ArrayObject>()) {
2821 if (convertToIterable(metaType, data, array))
2822 return true;
2823 }
2824
2825 return false;
2826}
2827
2828static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result)
2829{
2830 if (!(targetType.flags() & QMetaType::IsPointer))
2831 return false;
2832 if (QObject *qobject = qtObjectFromJS(value)) {
2833 // If the target type has a metaObject, use that for casting.
2834 if (const QMetaObject *targetMetaObject = targetType.metaObject()) {
2835 if (QObject *instance = targetMetaObject->cast(qobject)) {
2836 *result = instance;
2837 return true;
2838 }
2839 return false;
2840 }
2841
2842 // We have to call the generated qt_metacast rather than metaObject->cast() here so that
2843 // it works for types without QMetaObject, such as QStandardItem.
2844 const QByteArray targetTypeName = targetType.name();
2845 const int start = targetTypeName.startsWith("const ") ? 6 : 0;
2846 const QByteArray className = targetTypeName.mid(start, targetTypeName.size() - start - 1);
2847 if (void *instance = qobject->qt_metacast(className)) {
2848 *result = instance;
2849 return true;
2850 }
2851 }
2852 return false;
2853}
2854
2856{
2857 if (!value.isObject())
2858 return nullptr;
2859
2860 QV4::Scope scope(value.as<QV4::Managed>()->engine());
2862
2863 if (v) {
2864 QVariant variant = v->d()->data();
2865 int type = variant.userType();
2866 if (type == QMetaType::QObjectStar)
2867 return *reinterpret_cast<QObject* const *>(variant.constData());
2868 }
2870 if (wrapper)
2871 return wrapper->object();
2872
2873 QV4::Scoped<QV4::QQmlTypeWrapper> typeWrapper(scope, value);
2874 if (typeWrapper)
2875 return typeWrapper->object();
2876
2877 return nullptr;
2878}
2879
2888
2890{
2891 return &registrationData()->mutex;
2892}
2893
2895{
2896 return registrationData()->extensionCount++;
2897}
2898
2899#if QT_CONFIG(qml_network)
2900QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine)
2901{
2902 return engine->qmlEngine()->networkAccessManager();
2903}
2904#endif // qml_network
2905
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatetime.h:292
\inmodule QtCore \reentrant
Definition qdatetime.h:29
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
bool isValid() const noexcept
Returns false if the timer has never been started or invalidated by a call to invalidate().
QDateTime lastModified() const
Returns the date and time when the file was last modified.
Definition qfileinfo.h:160
\inmodule QtCore
Definition qfile.h:93
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:986
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1008
T value(const Key &key) const noexcept
Definition qhash.h:1055
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1304
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
static void setObjectOwnership(QObject *, ObjectOwnership)
Sets the ownership of object.
@ AllExtensions
Definition qjsengine.h:289
@ JavaScriptOwnership
Definition qjsengine.h:281
The QJSPrimitiveValue class operates on primitive types in JavaScript semantics.
constexpr Type type() const
Returns the type of the QJSPrimitiveValue.
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
Definition qjsvalue_p.h:197
static QV4::ExecutionEngine * engine(const QJSValue *jsval)
Definition qjsvalue_p.h:321
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
Definition qjsvalue_p.h:306
static void setValue(QJSValue *jsval, const QV4::Value &v)
Definition qjsvalue_p.h:290
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:25
QString arg(Args &&...args) const
Definition qlist.h:76
qsizetype size() const noexcept
Definition qlist.h:398
const_reference at(qsizetype i) const noexcept
Definition qlist.h:447
void append(parameter_type t)
Definition qlist.h:459
void clear()
Definition qlist.h:435
iterator insert(const Key &key, const T &value)
Definition qmap.h:689
bool hasSize() const
Returns true if the container can be queried for its size, false otherwise.
bool hasConstIterator() const
Returns true if the underlying container offers a const iterator, false otherwise.
\inmodule QtCore
bool canGetValueAtIndex() const
Returns true if values can be retrieved from the container by index, otherwise false.
bool canGetValueAtConstIterator() const
Returns true if the underlying container can retrieve the value pointed to by a const iterator,...
\inmodule QtCore
Definition qmetatype.h:342
static constexpr QMetaType fromType()
Definition qmetatype.h:2643
void destruct(void *data) const
static bool canConvert(QMetaType fromType, QMetaType toType)
Returns true if QMetaType::convert can convert from fromType to toType.
constexpr TypeFlags flags() const
Definition qmetatype.h:2659
static bool view(QMetaType fromType, void *from, QMetaType toType, void *to)
Creates a mutable view on the object at from of fromType in the preallocated space at to typed toType...
QMetaType underlyingType() const
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
bool isValid() const
int id(int=0) const
Definition qmetatype.h:476
@ PointerToQObject
Definition qmetatype.h:407
@ IsEnumeration
Definition qmetatype.h:408
Type
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
Definition qmetatype.h:346
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2664
constexpr const char * name() const
Definition qmetatype.h:2681
void * construct(void *where, const void *copy=nullptr) const
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
friend class QVariant
Definition qmetatype.h:797
\inmodule QtCore
Definition qmutex.h:281
The QNetworkAccessManager class allows the application to send network requests and receive replies.
\inmodule QtCore
Definition qobject.h:103
static void registerExtension(QV4::ExecutionEngine *engine)
void init(QV4::ExecutionEngine *)
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
QQmlListProperty< QObject > property
Definition qqmllist_p.h:35
The QQmlListReference class allows the manipulation of QQmlListProperty properties.
Definition qqmllist.h:183
static QQmlType qmlListType(QMetaType metaType)
static const QMetaObject * metaObjectForValueType(QMetaType type)
static const QQmlPrivate::CachedQmlUnit * findCachedCompilationUnit(const QUrl &uri, CacheMode mode, CachedUnitLookupError *status)
static void registerExtension(QV4::ExecutionEngine *engine)
static QUrl normalize(const QUrl &unNormalizedUrl)
bool isSequentialContainer() const
Definition qqmltype.cpp:658
QMetaSequence listMetaSequence() const
Definition qqmltype.cpp:678
static bool populateValueType(QMetaType targetMetaType, void *target, const QV4::Value &source)
static QVariant createValueType(const QJSValue &, QMetaType)
\inmodule QtCore \reentrant
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
The QSequentialIterable class is an iterable interface for a container in a QVariant.
Definition qset.h:19
const_iterator constBegin() const noexcept
Definition qset.h:140
iterator insert(const T &value)
Definition qset.h:156
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5881
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6028
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8095
\inmodule QtCore
static void yieldCurrentThread()
Definition qthread.cpp:1054
\inmodule QtCore \reentrant
Definition qdatetime.h:224
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3445
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2497
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2725
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
static QQmlRefPointer< QV4::CompiledData::CompilationUnit > compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList< QQmlJS::DiagnosticMessage > *diagnostics)
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
Definition qv4mm_p.h:199
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:298
PersistentValueStorage * m_persistentValues
Definition qv4mm_p.h:408
ManagedType::Data * allocWithStringData(std::size_t unmanagedSize, Arg1 &&arg1)
Definition qv4mm_p.h:272
ManagedType::Data * allocIC()
Definition qv4mm_p.h:333
ObjectType::Data * allocObject(Heap::InternalClass *ic, Args &&... args)
Definition qv4mm_p.h:282
\inmodule QtCore
Definition qvariant.h:65
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
bool convert(QMetaType type)
Casts the variant to the requested type, targetType.
T value() const &
Definition qvariant.h:517
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:715
int userType() const
Definition qvariant.h:339
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:537
Private d
Definition qvariant.h:673
QMetaType metaType() const
const void * constData() const
Definition qvariant.h:451
EGLContext ctx
QString str
[2]
QMap< QString, QString > map
[6]
QString text
QDate date
[1]
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Scoped< FunctionObject > ScopedFunctionObject
quint64 ReturnedValue
Scoped< String > ScopedString
StackProperties stackProperties()
@ Attr_Invalid
@ Attr_NotConfigurable
@ Attr_Data
@ Attr_NotEnumerable
@ Attr_ReadOnly
@ Attr_NotWritable
@ Attr_ReadOnly_ButConfigurable
@ Attr_Accessor
static const void * symbol()
Definition qctf_p.h:75
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Q_CORE_EXPORT char * qstrdup(const char *)
#define Q_UNLIKELY(x)
QMap< QString, QVariant > QVariantMap
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static AnchorData * createSequence(Graph< AnchorVertex, AnchorData > *graph, AnchorVertex *before, const QList< AnchorVertex * > &vertices, AnchorVertex *after)
QList< QVariant > QVariantList
Definition qjsonarray.h:15
#define qWarning
Definition qlogging.h:167
static ControlElement< T > * ptr(QWidget *widget)
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
#define Q_INFINITY
Definition qnumeric.h:77
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum src
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLuint start
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
const GLubyte * c
GLuint GLfloat * val
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLenum GLsizei len
GLubyte * pattern
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
static QString jsStack(QV4::ExecutionEngine *engine)
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
T qmlGetConfigOption(const char *var)
void * qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
void qt_rem_qmlxmlhttprequest(ExecutionEngine *, void *d)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static QList< QVariant > toList(const char **buf, int count)
SSL_CTX int void * arg
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define QT_CONFIG(feature)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
unsigned long ulong
Definition qtypes.h:35
quint64 qulonglong
Definition qtypes.h:64
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
unsigned short ushort
Definition qtypes.h:33
qint64 qlonglong
Definition qtypes.h:63
static const uint base
Definition qurlidna.cpp:20
void qt_add_domexceptions(ExecutionEngine *e)
static char * v4StackTrace(const ExecutionContext *context)
static QObject * qtObjectFromJS(const QV4::Value &value)
static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects=nullptr, JSToQVariantConversionBehavior behavior=JSToQVariantConversionBehavior::Safish)
Q_QML_EXPORT char * qt_v4StackTraceForEngine(void *executionEngine)
static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap)
static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
static QSequentialIterable jsvalueToSequence(const QJSValue &value)
ReturnType convertJSValueToVariantType(const QJSValue &value)
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects)
JSToQVariantConversionBehavior
static QtMetaContainerPrivate::QMetaSequenceInterface emptySequenceInterface()
static QVariantMap objectToVariantMap(const QV4::Object *o, V4ObjectSet *visitedObjects, JSToQVariantConversionBehavior conversionBehvior)
static ExecutionEngine::DiskCacheOptions transFormDiskCache(const char *v)
static QtMetaContainerPrivate::QMetaSequenceInterface sequenceInterface()
Q_QML_EXPORT char * qt_v4StackTrace(void *executionContext)
static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result)
static QBasicAtomicInt engineSerial
QSet< QV4::Heap::Object * > V4ObjectSet
static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value)
bool convertToIterable(QMetaType metaType, void *data, Source *sequence)
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
static int toInt(const QChar &qc, int R)
void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
const char property[13]
Definition qwizard.cpp:100
const char className[16]
[1]
Definition qwizard.cpp:99
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
obj metaObject() -> className()
QObject::connect nullptr
QVariant variant
[1]
QDateTime dateTime
[12]
QSharedPointer< T > other(t)
[5]
QFrame frame
[0]
QJSValueList args
QJSEngine engine
[0]
QJSValue const * data
\inmodule QtCore
static void registerStringLocaleCompare(QV4::ExecutionEngine *engine)
Type type() const
static ReturnedValue method_get_species(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static QDate dateTimeToDate(const QDateTime &dateTime)
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
const void * cppStackLimit
IdentifierTable * identifierTable
Heap::InternalClass * internalClasses(InternalClassType icType)
Heap::InternalClass * classes[NClasses]
MemoryManager * memoryManager
const void * cppStackBase
CppStackFrame * currentStackFrame
static ReturnedValue method_get_stack(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
Heap::QmlContext * qmlContext() const
FunctionObject * promiseCtor() const
Heap::Object * newSetIteratorObject(Object *o)
static bool metaTypeFromJS(const Value &value, QMetaType type, void *data)
WTF::PageAllocation * gcStack
Object * typeErrorPrototype() const
ExecutionContext * rootContext() const
Symbol * symbol_iterator() const
ReturnedValue throwUnimplemented(const QString &message)
QQmlRefPointer< QQmlContextData > callingQmlContext() const
StackTrace exceptionStackTrace
WTF::PageAllocation * jsStack
QQmlRefPointer< ExecutableCompilationUnit > insertCompilationUnit(QQmlRefPointer< QV4::CompiledData::CompilationUnit > &&unit)
Object * iteratorPrototype() const
FunctionObject * objectCtor() const
FunctionObject * urlSearchParamsCtor() const
FunctionObject * regExpCtor() const
QV4::Debugging::Debugger * debugger() const
String * id_arguments() const
FunctionObject * booleanCtor() const
QQmlError catchExceptionAsQmlError()
String * id_callee() const
static QVariant toVariantLossy(const QV4::Value &value)
Heap::DateObject * newDateObject(double dateTime)
Object * urlPrototype() const
Heap::PromiseObject * newPromiseObject()
Object * dataViewPrototype() const
ReturnedValue throwRangeError(const Value &value)
Object * stringPrototype() const
FunctionObject * dateCtor() const
String * id_length() const
void setProfiler(Profiling::Profiler *)
Heap::Object * newURIErrorObject(const QString &message)
Object * arrayPrototype() const
String * id_constructor() const
FunctionObject * evalErrorCtor() const
Heap::Object * newNumberObject(double value)
Object * weakSetPrototype() const
ReturnedValue throwError(const Value &value)
ReturnedValue throwReferenceError(const Value &value)
Object * stringIteratorPrototype() const
void markObjects(MarkStack *markStack)
FunctionObject * typedArrayCtors
QV4::ReturnedValue fromVariant(const QVariant &)
void setQmlEngine(QQmlEngine *engine)
Object * variantPrototype() const
static QVariantMap variantMapFromJS(const QV4::Object *o)
Heap::Object * newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
Object * weakMapPrototype() const
Heap::Object * newSymbolObject(const Symbol *symbol)
String * id_toString() const
Heap::Object * newEvalErrorObject(const QString &message)
Object * mapIteratorPrototype() const
Heap::UrlSearchParamsObject * newUrlSearchParamsObject()
String * id_prototype() const
Object * numberPrototype() const
String * id_lastIndex() const
Heap::Object * newObject()
QV4::ReturnedValue global()
static int registerExtension()
int consoleCountHelper(const QString &file, quint16 line, quint16 column)
FunctionObject * urlCtor() const
QML_NEARLY_ALWAYS_INLINE Value * jsAlloca(int nValues)
String * id_caller() const
Heap::Object * newMapIteratorObject(Object *o)
FunctionObject * typeErrorCtor() const
QQmlRefPointer< ExecutableCompilationUnit > compilationUnitForUrl(const QUrl &url) const
String * id_toLocaleString() const
FunctionObject * referenceErrorCtor() const
Object * rangeErrorPrototype() const
String * id_name() const
ExecutableAllocator * executableAllocator
int safeForAllocLength(qint64 len64)
Object * setPrototype() const
Heap::UrlObject * newUrlObject()
QQmlRefPointer< ExecutableCompilationUnit > compileModule(const QUrl &url)
FunctionObject * arrayBufferCtor() const
Object * forInIteratorPrototype() const
Module moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer=nullptr) const
Heap::String * newString(char16_t c)
Heap::String * newIdentifier(const QString &text)
String * id_index() const
const QSet< QString > & illegalNames() const
Heap::Object * newBooleanObject(bool b)
static QMutex * registrationMutex()
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols=true)
Object * uRIErrorPrototype() const
Object * datePrototype() const
EvalFunction * evalFunction() const
FunctionObject * functionCtor() const
FunctionObject * syntaxErrorCtor() const
Promise::ReactionHandler * getPromiseReactionHandler()
ExecutionEngine(QJSEngine *jsEngine=nullptr)
WTF::BumpPointerAllocator * bumperPointerAllocator
String * id_input() const
ExecutableAllocator * regExpAllocator
Object * intrinsicTypedArrayPrototype() const
Object * objectPrototype() const
Symbol * symbol_hasInstance() const
FunctionObject * errorCtor() const
StackTrace stackTrace(int frameLimit=-1) const
ReturnedValue throwURIError(const Value &msg)
FunctionObject * symbolCtor() const
QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data)
QUrl resolvedUrl(const QString &file)
void setExtensionData(int, Deletable *)
Object * syntaxErrorPrototype() const
RegExpCache * regExpCache
Object * sharedArrayBufferPrototype() const
static QJSPrimitiveValue createPrimitive(const Value &v)
FunctionObject * mapCtor() const
Object * booleanPrototype() const
Object * setIteratorPrototype() const
Heap::Object * newReferenceErrorObject(const QString &message)
void setDebugger(Debugging::Debugger *)
Object * symbolPrototype() const
Heap::InternalClass * newClass(Heap::InternalClass *other)
void freezeObject(const QV4::Value &value)
void startTimer(const QString &timerName)
Object * functionPrototype() const
FunctionObject * uRIErrorCtor() const
FunctionObject * generatorFunctionCtor() const
Object * urlSearchParamsPrototype() const
Heap::Object * newForInIteratorObject(Object *o)
Heap::Object * newRangeErrorObject(const QString &message)
FunctionObject * arrayCtor() const
Object * promisePrototype() const
FunctionObject * setCtor() const
qint64 stopTimer(const QString &timerName, bool *wasRunning)
Heap::ArrayObject * newArrayObject(int count=0)
Object * arrayIteratorPrototype() const
FunctionObject * thrower() const
Object * sequencePrototype() const
Heap::Object * newTypeErrorObject(const QString &message)
Object * arrayBufferPrototype() const
FunctionObject * intrinsicTypedArrayCtor() const
Heap::Object * newVariantObject(const QMetaType type, const void *data)
Heap::Object * newStringObject(const String *string)
FunctionObject * rangeErrorCtor() const
FunctionObject * dataViewCtor() const
Object * typedArrayPrototype
QV4::Value * registerNativeModule(const QUrl &url, const QV4::Value &module)
QV4::ReturnedValue fromData(QMetaType type, const void *ptr, Heap::Object *parent=nullptr, int property=-1, uint flags=0)
ReturnedValue throwSyntaxError(const QString &message)
QObject * qmlScopeObject() const
Object * propertyListPrototype() const
DiskCacheOptions diskCacheOptions() const
Object * evalErrorPrototype() const
String * id_valueOf() const
Heap::Object * newArrayIteratorObject(Object *o)
int maxJSStackSize() const
int maxGCStackSize() const
QQmlRefPointer< ExecutableCompilationUnit > executableCompilationUnit(QQmlRefPointer< QV4::CompiledData::CompilationUnit > &&unit)
Object * regExpPrototype() const
ReturnedValue catchException(StackTrace *trace=nullptr)
Heap::ArrayBuffer * newArrayBuffer(const QByteArray &array)
FunctionObject * weakSetCtor() const
FunctionObject * weakMapCtor() const
FunctionObject * stringCtor() const
Heap::RegExpObject * newRegExpObject(const QString &pattern, int flags)
ReturnedValue throwTypeError()
MultiplyWrappedQObjectMap * m_multiplyWrappedQObjects
FunctionObject * numberCtor() const
FunctionObject * sharedArrayBufferCtor() const
Heap::Object * newErrorObject(const Value &value)
Object * mapPrototype() const
Module loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer=nullptr)
Object * errorPrototype() const
Heap::InternalClass * newInternalClass(const VTable *vtable, Object *prototype)
QV4::Profiling::Profiler * profiler() const
ExecutionContext * currentContext() const
void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt, int argc, void **args, QMetaType *types)
Object * generatorPrototype() const
Object * referenceErrorPrototype() const
void lockObject(const QV4::Value &value)
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
ReturnedValue name() const
ReturnedValue callAsConstructor(const Value *argv, int argc, const Value *newTarget=nullptr) const
QUrl finalUrl() const
static void init(Object *globalObject, QJSEngine::Extensions extensions)
static ReturnedValue method_unescape(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_parseInt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_parseFloat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_isNaN(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
isNaN [15.1.2.4]
static ReturnedValue method_isFinite(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
isFinite [15.1.2.5]
static ReturnedValue method_encodeURIComponent(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
encodeURIComponent [15.1.3.4]
static ReturnedValue method_decodeURI(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
decodeURI [15.1.3.1]
static ReturnedValue method_decodeURIComponent(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
decodeURIComponent [15.1.3.2]
static ReturnedValue method_encodeURI(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
encodeURI [15.1.3.3]
static ReturnedValue method_escape(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
ReturnedValue asReturnedValue() const
Definition qv4value_p.h:342
Pointer< InternalClass *, 0 > internalClass
Definition qv4heap_p.h:63
void init(ExecutionEngine *engine)
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
SharedInternalClassData< PropertyKey > nameMap
Q_REQUIRED_RESULT InternalClass * changePrototype(Heap::Object *proto)
Q_REQUIRED_RESULT InternalClass * changeVTable(const VTable *vt)
void markObjects(MarkStack *markStack)
static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object)
static QJsonArray toJsonArray(const QV4::Object *o)
static ReturnedValue fromJsonArray(ExecutionEngine *engine, const QJsonArray &array)
static QJsonObject toJsonObject(const QV4::Object *o)
static QJsonValue toJsonValue(const QV4::Value &value)
Heap::InternalClass * internalClass() const
ExecutionEngine * engine() const
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
const Value * propertyData(uint index) const
const VTable * vtable() const
void defineReadonlyProperty(const QString &name, const Value &value)
Heap::Object * getPrototypeOf() const
void insertMember(StringOrSymbol *s, const Value &v, PropertyAttributes attributes=Attr_Data)
static void free(Value *v)
void setConfigurable(bool b)
static V4_NEEDS_DESTROY ReturnedValue create(ExecutionEngine *engine, const QMetaObject *metaObject)
static void initializeBindings(ExecutionEngine *engine)
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object)
static ReturnedValue wrapConst(ExecutionEngine *engine, QObject *object)
static ReturnedValue create(ExecutionEngine *engine, const void *data, const QMetaObject *metaObject, QMetaType type, Heap::Object *object, int property, Heap::ReferenceObject::Flags flags)
static V4_NEEDS_DESTROY ReturnedValue create(ExecutionEngine *engine, QObject *object, int propId, QMetaType propType)
static Heap::RegExp * create(ExecutionEngine *engine, const QString &pattern, uint flags=CompiledData::RegExp::RegExp_NoFlags)
ExecutionEngine * engine
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, QMetaType type, QMetaSequence metaSequence, const void *data, Heap::Object *object, int propertyIndex, Heap::ReferenceObject::Flags flags)
static QVariant toVariant(const Sequence *object)
static ReturnedValue fromData(QV4::ExecutionEngine *engine, QMetaType type, QMetaSequence metaSequence, const void *data)
constexpr ReturnedValue asReturnedValue() const
PropertyKey propertyKey() const
static V4_NEEDS_DESTROY Heap::Symbol * create(ExecutionEngine *e, const QString &s)
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
Definition qv4value_p.h:55
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
static Value fromDouble(double d)
Definition qv4value_p.h:199
const T * as() const
Definition qv4value_p.h:132
QString toQStringNoThrow() const
Definition qv4value.cpp:122
static constexpr Value emptyValue()
Definition qv4value_p.h:179
static void markCustom(Engine *engine, F &&markFunction)
uchar data[MaxInternalSize]
Definition qvariant.h:112
void wrapper()