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;
743
747 ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
748
749 for (int i = 0; i < NTypedArrayTypes; ++i) {
750 static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(this, Heap::TypedArray::Type(i));
751 static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
752 typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
753 }
754
755 //
756 // set up the global object
757 //
758 rootContext()->d()->activation.set(scope.engine, globalObject->d());
760
764 FunctionObject *numberObject = numberCtor();
765 globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
781
789
790 for (int i = 0; i < NTypedArrayTypes; ++i)
792 ScopedObject o(scope);
798
800 globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN()));
802
803
806
807 // ES6: 20.1.2.12 & 20.1.2.13:
808 // parseInt and parseFloat must be the same FunctionObject on the global &
809 // Number object.
810 {
811 QString piString(QStringLiteral("parseInt"));
812 QString pfString(QStringLiteral("parseFloat"));
813 Scope scope(this);
814 ScopedString pi(scope, newIdentifier(piString));
815 ScopedString pf(scope, newIdentifier(pfString));
818 globalObject->defineDefaultProperty(piString, parseIntFn);
819 globalObject->defineDefaultProperty(pfString, parseFloatFn);
820 numberObject->defineDefaultProperty(piString, parseIntFn);
821 numberObject->defineDefaultProperty(pfString, parseFloatFn);
822 }
823
832
834 scope,
836 t->defineReadonlyProperty(id_length(), Value::fromInt32(0));
837 t->setInternalClass(t->internalClass()->cryopreserved());
839
840 ScopedProperty pd(scope);
841 pd->value = thrower();
842 pd->set = thrower();
845
847
848 m_delayedCallQueue.init(this);
849 isInitialized = true;
850}
851
853{
854 for (auto val : nativeModules) {
856 }
857 nativeModules.clear();
858 qDeleteAll(m_extensionData);
861 delete identifierTable;
862 delete memoryManager;
863
864 for (const auto &cu : std::as_const(m_compilationUnits)) {
865 Q_ASSERT(cu->engine == this);
866 cu->clear();
867 cu->engine = nullptr;
868 }
869 m_compilationUnits.clear();
870
872 delete regExpCache;
873 delete regExpAllocator;
874 delete executableAllocator;
875 jsStack->deallocate();
876 delete jsStack;
877 gcStack->deallocate();
878 delete gcStack;
879
880#if QT_CONFIG(qml_xml_http_request)
881 qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
882 m_xmlHttpRequestData = nullptr;
883#endif
884}
885
886#if QT_CONFIG(qml_debug)
888{
889 Q_ASSERT(!m_debugger);
890 m_debugger.reset(debugger);
891}
892
894{
895 Q_ASSERT(!m_profiler);
896 m_profiler.reset(profiler);
897}
898#endif // QT_CONFIG(qml_debug)
899
901{
902 Scope scope(this);
903 Scoped<ExecutionContext> r(scope, memoryManager->allocManaged<ExecutionContext>());
904 r->d_unchecked()->init(Heap::ExecutionContext::Type_GlobalContext);
905 r->d()->activation.set(this, globalObject->d());
908 jsObjects[IntegerNull] = Encode((int)0);
909}
910
917
919{
920 Scope scope(this);
921 Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable));
922 return ic->changePrototype(prototype ? prototype->d() : nullptr);
923}
924
926{
927 return memoryManager->allocate<Object>();
928}
929
931{
932 return memoryManager->allocObject<Object>(internalClass);
933}
934
939
941{
942 Scope scope(this);
944 s->toPropertyKey();
945 return s->d();
946}
947
948Heap::Object *ExecutionEngine::newStringObject(const String *string)
949{
951}
952
957
959{
961}
962
964{
966}
967
969{
970 Scope scope(this);
972
973 if (count) {
974 if (count < 0x1000)
975 object->arrayReserve(count);
976 object->setArrayLengthUnchecked(count);
977 }
978 return object->d();
979}
980
982{
983 Scope scope(this);
985
986 if (length) {
987 size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
989 d->init();
990 d->type = Heap::ArrayData::Simple;
991 d->offset = 0;
992 d->values.alloc = length;
993 d->values.size = length;
994 // this doesn't require a write barrier, things will be ok, when the new array data gets inserted into
995 // the parent object
996 memcpy(&d->values.values, values, length*sizeof(Value));
997 a->d()->arrayData.set(this, d);
998 a->setArrayLengthUnchecked(length);
999 }
1000 return a->d();
1001}
1002
1007
1012
1017
1022
1024{
1026}
1027
1029{
1031}
1032
1034 QDate date, Heap::Object *parent, int index, uint flags)
1035{
1037 date, parent, index, Heap::ReferenceObject::Flags(flags));
1038}
1039
1041 QTime time, Heap::Object *parent, int index, uint flags)
1042{
1044 time, parent, index, Heap::ReferenceObject::Flags(flags));
1045}
1046
1048 QDateTime dateTime, Heap::Object *parent, int index, uint flags)
1049{
1051 dateTime, parent, index, Heap::ReferenceObject::Flags(flags));
1052}
1053
1055{
1056 Scope scope(this);
1057 Scoped<RegExp> re(scope, RegExp::create(this, pattern, static_cast<CompiledData::RegExp::Flags>(flags)));
1058 return newRegExpObject(re);
1059}
1060
1062{
1063 return memoryManager->allocate<RegExpObject>(re);
1064}
1065
1066#if QT_CONFIG(regularexpression)
1067Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
1068{
1069 return memoryManager->allocate<RegExpObject>(re);
1070}
1071#endif
1072
1074{
1075 return memoryManager->allocate<UrlObject>();
1076}
1077
1079{
1080 Scope scope(this);
1081 Scoped<UrlObject> urlObject(scope, newUrlObject());
1082 urlObject->setUrl(url);
1083 return urlObject->d();
1084}
1085
1086Heap::UrlSearchParamsObject *ExecutionEngine::newUrlSearchParamsObject()
1087{
1089}
1090
1092{
1093 return ErrorObject::create<ErrorObject>(this, value, errorCtor());
1094}
1095
1097{
1098 return ErrorObject::create<ErrorObject>(this, message);
1099}
1100
1102{
1103 return ErrorObject::create<SyntaxErrorObject>(this, message);
1104}
1105
1107{
1108 return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
1109}
1110
1111
1113{
1114 return ErrorObject::create<ReferenceErrorObject>(this, message);
1115}
1116
1118{
1119 return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
1120}
1121
1122
1124{
1125 return ErrorObject::create<TypeErrorObject>(this, message);
1126}
1127
1129{
1130 return ErrorObject::create<RangeErrorObject>(this, message);
1131}
1132
1134{
1135 return ErrorObject::create<URIErrorObject>(this, message, uRIErrorCtor());
1136}
1137
1139{
1140 if (!m_reactionHandler) {
1141 m_reactionHandler.reset(new Promise::ReactionHandler);
1142 }
1143
1144 Scope scope(this);
1145 Scoped<PromiseObject> object(scope, memoryManager->allocate<PromiseObject>(this));
1146 return object->d();
1147}
1148
1149Heap::Object *ExecutionEngine::newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability)
1150{
1151 if (!m_reactionHandler) {
1152 m_reactionHandler.reset(new Promise::ReactionHandler);
1153 }
1154
1155 Scope scope(this);
1156 Scoped<CapabilitiesExecutorWrapper> executor(scope, memoryManager->allocate<CapabilitiesExecutorWrapper>());
1157 executor->d()->capabilities.set(this, capability->d());
1159
1160 ScopedObject object(scope, thisObject->callAsConstructor(executor, 1));
1161 return object->d();
1162}
1163
1165{
1166 Q_ASSERT(m_reactionHandler);
1167 return m_reactionHandler.data();
1168}
1169
1171{
1172 return ErrorObject::create<URIErrorObject>(this, message);
1173}
1174
1176{
1177 return ErrorObject::create<EvalErrorObject>(this, message);
1178}
1179
1180Heap::Object *ExecutionEngine::newVariantObject(const QMetaType type, const void *data)
1181{
1183}
1184
1186{
1187 Scope scope(this);
1189 return obj->d();
1190}
1191
1193{
1194 return memoryManager->allocate<MapIteratorObject>(o->d(), this);
1195}
1196
1198{
1199 return memoryManager->allocate<SetIteratorObject>(o->d(), this);
1200}
1201
1203{
1204 return memoryManager->allocate<ArrayIteratorObject>(o->d(), this);
1205}
1206
1207Heap::QmlContext *ExecutionEngine::qmlContext() const
1208{
1209 return currentStackFrame
1210 ? static_cast<Heap::QmlContext *>(qmlContext(currentContext()->d()))
1211 : nullptr;
1212}
1213
1215{
1216 Heap::QmlContext *ctx = qmlContext();
1217 if (!ctx)
1218 return nullptr;
1219
1220 return ctx->qml()->scopeObject;
1221}
1222
1223QQmlRefPointer<QQmlContextData> ExecutionEngine::callingQmlContext() const
1224{
1225 Heap::QmlContext *ctx = qmlContext();
1226 if (!ctx)
1227 return nullptr;
1228
1229 return ctx->qml()->context;
1230}
1231
1233{
1234 StackTrace stack;
1235
1237 while (f && frameLimit) {
1239 frame.source = f->source();
1240 frame.function = f->function();
1241 frame.line = f->lineNumber();
1242
1243 stack.append(frame);
1244 if (f->isJSTypesFrame()) {
1245 if (static_cast<JSTypesStackFrame *>(f)->isTailCalling()) {
1247 frame.function = QStringLiteral("[elided tail calls]");
1248 stack.append(frame);
1249 }
1250 }
1251 --frameLimit;
1252 f = f->parentFrame();
1253 }
1254
1255 return stack;
1256}
1257
1258/* Helper and "C" linkage exported function to format a GDBMI stacktrace for
1259 * invocation by a debugger.
1260 * Sample GDB invocation: print qt_v4StackTrace((void*)0x7fffffffb290)
1261 * Sample CDB invocation: .call Qt5Qmld!qt_v4StackTrace(0x7fffffffb290) ; gh
1262 * Note: The helper is there to suppress MSVC warning 4190 about anything
1263 * with UDT return types in a "C" linkage function. */
1264
1265static inline char *v4StackTrace(const ExecutionContext *context)
1266{
1269 str << "stack=[";
1270 if (context && context->engine()) {
1271 const QVector<StackFrame> stackTrace = context->engine()->stackTrace(20);
1272 for (int i = 0; i < stackTrace.size(); ++i) {
1273 if (i)
1274 str << ',';
1275 const QUrl url(stackTrace.at(i).source);
1277 str << "frame={level=\"" << i << "\",func=\"" << stackTrace.at(i).function
1278 << "\",file=\"" << fileName << "\",fullname=\"" << fileName
1279 << "\",line=\"" << qAbs(stackTrace.at(i).line) << "\",language=\"js\"}";
1280 }
1281 }
1282 str << ']';
1283 return qstrdup(result.toLocal8Bit().constData());
1284}
1285
1286extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
1287{
1288 return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
1289}
1290
1291extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
1292{
1293 auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
1294 return v4StackTrace(engine->currentContext());
1295}
1296
1298{
1299 QUrl src(file);
1300 if (!src.isRelative())
1301 return src;
1302
1303 QUrl base;
1305 while (f) {
1306 if (f->v4Function) {
1307 base = f->v4Function->finalUrl();
1308 break;
1309 }
1310 f = f->parentFrame();
1311 }
1312
1313 if (base.isEmpty() && globalCode)
1315
1316 if (base.isEmpty())
1317 return src;
1318
1319 return base.resolved(src);
1320}
1321
1323{
1324 for (int i = 0; i < NClasses; ++i) {
1326 c->mark(markStack);
1327 }
1328
1329 identifierTable->markObjects(markStack);
1330
1331 for (const auto &compilationUnit : std::as_const(m_compilationUnits))
1332 compilationUnit->markObjects(markStack);
1333}
1334
1336{
1337 // we can get in here with an exception already set, as the runtime
1338 // doesn't check after every operation that can throw.
1339 // in this case preserve the first exception to give correct error
1340 // information
1341 if (hasException)
1342 return Encode::undefined();
1343
1344 hasException = true;
1346 QV4::Scope scope(this);
1348 if (!!error)
1349 exceptionStackTrace = *error->d()->stackTrace;
1350 else
1352
1354 debug->aboutToThrow();
1355
1356 return Encode::undefined();
1357}
1358
1370
1372{
1373 Scope scope(this);
1374 ScopedValue v(scope, newString(message));
1375 v = newErrorObject(v);
1376 return throwError(v);
1377}
1378
1385
1392
1393
1395{
1396 Scope scope(this);
1397 ScopedObject error(scope, newTypeErrorObject(QStringLiteral("Type error")));
1398 return throwError(error);
1399}
1400
1407
1409{
1410 Scope scope(this);
1411 QString msg = name + QLatin1String(" is not defined");
1413 return throwError(error);
1414}
1415
1417{
1418 Scope scope(this);
1419 ScopedString s(scope, value.toString(this));
1420 QString msg = s->toQString() + QLatin1String(" is not defined");
1422 return throwError(error);
1423}
1424
1432
1439
1441{
1442 Scope scope(this);
1443 ScopedString s(scope, value.toString(this));
1444 QString msg = s->toQString() + QLatin1String(" out of range");
1446 return throwError(error);
1447}
1448
1450{
1451 Scope scope(this);
1453 return throwError(error);
1454}
1455
1457{
1458 Scope scope(this);
1459 ScopedValue v(scope, newString(QLatin1String("Unimplemented ") + message));
1460 v = newErrorObject(v);
1461 return throwError(v);
1462}
1463
1464
1466{
1468 QV4::Scope scope(this);
1469 QV4::ScopedValue exception(scope, catchException(&trace));
1471 if (!trace.isEmpty()) {
1472 QV4::StackFrame frame = trace.constFirst();
1473 error.setUrl(QUrl(frame.source));
1474 error.setLine(qAbs(frame.line));
1475 error.setColumn(frame.column);
1476 }
1477 QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
1478 error.setDescription(exception->toQStringNoThrow());
1479 return error;
1480}
1481
1482// Variant conversion code
1483
1484typedef QSet<QV4::Heap::Object *> V4ObjectSet;
1486static QVariant toVariant(
1487 const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior,
1488 V4ObjectSet *visitedObjects);
1489static QObject *qtObjectFromJS(const QV4::Value &value);
1490static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr,
1492static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result);
1495{
1496 return v4->metaTypeToJS(value.metaType(), value.constData());
1497}
1498
1500 V4ObjectSet *visitedObjects)
1501{
1502 Q_ASSERT (!value.isEmpty());
1503
1505 return v->d()->data();
1506
1507 if (metaType == QMetaType::fromType<bool>())
1508 return QVariant(value.toBoolean());
1509
1510 if (metaType == QMetaType::fromType<double>())
1511 return QVariant(value.toNumber());
1512
1513 if (metaType == QMetaType::fromType<float>())
1514 return QVariant(float(value.toNumber()));
1515
1516 if (metaType == QMetaType::fromType<QJsonValue>())
1518
1519 if (metaType == QMetaType::fromType<QJSValue>())
1521
1522 if (const QV4::Object *o = value.as<QV4::Object>()) {
1523 QV4::Scope scope(o->engine());
1524 QV4::ScopedObject object(scope, o);
1525 if (metaType == QMetaType::fromType<QJsonObject>()
1526 && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
1529 return QVariant::fromValue<QObject *>(wrapper->object());
1530 } else if (object->as<QV4::QQmlContextWrapper>()) {
1531 return QVariant();
1533 return w->toVariant();
1535 return v->toVariant();
1536 } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
1537 return l->toVariant();
1538 } else if (QV4::Sequence *s = object->as<QV4::Sequence>()) {
1540 }
1541 }
1542
1543 if (const QV4::ArrayObject *o = value.as<ArrayObject>()) {
1544 QV4::Scope scope(o->engine());
1545 QV4::ScopedArrayObject a(scope, o);
1546 if (metaType == QMetaType::fromType<QList<QObject *>>()) {
1547 QList<QObject *> list;
1548 uint length = a->getLength();
1549 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
1550 for (uint ii = 0; ii < length; ++ii) {
1551 qobjectWrapper = a->get(ii);
1552 if (!!qobjectWrapper) {
1553 list << qobjectWrapper->object();
1554 } else {
1555 list << 0;
1556 }
1557 }
1558
1559 return QVariant::fromValue<QList<QObject*> >(list);
1560 } else if (metaType == QMetaType::fromType<QJsonArray>()) {
1562 }
1563
1565 if (retn.isValid())
1566 return retn;
1567
1568 if (metaType.isValid()) {
1569 retn = QVariant(metaType, nullptr);
1570 auto retnAsIterable = retn.value<QSequentialIterable>();
1571 if (retnAsIterable.metaContainer().canAddValue()) {
1572 QMetaType valueMetaType = retnAsIterable.metaContainer().valueMetaType();
1573 auto const length = a->getLength();
1574 QV4::ScopedValue arrayValue(scope);
1575 for (qint64 i = 0; i < length; ++i) {
1576 arrayValue = a->get(i);
1578 arrayValue, valueMetaType);
1579 if (asVariant.isValid()) {
1580 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1581 continue;
1582 }
1583
1584 if (QMetaType::canConvert(QMetaType::fromType<QJSValue>(), valueMetaType)) {
1585 // before attempting a conversion from the concrete types,
1586 // check if there exists a conversion from QJSValue -> out type
1587 // prefer that one for compatibility reasons
1589 arrayValue->asReturnedValue()));
1590 if (asVariant.convert(valueMetaType)) {
1591 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1592 continue;
1593 }
1594 }
1595
1596 asVariant = toVariant(arrayValue, valueMetaType, JSToQVariantConversionBehavior::Never, visitedObjects);
1597 if (valueMetaType == QMetaType::fromType<QVariant>()) {
1598 retnAsIterable.metaContainer().addValue(retn.data(), &asVariant);
1599 } else {
1600 auto originalType = asVariant.metaType();
1601 bool couldConvert = asVariant.convert(valueMetaType);
1602 if (!couldConvert && originalType.isValid()) {
1603 // If the original type was void, we're converting a "hole" in a sparse
1604 // array. There is no point in warning about that.
1605 qWarning().noquote()
1606 << QLatin1String("Could not convert array value "
1607 "at position %1 from %2 to %3")
1609 QString::fromUtf8(originalType.name()),
1610 QString::fromUtf8(valueMetaType.name()));
1611 }
1612 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1613 }
1614 }
1615 return retn;
1616 }
1617 }
1618 }
1619
1620 if (value.isUndefined())
1621 return QVariant();
1622 if (value.isNull())
1623 return QVariant::fromValue(nullptr);
1624 if (value.isBoolean())
1625 return value.booleanValue();
1626 if (value.isInteger())
1627 return value.integerValue();
1628 if (value.isNumber())
1629 return value.asDouble();
1630 if (String *s = value.stringValue()) {
1631 const QString &str = s->toQString();
1632 // QChars are stored as a strings
1633 if (metaType == QMetaType::fromType<QChar>() && str.size() == 1)
1634 return str.at(0);
1635 return str;
1636 }
1637 if (const QV4::DateObject *d = value.as<DateObject>()) {
1638 // NOTE: since we convert QTime to JS Date,
1639 // round trip will change the variant type (to QDateTime)!
1640
1641 if (metaType == QMetaType::fromType<QDate>())
1642 return DateObject::dateTimeToDate(d->toQDateTime());
1643
1644 if (metaType == QMetaType::fromType<QTime>())
1645 return d->toQDateTime().time();
1646
1647 if (metaType == QMetaType::fromType<QString>())
1648 return d->toString();
1649
1650 return d->toQDateTime();
1651 }
1652 if (const QV4::UrlObject *d = value.as<UrlObject>())
1653 return d->toQUrl();
1654 if (const ArrayBuffer *d = value.as<ArrayBuffer>())
1655 return d->asByteArray();
1656 if (const Symbol *symbol = value.as<Symbol>()) {
1657 return conversionBehavior == JSToQVariantConversionBehavior::Never
1659 : symbol->descriptiveString();
1660 }
1661
1662 const QV4::Object *object = value.as<QV4::Object>();
1663 Q_ASSERT(object);
1664 QV4::Scope scope(object->engine());
1665 QV4::ScopedObject o(scope, object);
1666
1667#if QT_CONFIG(regularexpression)
1668 if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
1669 return re->toQRegularExpression();
1670#endif
1671
1672 if (metaType.isValid() && !(metaType.flags() & QMetaType::PointerToQObject)) {
1674 if (result.isValid())
1675 return result;
1676 }
1677
1678 if (conversionBehavior == JSToQVariantConversionBehavior::Never)
1679 return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue()));
1680
1681 return objectToVariant(o, visitedObjects, conversionBehavior);
1682}
1683
1688
1690 const Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols)
1691{
1692 auto behavior = createJSValueForObjectsAndSymbols ? JSToQVariantConversionBehavior::Never
1694 return ::toVariant(value, typeHint, behavior, nullptr);
1695}
1696
1698 JSToQVariantConversionBehavior conversionBehvior)
1699{
1701 QV4::Scope scope(o->engine());
1703 QV4::ScopedValue name(scope);
1704 QV4::ScopedValue val(scope);
1705 while (1) {
1706 name = it.nextPropertyNameAsString(val);
1707 if (name->isNull())
1708 break;
1709
1710 QString key = name->toQStringNoThrow();
1712 val, /*type hint*/ QMetaType {},
1713 conversionBehvior, visitedObjects));
1714 }
1715 return map;
1716}
1717
1718static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects,
1719 JSToQVariantConversionBehavior conversionBehvior)
1720{
1721 Q_ASSERT(o);
1722
1723 V4ObjectSet recursionGuardSet;
1724 if (!visitedObjects) {
1725 visitedObjects = &recursionGuardSet;
1726 } else if (visitedObjects->contains(o->d())) {
1727 // Avoid recursion.
1728 // For compatibility with QVariant{List,Map} conversion, we return an
1729 // empty object (and no error is thrown).
1730 if (o->as<ArrayObject>())
1731 return QVariantList();
1732 return QVariantMap();
1733 }
1734 visitedObjects->insert(o->d());
1735
1737
1738 if (o->as<ArrayObject>()) {
1739 QV4::Scope scope(o->engine());
1740 QV4::ScopedArrayObject a(scope, o->asReturnedValue());
1741 QV4::ScopedValue v(scope);
1743
1744 int length = a->getLength();
1745 for (int ii = 0; ii < length; ++ii) {
1746 v = a->get(ii);
1747 list << ::toVariant(v, QMetaType {}, conversionBehvior,
1748 visitedObjects);
1749 }
1750
1751 result = list;
1752 } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()
1753 || (conversionBehvior == JSToQVariantConversionBehavior::Aggressive &&
1754 !o->as<QV4::FunctionObject>())) {
1755 /* FunctionObject is excluded for historical reasons, even though
1756 objects with a custom prototype risk losing information
1757 But the Aggressive path is used only in QJSValue::toVariant
1758 which is documented to be lossy
1759 */
1760 result = objectToVariantMap(o, visitedObjects, conversionBehvior);
1761 } else {
1762 // If it's not a plain object, we can only save it as QJSValue.
1764 }
1765
1766 visitedObjects->remove(o->d());
1767 return result;
1768}
1769
1776 QMetaType metaType, const void *ptr,
1777 QV4::Heap::Object *container, int property, uint flags)
1778{
1779 const auto createSequence = [&](const QMetaSequence metaSequence) {
1780 QV4::Scope scope(this);
1781 QV4::Scoped<Sequence> sequence(scope);
1782 if (container) {
1784 this, metaType, metaSequence, ptr,
1785 container, property, Heap::ReferenceObject::Flags(flags));
1786 } else {
1787 return QV4::SequencePrototype::fromData(this, metaType, metaSequence, ptr);
1788 }
1789 };
1790
1791 const int type = metaType.id();
1792 if (type < QMetaType::User) {
1793 switch (QMetaType::Type(type)) {
1795 case QMetaType::Void:
1796 return QV4::Encode::undefined();
1797 case QMetaType::Nullptr:
1798 case QMetaType::VoidStar:
1799 return QV4::Encode::null();
1800 case QMetaType::Bool:
1801 return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
1802 case QMetaType::Int:
1803 return QV4::Encode(*reinterpret_cast<const int*>(ptr));
1804 case QMetaType::UInt:
1805 return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
1806 case QMetaType::Long:
1807 return QV4::Encode((double)*reinterpret_cast<const long *>(ptr));
1808 case QMetaType::ULong:
1809 return QV4::Encode((double)*reinterpret_cast<const ulong *>(ptr));
1810 case QMetaType::LongLong:
1811 return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
1812 case QMetaType::ULongLong:
1813 return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
1814 case QMetaType::Double:
1815 return QV4::Encode(*reinterpret_cast<const double*>(ptr));
1816 case QMetaType::QString:
1817 return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
1818 case QMetaType::QByteArray:
1819 return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue();
1820 case QMetaType::Float:
1821 return QV4::Encode(*reinterpret_cast<const float*>(ptr));
1822 case QMetaType::Short:
1823 return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
1824 case QMetaType::UShort:
1825 return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
1826 case QMetaType::Char:
1827 return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
1828 case QMetaType::UChar:
1829 return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
1830 case QMetaType::SChar:
1831 return QV4::Encode((int)*reinterpret_cast<const signed char*>(ptr));
1832 case QMetaType::QChar:
1833 return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue();
1834 case QMetaType::Char16:
1835 return newString(QChar(*reinterpret_cast<const char16_t *>(ptr)))->asReturnedValue();
1836 case QMetaType::QDateTime:
1838 *reinterpret_cast<const QDateTime *>(ptr),
1839 container, property, flags));
1840 case QMetaType::QDate:
1842 *reinterpret_cast<const QDate *>(ptr),
1843 container, property, flags));
1844 case QMetaType::QTime:
1846 *reinterpret_cast<const QTime *>(ptr),
1847 container, property, flags));
1848#if QT_CONFIG(regularexpression)
1849 case QMetaType::QRegularExpression:
1850 return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
1851#endif
1852 case QMetaType::QObjectStar:
1853 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1854 case QMetaType::QStringList:
1855 return createSequence(QMetaSequence::fromContainer<QStringList>());
1856 case QMetaType::QVariantList:
1857 return createSequence(QMetaSequence::fromContainer<QVariantList>());
1858 case QMetaType::QVariantMap:
1859 return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr));
1860 case QMetaType::QJsonValue:
1861 return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
1862 case QMetaType::QJsonObject:
1863 return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr));
1864 case QMetaType::QJsonArray:
1865 return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr));
1866 case QMetaType::QPixmap:
1867 case QMetaType::QImage:
1868 // Scarce value types
1869 return QV4::Encode(newVariantObject(metaType, ptr));
1870 default:
1871 break;
1872 }
1873 }
1874
1875 if (metaType.flags() & QMetaType::IsEnumeration)
1876 return fromData(metaType.underlyingType(), ptr, container, property, flags);
1877
1878 QV4::Scope scope(this);
1879 if (metaType == QMetaType::fromType<QQmlListReference>()) {
1880 typedef QQmlListReferencePrivate QDLRP;
1881 QDLRP *p = QDLRP::get((QQmlListReference*)const_cast<void *>(ptr));
1882 if (p->object)
1883 return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType);
1884 else
1885 return QV4::Encode::null();
1886 } else if (auto flags = metaType.flags(); flags & QMetaType::IsQmlList) {
1887 // casting to QQmlListProperty<QObject> is slightly nasty, but it's the
1888 // same QQmlListReference does.
1889 const auto *p = static_cast<const QQmlListProperty<QObject> *>(ptr);
1890 if (p->object)
1891 return QV4::QmlListWrapper::create(scope.engine, *p, metaType);
1892 else
1893 return QV4::Encode::null();
1894 } else if (metaType == QMetaType::fromType<QJSValue>()) {
1896 this, *reinterpret_cast<const QJSValue *>(ptr));
1897 } else if (metaType == QMetaType::fromType<QList<QObject *> >()) {
1898 // XXX Can this be made more by using Array as a prototype and implementing
1899 // directly against QList<QObject*>?
1900 const QList<QObject *> &list = *(const QList<QObject *>*)ptr;
1902 a->arrayReserve(list.size());
1903 QV4::ScopedValue v(scope);
1904 for (int ii = 0; ii < list.size(); ++ii)
1905 a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(this, list.at(ii))));
1906 a->setArrayLengthUnchecked(list.size());
1907 return a.asReturnedValue();
1908 } else if (auto flags = metaType.flags(); flags & QMetaType::PointerToQObject) {
1909 if (flags.testFlag(QMetaType::IsConst))
1910 return QV4::QObjectWrapper::wrapConst(this, *reinterpret_cast<QObject* const *>(ptr));
1911 else
1912 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1913 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
1914 const QJSPrimitiveValue *primitive = static_cast<const QJSPrimitiveValue *>(ptr);
1915 switch (primitive->type()) {
1917 return Encode(primitive->asBoolean());
1919 return Encode(primitive->asInteger());
1921 return newString(primitive->asString())->asReturnedValue();
1923 return Encode::undefined();
1925 return Encode::null();
1927 return Encode(primitive->asDouble());
1928 }
1929 }
1930
1931 if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(metaType)) {
1932 if (container) {
1934 this, ptr, vtmo, metaType,
1935 container, property, Heap::ReferenceObject::Flags(flags));
1936 } else {
1937 return QV4::QQmlValueTypeWrapper::create(this, ptr, vtmo, metaType);
1938 }
1939 }
1940
1941 const QQmlType listType = QQmlMetaType::qmlListType(metaType);
1942 if (listType.isSequentialContainer())
1943 return createSequence(listType.listMetaSequence());
1944
1945 QSequentialIterable iterable;
1946 if (QMetaType::convert(metaType, ptr, QMetaType::fromType<QSequentialIterable>(), &iterable)) {
1947
1948 // If the resulting iterable is useful for anything, turn it into a QV4::Sequence.
1949 const QMetaSequence sequence = iterable.metaContainer();
1950 if (sequence.hasSize() && sequence.canGetValueAtIndex())
1951 return createSequence(sequence);
1952
1953 // As a last resort, try to read the contents of the container via an iterator
1954 // and build a JS array from them.
1955 if (sequence.hasConstIterator() && sequence.canGetValueAtConstIterator()) {
1957 for (auto it = iterable.constBegin(), end = iterable.constEnd(); it != end; ++it)
1958 a->push_back(fromVariant(*it));
1959 return a.asReturnedValue();
1960 }
1961 }
1962
1963 return QV4::Encode(newVariantObject(metaType, ptr));
1964}
1965
1970
1972 const QVariant &variant, Heap::Object *parent, int property, uint flags)
1973{
1974 return fromData(variant.metaType(), variant.constData(), parent, property, flags);
1975}
1976
1978{
1979 Q_ASSERT(o);
1980 V4ObjectSet visitedObjects;
1981 visitedObjects.insert(o->d());
1983}
1984
1985// Converts a QVariantMap to JS.
1986// The result is a new Object object with property names being
1987// the keys of the QVariantMap, and values being the values of
1988// the QVariantMap converted to JS, recursively.
1990{
1991 QV4::Scope scope(v4);
1992 QV4::ScopedObject o(scope, v4->newObject());
1993 QV4::ScopedString s(scope);
1995 QV4::ScopedValue v(scope);
1996 for (QVariantMap::const_iterator it = vmap.constBegin(), cend = vmap.constEnd(); it != cend; ++it) {
1997 s = v4->newIdentifier(it.key());
1998 key = s->propertyKey();
1999 v = variantToJS(v4, it.value());
2000 if (key->isArrayIndex())
2001 o->arraySet(key->asArrayIndex(), v);
2002 else
2003 o->insertMember(s, v);
2004 }
2005 return o.asReturnedValue();
2006}
2007
2008// Converts the meta-type defined by the given type and data to JS.
2009// Returns the value if conversion succeeded, an empty handle otherwise.
2011{
2012 Q_ASSERT(data != nullptr);
2013
2014 if (type == QMetaType::fromType<QVariant>()) {
2015 // unwrap it: this is tested in QJSEngine, and makes the most sense for
2016 // end-user code too.
2017 return fromVariant(*reinterpret_cast<const QVariant*>(data));
2018 } else if (type == QMetaType::fromType<QUrl>()) {
2019 // Create a proper URL object here, rather than a variant.
2020 return newUrlObject(*reinterpret_cast<const QUrl *>(data))->asReturnedValue();
2021 }
2022
2023 return fromData(type, data);
2024}
2025
2027{
2028 return s_maxJSStackSize;
2029}
2030
2032{
2033 return s_maxGCStackSize;
2034}
2035
2043{
2044 if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max())) {
2045 throwRangeError(QStringLiteral("Invalid array length."));
2046 return 0;
2047 }
2048 if (len64 > qint64(this->jsStackLimit - this->jsStackTop)) {
2049 throwRangeError(QStringLiteral("Array too large for apply()."));
2050 return 0;
2051 }
2052 return len64;
2053}
2054
2059
2060QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const QUrl &url)
2061{
2063 const DiskCacheOptions options = diskCacheOptions();
2064 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (options & DiskCache::Aot)
2066 url,
2067 (options & DiskCache::AotByteCode)
2070 &cacheError)
2071 : nullptr) {
2073 QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>(
2074 cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, url.fileName(),
2075 url.toString()));
2076 }
2077
2079 if (!f.open(QIODevice::ReadOnly)) {
2080 throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString()));
2081 return nullptr;
2082 }
2083
2084 const QDateTime timeStamp = QFileInfo(f).lastModified();
2085
2086 const QString sourceCode = QString::fromUtf8(f.readAll());
2087 f.close();
2088
2089 return compileModule(url, sourceCode, timeStamp);
2090}
2091
2092
2093QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(
2094 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
2095{
2096 QList<QQmlJS::DiagnosticMessage> diagnostics;
2097 auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
2098 sourceCode, sourceTimeStamp, &diagnostics);
2099 for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
2100 if (m.isError()) {
2101 throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
2102 return nullptr;
2103 } else {
2104 qWarning() << url << ':' << m.loc.startLine << ':' << m.loc.startColumn
2105 << ": warning: " << m.message;
2106 }
2107 }
2108
2109 return insertCompilationUnit(std::move(unit));
2110}
2111
2112QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compilationUnitForUrl(const QUrl &url) const
2113{
2114 // Gives the _most recently inserted_ CU of that URL. That's what we want.
2115 return m_compilationUnits.value(url);
2116}
2117
2118QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::executableCompilationUnit(
2119 QQmlRefPointer<CompiledData::CompilationUnit> &&unit)
2120{
2121 const QUrl url = unit->finalUrl();
2122 auto [begin, end] = std::as_const(m_compilationUnits).equal_range(url);
2123
2124 for (auto it = begin; it != end; ++it) {
2125 if ((*it)->baseCompilationUnit() == unit)
2126 return *it;
2127 }
2128
2129 auto executableUnit = m_compilationUnits.insert(
2130 url, ExecutableCompilationUnit::create(std::move(unit), this));
2131 // runtime data should not be initialized yet, so we don't need to mark the CU
2132 Q_ASSERT(!(*executableUnit)->runtimeStrings);
2133 return *executableUnit;
2134}
2135
2136QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::insertCompilationUnit(QQmlRefPointer<CompiledData::CompilationUnit> &&unit) {
2137 QUrl url = unit->finalUrl();
2138 auto executableUnit = ExecutableCompilationUnit::create(std::move(unit), this);
2139 /* Compilation Units stored in the engine are part of the gc roots,
2140 so we don't trigger any write-barrier when they are added. Use
2141 markCustom to make sure they are still marked when we insert them */
2142 QV4::WriteBarrier::markCustom(this, [&executableUnit](QV4::MarkStack *ms) {
2143 executableUnit->markObjects(ms);
2144 });
2145 return *m_compilationUnits.insert(std::move(url), std::move(executableUnit));
2146}
2147
2149{
2150 for (auto it = m_compilationUnits.begin(); it != m_compilationUnits.end();) {
2151 if ((*it)->count() == 1)
2152 it = m_compilationUnits.erase(it);
2153 else
2154 ++it;
2155 }
2156}
2157
2159 const QUrl &url, const ExecutableCompilationUnit *referrer) const
2160{
2161 const auto nativeModule = nativeModules.find(url);
2162 if (nativeModule != nativeModules.end())
2163 return Module { nullptr, *nativeModule };
2164
2165 const QUrl resolved = referrer
2166 ? referrer->finalUrl().resolved(QQmlTypeLoader::normalize(url))
2168 auto existingModule = m_compilationUnits.find(resolved);
2169 if (existingModule == m_compilationUnits.end())
2170 return Module { nullptr, nullptr };
2171 return Module { *existingModule, nullptr };
2172}
2173
2175{
2176 const auto nativeModule = nativeModules.constFind(url);
2177 if (nativeModule != nativeModules.cend())
2178 return Module { nullptr, *nativeModule };
2179
2180 const QUrl resolved = referrer
2181 ? referrer->finalUrl().resolved(QQmlTypeLoader::normalize(url))
2183 auto existingModule = m_compilationUnits.constFind(resolved);
2184 if (existingModule != m_compilationUnits.cend())
2185 return Module { *existingModule, nullptr };
2186
2187 auto newModule = compileModule(resolved);
2188 Q_ASSERT(!newModule || m_compilationUnits.contains(resolved, newModule));
2189
2190 return Module { newModule, nullptr };
2191}
2192
2194{
2195 const auto existingModule = nativeModules.constFind(url);
2196 if (existingModule != nativeModules.cend())
2197 return nullptr;
2198
2200 *val = module.asReturnedValue();
2201 nativeModules.insert(url, val);
2202
2203 // Make sure the type loader doesn't try to resolve the script anymore.
2204 if (m_qmlEngine)
2205 QQmlEnginePrivate::get(m_qmlEngine)->typeLoader.injectScript(url, *val);
2206
2207 return val;
2208}
2209
2210static ExecutionEngine::DiskCacheOptions transFormDiskCache(const char *v)
2211{
2212 using DiskCache = ExecutionEngine::DiskCache;
2213
2214 if (v == nullptr)
2215 return DiskCache::Enabled;
2216
2217 ExecutionEngine::DiskCacheOptions result = DiskCache::Disabled;
2218 const QList<QByteArray> options = QByteArray(v).split(',');
2219 for (const QByteArray &option : options) {
2220 if (option == "aot-bytecode")
2221 result |= DiskCache::AotByteCode;
2222 else if (option == "aot-native")
2223 result |= DiskCache::AotNative;
2224 else if (option == "aot")
2225 result |= DiskCache::Aot;
2226 else if (option == "qmlc-read")
2227 result |= DiskCache::QmlcRead;
2228 else if (option == "qmlc-write")
2229 result |= DiskCache::QmlcWrite;
2230 else if (option == "qmlc")
2231 result |= DiskCache::Qmlc;
2232 else
2233 qWarning() << "Ignoring unknown option to QML_DISK_CACHE:" << option;
2234 }
2235
2236 return result;
2237}
2238
2239ExecutionEngine::DiskCacheOptions ExecutionEngine::diskCacheOptions() const
2240{
2241 if (forceDiskCache())
2242 return DiskCache::Enabled;
2243 if (disableDiskCache() || debugger())
2244 return DiskCache::Disabled;
2245 static const DiskCacheOptions options = qmlGetConfigOption<
2246 DiskCacheOptions, transFormDiskCache>("QML_DISK_CACHE");
2247 return options;
2248}
2249
2251 QV4::ExecutionContext *context, int argc, void **args,
2253{
2254 if (!args) {
2255 Q_ASSERT(argc == 0);
2256 void *dummyArgs[] = { nullptr };
2257 QMetaType dummyTypes[] = { QMetaType::fromType<void>() };
2258 function->call(self, dummyArgs, dummyTypes, argc, context);
2259 return;
2260 }
2261 Q_ASSERT(types); // both args and types must be present
2262 // implicitly sets the return value, which is args[0]
2263 function->call(self, args, types, argc, context);
2264}
2265
2267 QV4::ExecutionContext *context, int argc,
2268 const QV4::Value *argv)
2269{
2270 QV4::Scope scope(this);
2271 QV4::ScopedObject jsSelf(scope, QV4::QObjectWrapper::wrap(this, self));
2272 Q_ASSERT(jsSelf);
2273 return function->call(jsSelf, argv, argc, context);
2274}
2275
2281
2283{
2285
2287
2288#if QT_CONFIG(qml_locale)
2292#endif
2293
2294#if QT_CONFIG(qml_xml_http_request)
2296 m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
2297#endif
2298
2300
2301 {
2302 for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
2303 if (globalObject->internalClass()->nameMap.at(i).isString()) {
2305 m_illegalNames.insert(id.toQString());
2306 }
2307 }
2308 }
2309}
2310
2312{
2313 QV4::Scope scope(this);
2314 QtObject *qtObject = new QtObject(this);
2316
2317 QV4::ScopedObject qtObjectWrapper(
2318 scope, QV4::QObjectWrapper::wrap(this, qtObject));
2319 QV4::ScopedObject qtNamespaceWrapper(
2320 scope, QV4::QMetaObjectWrapper::create(this, &Qt::staticMetaObject));
2321 QV4::ScopedObject qtObjectProtoWrapper(
2322 scope, qtObjectWrapper->getPrototypeOf());
2323
2324 qtNamespaceWrapper->setPrototypeOf(qtObjectProtoWrapper);
2325 qtObjectWrapper->setPrototypeOf(qtNamespaceWrapper);
2326
2327 globalObject->defineDefaultProperty(QStringLiteral("Qt"), qtObjectWrapper);
2328}
2329
2330const QSet<QString> &ExecutionEngine::illegalNames() const
2331{
2332 return m_illegalNames;
2333}
2334
2336{
2337 // Second stage of initialization. We're updating some more prototypes here.
2338 isInitialized = false;
2339 m_qmlEngine = engine;
2341 isInitialized = true;
2342}
2343
2345{
2347 return;
2348
2349 QV4::Scope scope(v4);
2350
2351 bool instanceOfObject = false;
2352 QV4::ScopedObject p(scope, object->getPrototypeOf());
2353 while (p) {
2354 if (p->d() == v4->objectPrototype()->d()) {
2355 instanceOfObject = true;
2356 break;
2357 }
2358 p = p->getPrototypeOf();
2359 }
2360 if (!instanceOfObject)
2361 return;
2362
2363 Heap::InternalClass *frozen = object->internalClass()->frozen();
2364 object->setInternalClass(frozen); // Immediately assign frozen to prevent it from getting GC'd
2365
2366 QV4::ScopedObject o(scope);
2367 for (uint i = 0; i < frozen->size; ++i) {
2368 if (!frozen->nameMap.at(i).isStringOrSymbol())
2369 continue;
2370 o = *object->propertyData(i);
2371 if (o)
2372 freeze_recursive(v4, o);
2373 }
2374}
2375
2377{
2378 QV4::Scope scope(this);
2379 QV4::ScopedObject o(scope, value);
2380 freeze_recursive(this, o);
2381}
2382
2384{
2385 QV4::Scope scope(this);
2386 ScopedObject object(scope, value);
2387 if (!object)
2388 return;
2389
2390 std::vector<Heap::Object *> stack { object->d() };
2391
2392 // Methods meant to be overridden
2393 const PropertyKey writableMembers[] = {
2398 };
2399 const auto writableBegin = std::begin(writableMembers);
2400 const auto writableEnd = std::end(writableMembers);
2401
2402 while (!stack.empty()) {
2403 object = stack.back();
2404 stack.pop_back();
2405
2407 continue;
2408
2409 Scoped<InternalClass> locked(scope, object->internalClass()->locked());
2410 QV4::ScopedObject member(scope);
2411
2412 // Taking this copy is cheap. It's refcounted. This avoids keeping a reference
2413 // to the original IC.
2414 const SharedInternalClassData<PropertyKey> nameMap = locked->d()->nameMap;
2415
2416 for (uint i = 0, end = locked->d()->size; i < end; ++i) {
2417 const PropertyKey key = nameMap.at(i);
2418 if (!key.isStringOrSymbol())
2419 continue;
2420 if ((member = *object->propertyData(i))) {
2421 stack.push_back(member->d());
2422 if (std::find(writableBegin, writableEnd, key) == writableEnd) {
2423 PropertyAttributes attributes = locked->d()->find(key).attributes;
2424 attributes.setConfigurable(false);
2425 attributes.setWritable(false);
2426 locked = locked->changeMember(key, attributes);
2427 }
2428 }
2429 }
2430
2431 object->setInternalClass(locked->d());
2432 }
2433}
2434
2436{
2437 if (!m_time.isValid())
2438 m_time.start();
2439 m_startedTimers[timerName] = m_time.elapsed();
2440}
2441
2442qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
2443{
2444 if (!m_startedTimers.contains(timerName)) {
2445 *wasRunning = false;
2446 return 0;
2447 }
2448 *wasRunning = true;
2449 qint64 startedAt = m_startedTimers.take(timerName);
2450 return m_time.elapsed() - startedAt;
2451}
2452
2454{
2456 int number = m_consoleCount.value(key, 0);
2457 number++;
2458 m_consoleCount.insert(key, number);
2459 return number;
2460}
2461
2463{
2464 if (m_extensionData.size() <= index)
2465 m_extensionData.resize(index + 1);
2466
2467 if (m_extensionData.at(index))
2468 delete m_extensionData.at(index);
2469
2470 m_extensionData[index] = data;
2471}
2472
2473template<typename Source>
2474bool convertToIterable(QMetaType metaType, void *data, Source *sequence)
2475{
2476 QSequentialIterable iterable;
2477 if (!QMetaType::view(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
2478 return false;
2479
2480 const QMetaType elementMetaType = iterable.valueMetaType();
2481 QVariant element(elementMetaType);
2482 for (qsizetype i = 0, end = sequence->getLength(); i < end; ++i) {
2483 if (!ExecutionEngine::metaTypeFromJS(sequence->get(i), elementMetaType, element.data()))
2484 element = QVariant(elementMetaType);
2485 iterable.addValue(element, QSequentialIterable::AtEnd);
2486 }
2487 return true;
2488}
2489
2490// Converts a JS value to a meta-type.
2491// data must point to a place that can store a value of the given type.
2492// Returns true if conversion succeeded, false otherwise.
2494{
2495 // check if it's one of the types we know
2496 switch (metaType.id()) {
2497 case QMetaType::Bool:
2498 *reinterpret_cast<bool*>(data) = value.toBoolean();
2499 return true;
2500 case QMetaType::Int:
2501 *reinterpret_cast<int*>(data) = value.toInt32();
2502 return true;
2503 case QMetaType::UInt:
2504 *reinterpret_cast<uint*>(data) = value.toUInt32();
2505 return true;
2506 case QMetaType::Long:
2507 *reinterpret_cast<long*>(data) = long(value.toInteger());
2508 return true;
2509 case QMetaType::ULong:
2510 *reinterpret_cast<ulong*>(data) = ulong(value.toInteger());
2511 return true;
2512 case QMetaType::LongLong:
2513 *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
2514 return true;
2515 case QMetaType::ULongLong:
2516 *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
2517 return true;
2518 case QMetaType::Double:
2519 *reinterpret_cast<double*>(data) = value.toNumber();
2520 return true;
2521 case QMetaType::QString:
2522 if (value.isUndefined())
2523 *reinterpret_cast<QString*>(data) = QStringLiteral("undefined");
2524 else if (value.isNull())
2525 *reinterpret_cast<QString*>(data) = QStringLiteral("null");
2526 else
2527 *reinterpret_cast<QString*>(data) = value.toQString();
2528 return true;
2529 case QMetaType::QByteArray:
2530 if (const ArrayBuffer *ab = value.as<ArrayBuffer>()) {
2531 *reinterpret_cast<QByteArray*>(data) = ab->asByteArray();
2532 } else if (const String *string = value.as<String>()) {
2533 *reinterpret_cast<QByteArray*>(data) = string->toQString().toUtf8();
2534 } else if (const ArrayObject *ao = value.as<ArrayObject>()) {
2535 // Since QByteArray is sequentially iterable, we have to construct it from a JS Array.
2537 const qint64 length = ao->getLength();
2538 result.reserve(length);
2539 for (qint64 i = 0; i < length; ++i) {
2540 char value = 0;
2541 ExecutionEngine::metaTypeFromJS(ao->get(i), QMetaType::fromType<char>(), &value);
2542 result.push_back(value);
2543 }
2544 *reinterpret_cast<QByteArray*>(data) = std::move(result);
2545 } else {
2546 *reinterpret_cast<QByteArray*>(data) = QByteArray();
2547 }
2548 return true;
2549 case QMetaType::Float:
2550 *reinterpret_cast<float*>(data) = value.toNumber();
2551 return true;
2552 case QMetaType::Short:
2553 *reinterpret_cast<short*>(data) = short(value.toInt32());
2554 return true;
2555 case QMetaType::UShort:
2556 *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
2557 return true;
2558 case QMetaType::Char:
2559 *reinterpret_cast<char*>(data) = char(value.toInt32());
2560 return true;
2561 case QMetaType::UChar:
2562 *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
2563 return true;
2564 case QMetaType::SChar:
2565 *reinterpret_cast<signed char*>(data) = (signed char)(value.toInt32());
2566 return true;
2567 case QMetaType::QChar:
2568 if (String *s = value.stringValue()) {
2569 QString str = s->toQString();
2570 *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
2571 } else {
2572 *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
2573 }
2574 return true;
2575 case QMetaType::QDateTime:
2576 if (const QV4::DateObject *d = value.as<DateObject>()) {
2577 *reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
2578 return true;
2579 } break;
2580 case QMetaType::QDate:
2581 if (const QV4::DateObject *d = value.as<DateObject>()) {
2582 *reinterpret_cast<QDate *>(data) = DateObject::dateTimeToDate(d->toQDateTime());
2583 return true;
2584 } break;
2585 case QMetaType::QTime:
2586 if (const QV4::DateObject *d = value.as<DateObject>()) {
2587 *reinterpret_cast<QTime *>(data) = d->toQDateTime().time();
2588 return true;
2589 } break;
2590 case QMetaType::QUrl:
2591 if (String *s = value.stringValue()) {
2592 *reinterpret_cast<QUrl *>(data) = QUrl(s->toQString());
2593 return true;
2594 } else if (const QV4::UrlObject *d = value.as<UrlObject>()) {
2595 *reinterpret_cast<QUrl *>(data) = d->toQUrl();
2596 return true;
2597 } else if (const QV4::VariantObject *d = value.as<VariantObject>()) {
2598 const QVariant *variant = &d->d()->data();
2599 if (variant->metaType() == QMetaType::fromType<QUrl>()) {
2600 *reinterpret_cast<QUrl *>(data)
2601 = *reinterpret_cast<const QUrl *>(variant->constData());
2602 return true;
2603 }
2604 }
2605 break;
2606#if QT_CONFIG(regularexpression)
2607 case QMetaType::QRegularExpression:
2608 if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
2609 *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
2610 return true;
2611 } break;
2612#endif
2613 case QMetaType::QObjectStar: {
2614 if (value.isNull()) {
2615 *reinterpret_cast<QObject* *>(data) = nullptr;
2616 return true;
2617 }
2618 if (value.as<QV4::QObjectWrapper>()) {
2619 *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
2620 return true;
2621 }
2622 break;
2623 }
2624 case QMetaType::QStringList: {
2626 if (a) {
2627 *reinterpret_cast<QStringList *>(data) = a->toQStringList();
2628 return true;
2629 }
2630 break;
2631 }
2632 case QMetaType::QVariantList: {
2634 if (a) {
2635 *reinterpret_cast<QVariantList *>(data) = ExecutionEngine::toVariant(
2636 *a, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false)
2637 .toList();
2638 return true;
2639 }
2640 break;
2641 }
2642 case QMetaType::QVariantMap: {
2643 const QV4::Object *o = value.as<QV4::Object>();
2644 if (o) {
2645 *reinterpret_cast<QVariantMap *>(data) = o->engine()->variantMapFromJS(o);
2646 return true;
2647 }
2648 break;
2649 }
2651 if (value.as<QV4::Managed>()) {
2652 *reinterpret_cast<QVariant*>(data) = ExecutionEngine::toVariant(
2653 value, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false);
2654 } else if (value.isNull()) {
2655 *reinterpret_cast<QVariant*>(data) = QVariant::fromValue(nullptr);
2656 } else if (value.isUndefined()) {
2657 *reinterpret_cast<QVariant*>(data) = QVariant();
2658 } else if (value.isBoolean()) {
2659 *reinterpret_cast<QVariant*>(data) = QVariant(value.booleanValue());
2660 } else if (value.isInteger()) {
2661 *reinterpret_cast<QVariant*>(data) = QVariant(value.integerValue());
2662 } else if (value.isDouble()) {
2663 *reinterpret_cast<QVariant*>(data) = QVariant(value.doubleValue());
2664 }
2665 return true;
2666 case QMetaType::QJsonValue:
2667 *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
2668 return true;
2669 case QMetaType::QJsonObject: {
2670 *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.as<Object>());
2671 return true;
2672 }
2673 case QMetaType::QJsonArray: {
2675 if (a) {
2676 *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
2677 return true;
2678 }
2679 break;
2680 }
2681 default:
2682 break;
2683 }
2684
2685 if (metaType.flags() & QMetaType::IsEnumeration) {
2686 *reinterpret_cast<int *>(data) = value.toInt32();
2687 return true;
2688 }
2689
2691 if (metaType == QMetaType::fromType<QQmlListReference>()) {
2692 *reinterpret_cast<QQmlListReference *>(data) = wrapper->toListReference();
2693 return true;
2694 }
2695
2696 const auto wrapperPrivate = wrapper->d();
2697 if (wrapperPrivate->propertyType() == metaType) {
2698 *reinterpret_cast<QQmlListProperty<QObject> *>(data) = *wrapperPrivate->property();
2699 return true;
2700 }
2701 }
2702
2703 if (const QQmlValueTypeWrapper *vtw = value.as<QQmlValueTypeWrapper>()) {
2704 const QMetaType valueType = vtw->type();
2705 if (valueType == metaType)
2706 return vtw->toGadget(data);
2707
2708 Heap::QQmlValueTypeWrapper *d = vtw->d();
2709 if (d->isReference())
2710 d->readReference();
2711
2712 if (void *gadgetPtr = d->gadgetPtr()) {
2713 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, gadgetPtr))
2714 return true;
2715 if (QMetaType::canConvert(valueType, metaType))
2716 return QMetaType::convert(valueType, gadgetPtr, metaType, data);
2717 } else {
2718 QVariant empty(valueType);
2719 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, empty.data()))
2720 return true;
2721 if (QMetaType::canConvert(valueType, metaType))
2722 return QMetaType::convert(valueType, empty.data(), metaType, data);
2723 }
2724 }
2725
2726 // Try to use magic; for compatibility with qjsvalue_cast.
2727
2728 if (convertToNativeQObject(value, metaType, reinterpret_cast<void **>(data)))
2729 return true;
2730
2731 const bool isPointer = (metaType.flags() & QMetaType::IsPointer);
2732 const QV4::VariantObject *variantObject = value.as<QV4::VariantObject>();
2733 if (variantObject) {
2734 // Actually a reference, because we're poking it for its data() below and we want
2735 // the _original_ data, not some copy.
2736 QVariant &var = variantObject->d()->data();
2737
2738 if (var.metaType() == metaType) {
2739 metaType.destruct(data);
2740 metaType.construct(data, var.data());
2741 return true;
2742 }
2743
2744 if (isPointer) {
2745 const QByteArray pointedToTypeName = QByteArray(metaType.name()).chopped(1);
2746 const QMetaType valueType = QMetaType::fromName(pointedToTypeName);
2747
2748 if (valueType == var.metaType()) {
2749 // ### Qt7: Remove this. Returning pointers to potentially gc'd data is crazy.
2750 // We have T t, T* is requested, so return &t.
2751 *reinterpret_cast<const void **>(data) = var.data();
2752 return true;
2753 } else if (Object *o = value.objectValue()) {
2754 // Look in the prototype chain.
2755 QV4::Scope scope(o->engine());
2756 QV4::ScopedObject proto(scope, o->getPrototypeOf());
2757 while (proto) {
2758 bool canCast = false;
2759 if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
2760 const QVariant &v = vo->d()->data();
2761 canCast = (metaType == v.metaType());
2762 }
2763 else if (proto->as<QV4::QObjectWrapper>()) {
2764 QV4::ScopedObject p(scope, proto.getPointer());
2765 if (QObject *qobject = qtObjectFromJS(p)) {
2766 if (const QMetaObject *metaObject = metaType.metaObject())
2767 canCast = metaObject->cast(qobject) != nullptr;
2768 else
2769 canCast = qobject->qt_metacast(pointedToTypeName);
2770 }
2771 }
2772 if (canCast) {
2773 const QMetaType varType = var.metaType();
2774 if (varType.flags() & QMetaType::IsPointer) {
2775 *reinterpret_cast<const void **>(data)
2776 = *reinterpret_cast<void *const *>(var.data());
2777 } else {
2778 *reinterpret_cast<const void **>(data) = var.data();
2779 }
2780 return true;
2781 }
2782 proto = proto->getPrototypeOf();
2783 }
2784 }
2786 metaType, data, var.metaType(), var.data())) {
2787 return true;
2788 }
2789 } else if (value.isNull() && isPointer) {
2790 *reinterpret_cast<void* *>(data) = nullptr;
2791 return true;
2792 } else if (metaType == QMetaType::fromType<QJSValue>()) {
2793 QJSValuePrivate::setValue(reinterpret_cast<QJSValue*>(data), value.asReturnedValue());
2794 return true;
2795 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
2796 *reinterpret_cast<QJSPrimitiveValue *>(data) = createPrimitive(&value);
2797 return true;
2798 } else if (!isPointer) {
2800 return true;
2801 }
2802
2803 if (const QV4::Sequence *sequence = value.as<Sequence>()) {
2805 if (result.metaType() == metaType) {
2806 metaType.destruct(data);
2807 metaType.construct(data, result.constData());
2808 return true;
2809 }
2810
2811 if (convertToIterable(metaType, data, sequence))
2812 return true;
2813 }
2814
2815 if (const QV4::ArrayObject *array = value.as<ArrayObject>()) {
2816 if (convertToIterable(metaType, data, array))
2817 return true;
2818 }
2819
2820 return false;
2821}
2822
2823static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result)
2824{
2825 if (!(targetType.flags() & QMetaType::IsPointer))
2826 return false;
2827 if (QObject *qobject = qtObjectFromJS(value)) {
2828 // If the target type has a metaObject, use that for casting.
2829 if (const QMetaObject *targetMetaObject = targetType.metaObject()) {
2830 if (QObject *instance = targetMetaObject->cast(qobject)) {
2831 *result = instance;
2832 return true;
2833 }
2834 return false;
2835 }
2836
2837 // We have to call the generated qt_metacast rather than metaObject->cast() here so that
2838 // it works for types without QMetaObject, such as QStandardItem.
2839 const QByteArray targetTypeName = targetType.name();
2840 const int start = targetTypeName.startsWith("const ") ? 6 : 0;
2841 const QByteArray className = targetTypeName.mid(start, targetTypeName.size() - start - 1);
2842 if (void *instance = qobject->qt_metacast(className)) {
2843 *result = instance;
2844 return true;
2845 }
2846 }
2847 return false;
2848}
2849
2851{
2852 if (!value.isObject())
2853 return nullptr;
2854
2855 QV4::Scope scope(value.as<QV4::Managed>()->engine());
2857
2858 if (v) {
2859 QVariant variant = v->d()->data();
2860 int type = variant.userType();
2861 if (type == QMetaType::QObjectStar)
2862 return *reinterpret_cast<QObject* const *>(variant.constData());
2863 }
2865 if (wrapper)
2866 return wrapper->object();
2867
2868 QV4::Scoped<QV4::QQmlTypeWrapper> typeWrapper(scope, value);
2869 if (typeWrapper)
2870 return typeWrapper->object();
2871
2872 return nullptr;
2873}
2874
2883
2885{
2886 return &registrationData()->mutex;
2887}
2888
2890{
2891 return registrationData()->extensionCount++;
2892}
2893
2894#if QT_CONFIG(qml_network)
2895QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine)
2896{
2897 return engine->qmlEngine()->networkAccessManager();
2898}
2899#endif // qml_network
2900
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatetime.h:283
\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:985
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
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:75
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
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:341
static constexpr QMetaType fromType()
Definition qmetatype.h:2642
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:2658
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:475
@ PointerToQObject
Definition qmetatype.h:406
@ IsEnumeration
Definition qmetatype.h:407
Type
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
Definition qmetatype.h:345
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2663
constexpr const char * name() const
Definition qmetatype.h:2680
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:796
\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:18
const_iterator constBegin() const noexcept
Definition qset.h:139
iterator insert(const T &value)
Definition qset.h:155
\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:5871
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:6018
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:8084
\inmodule QtCore
static void yieldCurrentThread()
Definition qthread.cpp:1054
\inmodule QtCore \reentrant
Definition qdatetime.h:215
\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:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
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:536
Private d
Definition qvariant.h:672
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
Q_QML_EXPORT void registerStringLocaleCompare(QV4::ExecutionEngine *engine)
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
static void * context
#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:166
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(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:101
const char className[16]
[1]
Definition qwizard.cpp:100
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
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()