Qt 6.x
The Qt SDK
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"
64#include "qv4memberdata_p.h"
65#include "qv4arraybuffer_p.h"
66#include "qv4dataview_p.h"
67#include "qv4promiseobject_p.h"
68#include "qv4typedarray_p.h"
69#include <private/qjsvalue_p.h>
70#include <private/qqmltypewrapper_p.h>
71#include <private/qqmlvaluetypewrapper_p.h>
72#include <private/qqmlvaluetype_p.h>
73#include <private/qqmllistwrapper_p.h>
74#include <private/qqmllist_p.h>
75#include <private/qqmltypeloader_p.h>
76#include <private/qqmlbuiltinfunctions_p.h>
77#if QT_CONFIG(qml_locale)
78#include <private/qqmllocale_p.h>
79#endif
80#if QT_CONFIG(qml_xml_http_request)
81#include <private/qv4domerrors_p.h>
82#include <private/qqmlxmlhttprequest_p.h>
83#endif
84#include <private/qv4sqlerrors_p.h>
85#include <qqmlfile.h>
86#include <qmetatype.h>
87#include <qsequentialiterable.h>
88
89#include <private/qqmlengine_p.h>
90
91#ifdef V4_USE_VALGRIND
92#include <valgrind/memcheck.h>
93#endif
94
96
97DEFINE_BOOL_CONFIG_OPTION(disableDiskCache, QML_DISABLE_DISK_CACHE);
98DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE);
99
100using namespace QV4;
101
102// While engineSerial is odd the statics haven't been initialized. The engine that receives ID 1
103// initializes the statics and sets engineSerial to 2 afterwards.
104// Each engine does engineSerial.fetchAndAddOrdered(2) on creation. Therefore engineSerial stays
105// odd while the statics are being initialized, and stays even afterwards.
106// Any further engines created while the statics are being initialized busy-wait until engineSerial
107// is even.
109int ExecutionEngine::s_maxCallDepth = -1;
110int ExecutionEngine::s_jitCallCountThreshold = 3;
111int ExecutionEngine::s_maxJSStackSize = 4 * 1024 * 1024;
112int ExecutionEngine::s_maxGCStackSize = 2 * 1024 * 1024;
113
115{
116 return b->engine()->throwTypeError();
117}
118
119
120template <typename ReturnType>
122{
123 const QVariant variant = value.toVariant();
124 return variant.metaType() == QMetaType::fromType<QJSValue>()
125 ? ReturnType()
126 : variant.value<ReturnType>();
127}
128
132};
133
134namespace {
135void createNewIteratorIfNonExisting(void **iterator) {
136 if (*iterator == nullptr)
137 *iterator = new JSArrayIterator;
138}
139}
140
142{
143 // set up some functions so that non-array QSequentialIterables do not crash
144 // but instead appear as an empty sequence
145
146 using namespace QtMetaContainerPrivate;
148 iface.sizeFn = [](const void *) { return qsizetype(0); };
149 iface.valueAtIndexFn = [](const void *, qsizetype, void *) {};
150 iface.createIteratorFn = [](void *, QMetaSequenceInterface::Position) -> void * {
151 return nullptr;
152 };
153 iface.advanceIteratorFn = [](void *, qsizetype) {};
154 iface.compareIteratorFn = [](const void *, const void *) {
155 return true; /*all iterators are nullptr*/
156 };
157 iface.destroyIteratorFn = [](const void *) {};
158 iface.copyIteratorFn = [](void *, const void *) {};
159 iface.diffIteratorFn = [](const void *, const void *) { return qsizetype(0); };
160 return iface;
161}
162
164{
165 using namespace QtMetaContainerPrivate;
167 iface.valueMetaType = QtPrivate::qMetaTypeInterfaceForType<QVariant>();
168 iface.iteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability;
169 iface.addRemoveCapabilities = CanAddAtEnd;
170 iface.sizeFn = [](const void *p) -> qsizetype {
171 return static_cast<QJSValue const *>(p)->property(QString::fromLatin1("length")).toInt();
172 };
173
174 /* Lifetime management notes:
175 * valueAtIndexFn and valueAtIteratorFn return a pointer to a JSValue allocated via
176 * QMetaType::create Because we set QVariantConstructionFlags::ShouldDeleteVariantData,
177 * QSequentialIterable::at and QSequentialIterable::operator*() will free that memory
178 */
179
180 iface.valueAtIndexFn = [](const void *iterable, qsizetype index, void *dataPtr) -> void {
181 auto *data = static_cast<QVariant *>(dataPtr);
182 *data = static_cast<QJSValue const *>(iterable)->property(quint32(index)).toVariant();
183 };
184 iface.createIteratorFn = [](void *iterable, QMetaSequenceInterface::Position pos) {
185 void *iterator = nullptr;
186 createNewIteratorIfNonExisting(&iterator);
187 auto jsArrayIterator = static_cast<JSArrayIterator *>(iterator);
188 jsArrayIterator->index = 0;
189 jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
190 if (pos == QMetaSequenceInterface::AtEnd) {
191 auto length = static_cast<QJSValue const *>(iterable)->property(
192 QString::fromLatin1("length")).toInt();
193 jsArrayIterator->index = quint32(length);
194 }
195 return iterator;
196 };
197 iface.createConstIteratorFn = [](const void *iterable, QMetaSequenceInterface::Position pos) {
198 void *iterator = nullptr;
199 createNewIteratorIfNonExisting(&iterator);
200 auto jsArrayIterator = static_cast<JSArrayIterator *>(iterator);
201 jsArrayIterator->index = 0;
202 jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
203 if (pos == QMetaSequenceInterface::AtEnd) {
204 auto length = static_cast<QJSValue const *>(iterable)->property(
205 QString::fromLatin1("length")).toInt();
206 jsArrayIterator->index = quint32(length);
207 }
208 return iterator;
209 };
210 iface.advanceIteratorFn = [](void *iterator, qsizetype advanceBy) {
211 static_cast<JSArrayIterator *>(iterator)->index += quint32(advanceBy);
212 };
213 iface.advanceConstIteratorFn = [](void *iterator, qsizetype advanceBy) {
214 static_cast<JSArrayIterator *>(iterator)->index += quint32(advanceBy);
215 };
216 iface.valueAtIteratorFn = [](const void *iterator, void *dataPtr) -> void {
217 const auto *arrayIterator = static_cast<const JSArrayIterator *>(iterator);
218 const QJSValue *jsArray = arrayIterator->data;
219 auto *data = static_cast<QVariant *>(dataPtr);
220 *data = jsArray->property(arrayIterator->index).toVariant();
221 };
222 iface.valueAtConstIteratorFn = [](const void *iterator, void *dataPtr) -> void {
223 const auto *arrayIterator = static_cast<const JSArrayIterator *>(iterator);
224 const QJSValue *jsArray = arrayIterator->data;
225 auto *data = static_cast<QVariant *>(dataPtr);
226 *data = jsArray->property(arrayIterator->index).toVariant();
227 };
228 iface.destroyIteratorFn = [](const void *iterator) {
229 delete static_cast<const JSArrayIterator *>(iterator);
230 };
231 iface.destroyConstIteratorFn = [](const void *iterator) {
232 delete static_cast<const JSArrayIterator *>(iterator);
233 };
234 iface.compareIteratorFn = [](const void *p, const void *other) {
235 auto this_ = static_cast<const JSArrayIterator *>(p);
236 auto that_ = static_cast<const JSArrayIterator *>(other);
237 return this_->index == that_->index && this_->data == that_->data;
238 };
239 iface.compareConstIteratorFn = [](const void *p, const void *other) {
240 auto this_ = static_cast<const JSArrayIterator *>(p);
241 auto that_ = static_cast<const JSArrayIterator *>(other);
242 return this_->index == that_->index && this_->data == that_->data;
243 };
244 iface.copyIteratorFn = [](void *iterator, const void *otherIterator) {
245 auto *otherIter = (static_cast<JSArrayIterator const *>(otherIterator));
246 static_cast<JSArrayIterator *>(iterator)->index = otherIter->index;
247 static_cast<JSArrayIterator *>(iterator)->data = otherIter->data;
248 };
249 iface.copyConstIteratorFn = [](void *iterator, const void *otherIterator) {
250 auto *otherIter = (static_cast<JSArrayIterator const *>(otherIterator));
251 static_cast<JSArrayIterator *>(iterator)->index = otherIter->index;
252 static_cast<JSArrayIterator *>(iterator)->data = otherIter->data;
253 };
254 iface.diffIteratorFn = [](const void *iterator, const void *otherIterator) -> qsizetype {
255 const auto *self = static_cast<const JSArrayIterator *>(iterator);
256 const auto *other = static_cast<const JSArrayIterator *>(otherIterator);
257 return self->index - other->index;
258 };
259 iface.diffConstIteratorFn = [](const void *iterator, const void *otherIterator) -> qsizetype {
260 const auto *self = static_cast<const JSArrayIterator *>(iterator);
261 const auto *other = static_cast<const JSArrayIterator *>(otherIterator);
262 return self->index - other->index;
263 };
264 iface.addValueFn = [](void *iterable, const void *data, QMetaSequenceInterface::Position) {
265 auto *jsvalue = static_cast<QJSValue *>(iterable);
266 QV4::Scope scope(QJSValuePrivate::engine(jsvalue));
267 QV4::ScopedArrayObject a(scope, QJSValuePrivate::asManagedType<QV4::ArrayObject>(jsvalue));
268 QV4::ScopedValue v(scope, scope.engine->fromVariant(*static_cast<const QVariant *>(data)));
269 if (!a)
270 return;
271 int len = a->getLength();
272 a->setIndexed(len, v, QV4::Object::DoNotThrow);
273 };
274 return iface;
275}
276
278 using namespace QtMetaTypePrivate;
279 using namespace QtMetaContainerPrivate;
280
281
282 if (!value.isArray()) {
283 static QMetaSequenceInterface emptySequence = emptySequenceInterface();
284 return QSequentialIterable(QMetaSequence(&emptySequence), nullptr);
285 }
286
287 static QMetaSequenceInterface sequence = sequenceInterface();
288 return QSequentialIterable(QMetaSequence(&sequence), &value);
289}
290
291void ExecutionEngine::initializeStaticMembers()
292{
293 bool ok = false;
294
295 const int envMaxJSStackSize = qEnvironmentVariableIntValue("QV4_JS_MAX_STACK_SIZE", &ok);
296 if (ok && envMaxJSStackSize > 0)
297 s_maxJSStackSize = envMaxJSStackSize;
298
299 const int envMaxGCStackSize = qEnvironmentVariableIntValue("QV4_GC_MAX_STACK_SIZE", &ok);
300 if (ok && envMaxGCStackSize > 0)
301 s_maxGCStackSize = envMaxGCStackSize;
302
303 if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) {
304 s_maxCallDepth = std::numeric_limits<qint32>::max();
305 } else {
306 ok = false;
307 s_maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
308 if (!ok || s_maxCallDepth <= 0)
309 s_maxCallDepth = -1;
310 }
311
312 ok = false;
313 s_jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
314 if (!ok)
315 s_jitCallCountThreshold = 3;
316 if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
317 s_jitCallCountThreshold = std::numeric_limits<int>::max();
318
319 qMetaTypeId<QJSValue>();
320 qMetaTypeId<QList<int> >();
321
322 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
323 QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
324 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
325 QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
326 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
327 QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
328 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QSequentialIterable>())
329 QMetaType::registerConverter<QJSValue, QSequentialIterable>(jsvalueToSequence);
330}
331
333 : executableAllocator(new QV4::ExecutableAllocator)
334 , regExpAllocator(new QV4::ExecutableAllocator)
335 , bumperPointerAllocator(new WTF::BumpPointerAllocator)
336 , jsStack(new WTF::PageAllocation)
337 , gcStack(new WTF::PageAllocation)
338 , globalCode(nullptr)
339 , publicEngine(jsEngine)
340 , m_engineId(engineSerial.fetchAndAddOrdered(2))
341 , regExpCache(nullptr)
342 , m_multiplyWrappedQObjects(nullptr)
343#if QT_CONFIG(qml_jit)
344 , m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
345#endif
346#if QT_CONFIG(qml_xml_http_request)
347 , m_xmlHttpRequestData(nullptr)
348#endif
349 , m_qmlEngine(nullptr)
350{
351 if (m_engineId == 1) {
352 initializeStaticMembers();
353 engineSerial.storeRelease(2); // make it even
354 } else if (Q_UNLIKELY(m_engineId & 1)) {
355 // This should be rare. You usually don't create lots of engines at the same time.
356 while (engineSerial.loadAcquire() & 1) {
358 }
359 }
360
361 if (s_maxCallDepth < 0) {
362 const StackProperties stack = stackProperties();
363 cppStackBase = stack.base;
364 cppStackLimit = stack.softLimit;
365 } else {
366 callDepth = 0;
367 }
368
369 // We allocate guard pages around our stacks.
370 const size_t guardPages = 2 * WTF::pageSize();
371
373 // reserve space for the JS stack
374 // we allow it to grow to a bit more than m_maxJSStackSize, as we can overshoot due to ScopedValues
375 // allocated outside of JIT'ed methods.
376 *jsStack = WTF::PageAllocation::allocate(
377 s_maxJSStackSize + 256*1024 + guardPages, WTF::OSAllocator::JSVMStackPages,
378 /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
379 jsStackBase = (Value *)jsStack->base();
380#ifdef V4_USE_VALGRIND
381 VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, m_maxJSStackSize + 256*1024);
382#endif
383
385
386 *gcStack = WTF::PageAllocation::allocate(
387 s_maxGCStackSize + guardPages, WTF::OSAllocator::JSVMStackPages,
388 /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
389
392 globalObject = static_cast<Object *>(jsAlloca(1));
398
399 // set up stack limits
400 jsStackLimit = jsStackBase + s_maxJSStackSize/sizeof(Value);
401
403
404 memset(classes, 0, sizeof(classes));
406 classes[Class_Empty]->init(this);
407
408 classes[Class_MemberData] = classes[Class_Empty]->changeVTable(QV4::MemberData::staticVTable());
409 classes[Class_SimpleArrayData] = classes[Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
410 classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
411 classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
412 classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
413 classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable());
414
415 Scope scope(this);
416 Scoped<InternalClass> ic(scope);
417 ic = classes[Class_Empty]->changeVTable(QV4::Object::staticVTable());
419 classes[Class_Object] = ic->changePrototype(objectPrototype()->d());
420 classes[Class_QmlContextWrapper] = classes[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
421
422 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
423 jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic->d(), /*init =*/ false);
424 classes[Class_String] = classes[Class_Empty]->changeVTable(QV4::String::staticVTable())->changePrototype(stringPrototype()->d());
425 Q_ASSERT(stringPrototype()->d() && classes[Class_String]->prototype);
426
428 classes[Class_Symbol] = classes[EngineBase::Class_Empty]->changeVTable(QV4::Symbol::staticVTable())->changePrototype(symbolPrototype()->d());
429
480
481 jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
482 jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
483 jsSymbols[Symbol_iterator] = Symbol::create(this, QStringLiteral("@Symbol.iterator"));
484 jsSymbols[Symbol_match] = Symbol::create(this, QStringLiteral("@Symbol.match"));
485 jsSymbols[Symbol_replace] = Symbol::create(this, QStringLiteral("@Symbol.replace"));
486 jsSymbols[Symbol_search] = Symbol::create(this, QStringLiteral("@Symbol.search"));
487 jsSymbols[Symbol_species] = Symbol::create(this, QStringLiteral("@Symbol.species"));
488 jsSymbols[Symbol_split] = Symbol::create(this, QStringLiteral("@Symbol.split"));
489 jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
490 jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
491 jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
492 jsSymbols[Symbol_revokableProxy] = Symbol::create(this, QStringLiteral("@Proxy.revokableProxy"));
493
494 ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
495 Q_ASSERT(ic->d()->prototype);
496 ic = ic->addMember(id_length()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
497 Q_ASSERT(ic->d()->prototype);
499 classes[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d());
501
502 Scoped<InternalClass> argsClass(scope);
503 argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype());
504 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
505 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
507 argsClass = newInternalClass(StrictArgumentsObject::staticVTable(), objectPrototype());
508 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
509 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
511
512 *static_cast<Value *>(globalObject) = newObject();
515
516 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
517 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly);
518 classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
519 Q_ASSERT(classes[Class_StringObject]->verifyIndex(id_length()->propertyKey(), Heap::StringObject::LengthPropertyIndex));
520
521 classes[Class_SymbolObject] = newInternalClass(QV4::SymbolObject::staticVTable(), symbolPrototype());
522
526
527#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
528 InternalClassEntry *index = nullptr;
529#else
530 InternalClassEntry _index;
531 auto *index = &_index;
532#endif
533 ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
534 auto addProtoHasInstance = [&] {
535 // Add an invalid prototype slot, so that all function objects have the same layout
536 // This helps speed up instanceof operations and other things where we need to query
537 // prototype property (as we always know it's location)
538 ic = ic->addMember(id_prototype()->propertyKey(), Attr_Invalid, index);
539 Q_ASSERT(index->index == Heap::FunctionObject::Index_Prototype);
540 // add an invalid @hasInstance slot, so that we can quickly track whether the
541 // hasInstance method has been reimplemented. This is required for a fast
542 // instanceof implementation
543 ic = ic->addMember(symbol_hasInstance()->propertyKey(), Attr_Invalid, index);
544 Q_ASSERT(index->index == Heap::FunctionObject::Index_HasInstance);
545 };
546 addProtoHasInstance();
548 ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
549 addProtoHasInstance();
550 classes[Class_FunctionObject] = ic->d();
551 ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, index);
553 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, index);
555 classes[Class_ArrowFunction] = ic->changeVTable(ArrowFunction::staticVTable());
556 ic = ic->changeVTable(MemberFunction::staticVTable());
557 classes[Class_MemberFunction] = ic->d();
558 ic = ic->changeVTable(GeneratorFunction::staticVTable());
560 ic = ic->changeVTable(MemberGeneratorFunction::staticVTable());
562
563 ic = ic->changeMember(id_prototype()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
564 ic = ic->changeVTable(ScriptFunction::staticVTable());
565 classes[Class_ScriptFunction] = ic->d();
566 ic = ic->changeVTable(ConstructorFunction::staticVTable());
568
570 Q_ASSERT(index->index == Heap::FunctionObject::Index_ProtoConstructor);
571
573 classes[Class_GeneratorObject] = newInternalClass(QV4::GeneratorObject::staticVTable(), generatorPrototype());
574
575 ScopedString str(scope);
576 classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
577 ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
578 ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, index);
581 classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
582
585 classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, index);
587
588 ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
589 ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, index);
592 ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
594 ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
595 classes[Class_ErrorObject] = ic->d();
599 ic = newInternalClass(Object::staticVTable(), objectPrototype());
600 ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
602 ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
604 classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
606
607 classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
608 classes[Class_ProxyFunctionObject] = classes[Class_Empty]->changeVTable(ProxyFunctionObject::staticVTable());
609
611
620
622 Q_ASSERT(variantPrototype()->getPrototypeOf() == objectPrototype()->d());
623
624 ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this));
626
628
647
648 ic = newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype());
650 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
652 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
654 ic = newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype());
656 ic = newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype());
658
659 //
660 // url
661 //
662
667
668 str = newString(QStringLiteral("get [Symbol.species]"));
670
671 static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
672 static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
673 static_cast<SymbolPrototype *>(symbolPrototype())->init(this, symbolCtor());
674 static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
675 static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
676 static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
678 static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
679 static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
681 static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
682 static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
683 static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
687 static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
688 static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
689 static_cast<UrlPrototype *>(urlPrototype())->init(this, urlCtor());
691
692 static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
693 static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
694 static_cast<MapIteratorPrototype *>(mapIteratorPrototype())->init(this);
695 static_cast<SetIteratorPrototype *>(setIteratorPrototype())->init(this);
696 static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this);
698
699 static_cast<VariantPrototype *>(variantPrototype())->init();
700
702
705 static_cast<WeakMapPrototype *>(weakMapPrototype())->init(this, weakMapCtor());
706
709 static_cast<MapPrototype *>(mapPrototype())->init(this, mapCtor());
710
713 static_cast<WeakSetPrototype *>(weakSetPrototype())->init(this, weakSetCtor());
714
717 static_cast<SetPrototype *>(setPrototype())->init(this, setCtor());
718
719 //
720 // promises
721 //
722
725 static_cast<PromisePrototype *>(promisePrototype())->init(this, promiseCtor());
726
727 // typed arrays
728
732
736
739 static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
740 jsObjects[ValueTypeProto] = (Heap::Base *) nullptr;
742
746 ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
747
748 for (int i = 0; i < NTypedArrayTypes; ++i) {
749 static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
750 static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
751 typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
752 }
753
754 //
755 // set up the global object
756 //
757 rootContext()->d()->activation.set(scope.engine, globalObject->d());
759
763 FunctionObject *numberObject = numberCtor();
764 globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
780
788
789 for (int i = 0; i < NTypedArrayTypes; ++i)
791 ScopedObject o(scope);
797
799 globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN()));
801
802
805
806 // ES6: 20.1.2.12 & 20.1.2.13:
807 // parseInt and parseFloat must be the same FunctionObject on the global &
808 // Number object.
809 {
810 QString piString(QStringLiteral("parseInt"));
811 QString pfString(QStringLiteral("parseFloat"));
812 Scope scope(this);
813 ScopedString pi(scope, newIdentifier(piString));
814 ScopedString pf(scope, newIdentifier(pfString));
817 globalObject->defineDefaultProperty(piString, parseIntFn);
818 globalObject->defineDefaultProperty(pfString, parseFloatFn);
819 numberObject->defineDefaultProperty(piString, parseIntFn);
820 numberObject->defineDefaultProperty(pfString, parseFloatFn);
821 }
822
831
833 t->defineReadonlyProperty(id_length(), Value::fromInt32(0));
834 t->setInternalClass(t->internalClass()->cryopreserved());
836
837 ScopedProperty pd(scope);
838 pd->value = thrower();
839 pd->set = thrower();
842
844
845 m_delayedCallQueue.init(this);
846 isInitialized = true;
847}
848
850{
851 modules.clear();
852 for (auto val : nativeModules) {
854 }
855 nativeModules.clear();
856 qDeleteAll(m_extensionData);
859 delete identifierTable;
860 delete memoryManager;
861
862 // Take a temporary reference to the CU so that it doesn't disappear during unlinking.
863 while (!compilationUnits.isEmpty())
865
867 delete regExpCache;
868 delete regExpAllocator;
869 delete executableAllocator;
870 jsStack->deallocate();
871 delete jsStack;
872 gcStack->deallocate();
873 delete gcStack;
874
875#if QT_CONFIG(qml_xml_http_request)
876 qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
877 m_xmlHttpRequestData = nullptr;
878#endif
879}
880
881#if QT_CONFIG(qml_debug)
883{
884 Q_ASSERT(!m_debugger);
885 m_debugger.reset(debugger);
886}
887
889{
890 Q_ASSERT(!m_profiler);
891 m_profiler.reset(profiler);
892}
893#endif // QT_CONFIG(qml_debug)
894
896{
897 Scope scope(this);
898 Scoped<ExecutionContext> r(scope, memoryManager->allocManaged<ExecutionContext>(sizeof(ExecutionContext::Data)));
899 r->d_unchecked()->init(Heap::ExecutionContext::Type_GlobalContext);
900 r->d()->activation.set(this, globalObject->d());
903 jsObjects[IntegerNull] = Encode((int)0);
904}
905
907{
909 ic->init(other);
910 return ic;
911}
912
914{
915 Scope scope(this);
916 Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable));
917 return ic->changePrototype(prototype ? prototype->d() : nullptr);
918}
919
921{
922 return memoryManager->allocate<Object>();
923}
924
926{
927 return memoryManager->allocObject<Object>(internalClass);
928}
929
931{
932 return memoryManager->allocWithStringData<String>(s.size() * sizeof(QChar), s);
933}
934
936{
937 Scope scope(this);
939 s->toPropertyKey();
940 return s->d();
941}
942
943Heap::Object *ExecutionEngine::newStringObject(const String *string)
944{
946}
947
949{
951}
952
954{
956}
957
959{
961}
962
964{
965 Scope scope(this);
967
968 if (count) {
969 if (count < 0x1000)
970 object->arrayReserve(count);
971 object->setArrayLengthUnchecked(count);
972 }
973 return object->d();
974}
975
977{
978 Scope scope(this);
980
981 if (length) {
982 size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
984 d->init();
985 d->type = Heap::ArrayData::Simple;
986 d->offset = 0;
987 d->values.alloc = length;
988 d->values.size = length;
989 // this doesn't require a write barrier, things will be ok, when the new array data gets inserted into
990 // the parent object
991 memcpy(&d->values.values, values, length*sizeof(Value));
992 a->d()->arrayData.set(this, d);
993 a->setArrayLengthUnchecked(length);
994 }
995 return a->d();
996}
997
999{
1001}
1002
1004{
1005 return memoryManager->allocObject<ArrayObject>(internalClass);
1006}
1007
1009{
1011}
1012
1014{
1016}
1017
1019{
1021}
1022
1024{
1026}
1027
1029 QDate date, Heap::Object *parent, int index, uint flags)
1030{
1032 date, parent, index, Heap::ReferenceObject::Flags(flags));
1033}
1034
1036 QTime time, Heap::Object *parent, int index, uint flags)
1037{
1039 time, parent, index, Heap::ReferenceObject::Flags(flags));
1040}
1041
1043 QDateTime dateTime, Heap::Object *parent, int index, uint flags)
1044{
1046 dateTime, parent, index, Heap::ReferenceObject::Flags(flags));
1047}
1048
1050{
1051 Scope scope(this);
1053 return newRegExpObject(re);
1054}
1055
1057{
1058 return memoryManager->allocate<RegExpObject>(re);
1059}
1060
1061#if QT_CONFIG(regularexpression)
1062Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
1063{
1064 return memoryManager->allocate<RegExpObject>(re);
1065}
1066#endif
1067
1069{
1070 return memoryManager->allocate<UrlObject>();
1071}
1072
1074{
1075 Scope scope(this);
1076 Scoped<UrlObject> urlObject(scope, newUrlObject());
1077 urlObject->setUrl(url);
1078 return urlObject->d();
1079}
1080
1081Heap::UrlSearchParamsObject *ExecutionEngine::newUrlSearchParamsObject()
1082{
1084}
1085
1087{
1088 return ErrorObject::create<ErrorObject>(this, value, errorCtor());
1089}
1090
1092{
1093 return ErrorObject::create<ErrorObject>(this, message);
1094}
1095
1097{
1098 return ErrorObject::create<SyntaxErrorObject>(this, message);
1099}
1100
1102{
1103 return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
1104}
1105
1106
1108{
1109 return ErrorObject::create<ReferenceErrorObject>(this, message);
1110}
1111
1113{
1114 return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
1115}
1116
1117
1119{
1120 return ErrorObject::create<TypeErrorObject>(this, message);
1121}
1122
1124{
1125 return ErrorObject::create<RangeErrorObject>(this, message);
1126}
1127
1129{
1130 return ErrorObject::create<URIErrorObject>(this, message, uRIErrorCtor());
1131}
1132
1134{
1135 if (!m_reactionHandler) {
1136 m_reactionHandler.reset(new Promise::ReactionHandler);
1137 }
1138
1139 Scope scope(this);
1141 return object->d();
1142}
1143
1144Heap::Object *ExecutionEngine::newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability)
1145{
1146 if (!m_reactionHandler) {
1147 m_reactionHandler.reset(new Promise::ReactionHandler);
1148 }
1149
1150 Scope scope(this);
1152 executor->d()->capabilities.set(this, capability->d());
1154
1155 ScopedObject object(scope, thisObject->callAsConstructor(executor, 1));
1156 return object->d();
1157}
1158
1160{
1161 Q_ASSERT(m_reactionHandler);
1162 return m_reactionHandler.data();
1163}
1164
1166{
1167 return ErrorObject::create<URIErrorObject>(this, message);
1168}
1169
1171{
1172 return ErrorObject::create<EvalErrorObject>(this, message);
1173}
1174
1175Heap::Object *ExecutionEngine::newVariantObject(const QMetaType type, const void *data)
1176{
1178}
1179
1181{
1182 Scope scope(this);
1184 return obj->d();
1185}
1186
1188{
1189 return memoryManager->allocate<MapIteratorObject>(o->d(), this);
1190}
1191
1193{
1194 return memoryManager->allocate<SetIteratorObject>(o->d(), this);
1195}
1196
1198{
1199 return memoryManager->allocate<ArrayIteratorObject>(o->d(), this);
1200}
1201
1202Heap::QmlContext *ExecutionEngine::qmlContext() const
1203{
1204 return currentStackFrame
1205 ? static_cast<Heap::QmlContext *>(qmlContext(currentContext()->d()))
1206 : nullptr;
1207}
1208
1210{
1211 Heap::QmlContext *ctx = qmlContext();
1212 if (!ctx)
1213 return nullptr;
1214
1215 return ctx->qml()->scopeObject;
1216}
1217
1219{
1220 Heap::QmlContext *ctx = qmlContext();
1221 if (!ctx)
1222 return nullptr;
1223
1224 return ctx->qml()->context;
1225}
1226
1228{
1229 Scope scope(const_cast<ExecutionEngine *>(this));
1230 ScopedString name(scope);
1231 StackTrace stack;
1232
1234 while (f && frameLimit) {
1236 frame.source = f->source();
1237 frame.function = f->function();
1238 frame.line = f->lineNumber();
1239 frame.column = -1;
1240 stack.append(frame);
1241 if (f->isJSTypesFrame()) {
1242 if (static_cast<JSTypesStackFrame *>(f)->isTailCalling()) {
1244 frame.function = QStringLiteral("[elided tail calls]");
1245 stack.append(frame);
1246 }
1247 }
1248 --frameLimit;
1249 f = f->parentFrame();
1250 }
1251
1252 return stack;
1253}
1254
1255/* Helper and "C" linkage exported function to format a GDBMI stacktrace for
1256 * invocation by a debugger.
1257 * Sample GDB invocation: print qt_v4StackTrace((void*)0x7fffffffb290)
1258 * Sample CDB invocation: .call Qt5Qmld!qt_v4StackTrace(0x7fffffffb290) ; gh
1259 * Note: The helper is there to suppress MSVC warning 4190 about anything
1260 * with UDT return types in a "C" linkage function. */
1261
1262static inline char *v4StackTrace(const ExecutionContext *context)
1263{
1266 str << "stack=[";
1267 if (context && context->engine()) {
1268 const QVector<StackFrame> stackTrace = context->engine()->stackTrace(20);
1269 for (int i = 0; i < stackTrace.size(); ++i) {
1270 if (i)
1271 str << ',';
1272 const QUrl url(stackTrace.at(i).source);
1274 str << "frame={level=\"" << i << "\",func=\"" << stackTrace.at(i).function
1275 << "\",file=\"" << fileName << "\",fullname=\"" << fileName
1276 << "\",line=\"" << qAbs(stackTrace.at(i).line) << "\",language=\"js\"}";
1277 }
1278 }
1279 str << ']';
1280 return qstrdup(result.toLocal8Bit().constData());
1281}
1282
1283extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
1284{
1285 return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
1286}
1287
1288extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
1289{
1290 auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
1291 return v4StackTrace(engine->currentContext());
1292}
1293
1295{
1296 QUrl src(file);
1297 if (!src.isRelative())
1298 return src;
1299
1300 QUrl base;
1302 while (f) {
1303 if (f->v4Function) {
1304 base = f->v4Function->finalUrl();
1305 break;
1306 }
1307 f = f->parentFrame();
1308 }
1309
1310 if (base.isEmpty() && globalCode)
1312
1313 if (base.isEmpty())
1314 return src;
1315
1316 return base.resolved(src);
1317}
1318
1320{
1321 for (int i = 0; i < NClasses; ++i) {
1323 c->mark(markStack);
1324 }
1325
1326 identifierTable->markObjects(markStack);
1327
1328 for (auto compilationUnit: compilationUnits)
1329 compilationUnit->markObjects(markStack);
1330}
1331
1333{
1334 // we can get in here with an exception already set, as the runtime
1335 // doesn't check after every operation that can throw.
1336 // in this case preserve the first exception to give correct error
1337 // information
1338 if (hasException)
1339 return Encode::undefined();
1340
1341 hasException = true;
1343 QV4::Scope scope(this);
1345 if (!!error)
1346 exceptionStackTrace = *error->d()->stackTrace;
1347 else
1349
1351 debug->aboutToThrow();
1352
1353 return Encode::undefined();
1354}
1355
1357{
1359 if (trace)
1362 hasException = false;
1365 return res;
1366}
1367
1369{
1370 Scope scope(this);
1371 ScopedValue v(scope, newString(message));
1372 v = newErrorObject(v);
1373 return throwError(v);
1374}
1375
1377{
1378 Scope scope(this);
1380 return throwError(error);
1381}
1382
1384{
1385 Scope scope(this);
1387 return throwError(error);
1388}
1389
1390
1392{
1393 Scope scope(this);
1394 ScopedObject error(scope, newTypeErrorObject(QStringLiteral("Type error")));
1395 return throwError(error);
1396}
1397
1399{
1400 Scope scope(this);
1402 return throwError(error);
1403}
1404
1406{
1407 Scope scope(this);
1408 QString msg = name + QLatin1String(" is not defined");
1410 return throwError(error);
1411}
1412
1414{
1415 Scope scope(this);
1416 ScopedString s(scope, value.toString(this));
1417 QString msg = s->toQString() + QLatin1String(" is not defined");
1419 return throwError(error);
1420}
1421
1423{
1424 Scope scope(this);
1425 QString msg = message;
1427 return throwError(error);
1428}
1429
1431{
1432 Scope scope(this);
1434 return throwError(error);
1435}
1436
1438{
1439 Scope scope(this);
1440 ScopedString s(scope, value.toString(this));
1441 QString msg = s->toQString() + QLatin1String(" out of range");
1443 return throwError(error);
1444}
1445
1447{
1448 Scope scope(this);
1450 return throwError(error);
1451}
1452
1454{
1455 Scope scope(this);
1456 ScopedValue v(scope, newString(QLatin1String("Unimplemented ") + message));
1457 v = newErrorObject(v);
1458 return throwError(v);
1459}
1460
1461
1463{
1465 QV4::Scope scope(this);
1466 QV4::ScopedValue exception(scope, catchException(&trace));
1468 if (!trace.isEmpty()) {
1469 QV4::StackFrame frame = trace.constFirst();
1470 error.setUrl(QUrl(frame.source));
1471 error.setLine(qAbs(frame.line));
1472 error.setColumn(frame.column);
1473 }
1474 QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
1475 error.setDescription(exception->toQStringNoThrow());
1476 return error;
1477}
1478
1479// Variant conversion code
1480
1482static QVariant toVariant(
1483 const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols,
1484 V4ObjectSet *visitedObjects);
1485static QObject *qtObjectFromJS(const QV4::Value &value);
1486static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr);
1487static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result);
1490{
1491 return v4->metaTypeToJS(value.metaType(), value.constData());
1492}
1493
1495 const QV4::Value &value, QMetaType metaType, bool createJSValueForObjectsAndSymbols,
1496 V4ObjectSet *visitedObjects)
1497{
1498 Q_ASSERT (!value.isEmpty());
1499
1501 return v->d()->data();
1502
1503 if (metaType == QMetaType::fromType<bool>())
1504 return QVariant(value.toBoolean());
1505
1506 if (metaType == QMetaType::fromType<double>())
1507 return QVariant(value.toNumber());
1508
1509 if (metaType == QMetaType::fromType<float>())
1510 return QVariant(float(value.toNumber()));
1511
1512 if (metaType == QMetaType::fromType<QJsonValue>())
1514
1515 if (metaType == QMetaType::fromType<QJSValue>())
1517
1518 if (const QV4::Object *o = value.as<QV4::Object>()) {
1519 QV4::Scope scope(o->engine());
1520 QV4::ScopedObject object(scope, o);
1521 if (metaType == QMetaType::fromType<QJsonObject>()
1522 && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
1525 return QVariant::fromValue<QObject *>(wrapper->object());
1526 } else if (object->as<QV4::QQmlContextWrapper>()) {
1527 return QVariant();
1529 return w->toVariant();
1531 return v->toVariant();
1532 } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
1533 return l->toVariant();
1534 } else if (QV4::Sequence *s = object->as<QV4::Sequence>()) {
1536 }
1537 }
1538
1539 if (const QV4::ArrayObject *o = value.as<ArrayObject>()) {
1540 QV4::Scope scope(o->engine());
1541 QV4::ScopedArrayObject a(scope, o);
1542 if (metaType == QMetaType::fromType<QList<QObject *>>()) {
1544 uint length = a->getLength();
1545 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
1546 for (uint ii = 0; ii < length; ++ii) {
1547 qobjectWrapper = a->get(ii);
1548 if (!!qobjectWrapper) {
1549 list << qobjectWrapper->object();
1550 } else {
1551 list << 0;
1552 }
1553 }
1554
1555 return QVariant::fromValue<QList<QObject*> >(list);
1556 } else if (metaType == QMetaType::fromType<QJsonArray>()) {
1558 }
1559
1561 if (retn.isValid())
1562 return retn;
1563
1564 if (metaType.isValid()) {
1565 retn = QVariant(metaType, nullptr);
1566 auto retnAsIterable = retn.value<QSequentialIterable>();
1567 if (retnAsIterable.metaContainer().canAddValue()) {
1568 QMetaType valueMetaType = retnAsIterable.metaContainer().valueMetaType();
1569 auto const length = a->getLength();
1570 QV4::ScopedValue arrayValue(scope);
1571 for (qint64 i = 0; i < length; ++i) {
1572 arrayValue = a->get(i);
1574 arrayValue, valueMetaType);
1575 if (asVariant.isValid()) {
1576 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1577 continue;
1578 }
1579
1580 if (QMetaType::canConvert(QMetaType::fromType<QJSValue>(), valueMetaType)) {
1581 // before attempting a conversion from the concrete types,
1582 // check if there exists a conversion from QJSValue -> out type
1583 // prefer that one for compatibility reasons
1585 arrayValue->asReturnedValue()));
1586 if (asVariant.convert(valueMetaType)) {
1587 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1588 continue;
1589 }
1590 }
1591
1592 asVariant = toVariant(arrayValue, valueMetaType, false, visitedObjects);
1593 if (valueMetaType == QMetaType::fromType<QVariant>()) {
1594 retnAsIterable.metaContainer().addValue(retn.data(), &asVariant);
1595 } else {
1596 auto originalType = asVariant.metaType();
1597 bool couldConvert = asVariant.convert(valueMetaType);
1598 if (!couldConvert) {
1599 qWarning().noquote()
1600 << QLatin1String("Could not convert array value "
1601 "at position %1 from %2 to %3")
1603 QString::fromUtf8(originalType.name()),
1604 QString::fromUtf8(valueMetaType.name()));
1605 // create default constructed value
1606 asVariant = QVariant(valueMetaType, nullptr);
1607 }
1608 retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
1609 }
1610 }
1611 return retn;
1612 }
1613 }
1614 }
1615
1616 if (value.isUndefined())
1617 return QVariant();
1618 if (value.isNull())
1619 return QVariant::fromValue(nullptr);
1620 if (value.isBoolean())
1621 return value.booleanValue();
1622 if (value.isInteger())
1623 return value.integerValue();
1624 if (value.isNumber())
1625 return value.asDouble();
1626 if (String *s = value.stringValue()) {
1627 const QString &str = s->toQString();
1628 // QChars are stored as a strings
1629 if (metaType == QMetaType::fromType<QChar>() && str.size() == 1)
1630 return str.at(0);
1631 return str;
1632 }
1633#if QT_CONFIG(qml_locale)
1635 return *ld->d()->locale;
1636#endif
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 createJSValueForObjectsAndSymbols
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 (createJSValueForObjectsAndSymbols)
1679 return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue()));
1680
1681 return objectToVariant(o, visitedObjects);
1682}
1683
1684
1686 const Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols)
1687{
1688 return ::toVariant(value, typeHint, createJSValueForObjectsAndSymbols, nullptr);
1689}
1690
1691static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects)
1692{
1693 Q_ASSERT(o);
1694
1695 V4ObjectSet recursionGuardSet;
1696 if (!visitedObjects) {
1697 visitedObjects = &recursionGuardSet;
1698 } else if (visitedObjects->contains(o->d())) {
1699 // Avoid recursion.
1700 // For compatibility with QVariant{List,Map} conversion, we return an
1701 // empty object (and no error is thrown).
1702 if (o->as<ArrayObject>())
1703 return QVariantList();
1704 return QVariantMap();
1705 }
1706 visitedObjects->insert(o->d());
1707
1709
1710 if (o->as<ArrayObject>()) {
1711 QV4::Scope scope(o->engine());
1712 QV4::ScopedArrayObject a(scope, o->asReturnedValue());
1713 QV4::ScopedValue v(scope);
1715
1716 int length = a->getLength();
1717 for (int ii = 0; ii < length; ++ii) {
1718 v = a->get(ii);
1719 list << ::toVariant(v, QMetaType {}, /*createJSValueForObjectsAndSymbols*/false,
1720 visitedObjects);
1721 }
1722
1723 result = list;
1724 } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()) {
1726 QV4::Scope scope(o->engine());
1728 QV4::ScopedValue name(scope);
1729 QV4::ScopedValue val(scope);
1730 while (1) {
1731 name = it.nextPropertyNameAsString(val);
1732 if (name->isNull())
1733 break;
1734
1735 QString key = name->toQStringNoThrow();
1737 val, /*type hint*/ QMetaType {},
1738 /*createJSValueForObjectsAndSymbols*/false, visitedObjects));
1739 }
1740
1741 result = map;
1742 } else {
1743 // If it's not a plain object, we can only save it as QJSValue.
1745 }
1746
1747 visitedObjects->remove(o->d());
1748 return result;
1749}
1750
1757 QMetaType metaType, const void *ptr,
1758 QV4::Heap::Object *container, int property, uint flags)
1759{
1760 const auto createSequence = [&](const QMetaSequence metaSequence) {
1761 QV4::Scope scope(this);
1762 QV4::Scoped<Sequence> sequence(scope);
1763 if (container) {
1765 this, metaType, metaSequence, ptr,
1766 container, property, Heap::ReferenceObject::Flags(flags));
1767 } else {
1768 return QV4::SequencePrototype::fromData(this, metaType, metaSequence, ptr);
1769 }
1770 };
1771
1772 const int type = metaType.id();
1773 if (type < QMetaType::User) {
1774 switch (QMetaType::Type(type)) {
1776 case QMetaType::Void:
1777 return QV4::Encode::undefined();
1778 case QMetaType::Nullptr:
1779 case QMetaType::VoidStar:
1780 return QV4::Encode::null();
1781 case QMetaType::Bool:
1782 return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
1783 case QMetaType::Int:
1784 return QV4::Encode(*reinterpret_cast<const int*>(ptr));
1785 case QMetaType::UInt:
1786 return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
1787 case QMetaType::Long:
1788 return QV4::Encode((double)*reinterpret_cast<const long *>(ptr));
1789 case QMetaType::ULong:
1790 return QV4::Encode((double)*reinterpret_cast<const ulong *>(ptr));
1791 case QMetaType::LongLong:
1792 return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
1793 case QMetaType::ULongLong:
1794 return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
1795 case QMetaType::Double:
1796 return QV4::Encode(*reinterpret_cast<const double*>(ptr));
1797 case QMetaType::QString:
1798 return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
1799 case QMetaType::QByteArray:
1800 return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue();
1801 case QMetaType::Float:
1802 return QV4::Encode(*reinterpret_cast<const float*>(ptr));
1803 case QMetaType::Short:
1804 return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
1805 case QMetaType::UShort:
1806 return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
1807 case QMetaType::Char:
1808 return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
1809 case QMetaType::UChar:
1810 return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
1811 case QMetaType::SChar:
1812 return QV4::Encode((int)*reinterpret_cast<const signed char*>(ptr));
1813 case QMetaType::QChar:
1814 return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue();
1815 case QMetaType::Char16:
1816 return newString(QChar(*reinterpret_cast<const char16_t *>(ptr)))->asReturnedValue();
1817 case QMetaType::QDateTime:
1819 *reinterpret_cast<const QDateTime *>(ptr),
1820 container, property, flags));
1821 case QMetaType::QDate:
1823 *reinterpret_cast<const QDate *>(ptr),
1824 container, property, flags));
1825 case QMetaType::QTime:
1827 *reinterpret_cast<const QTime *>(ptr),
1828 container, property, flags));
1829#if QT_CONFIG(regularexpression)
1830 case QMetaType::QRegularExpression:
1831 return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
1832#endif
1833 case QMetaType::QObjectStar:
1834 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1835 case QMetaType::QStringList:
1836 return createSequence(QMetaSequence::fromContainer<QStringList>());
1837 case QMetaType::QVariantList:
1838 return createSequence(QMetaSequence::fromContainer<QVariantList>());
1839 case QMetaType::QVariantMap:
1840 return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr));
1841 case QMetaType::QJsonValue:
1842 return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
1843 case QMetaType::QJsonObject:
1844 return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr));
1845 case QMetaType::QJsonArray:
1846 return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr));
1847#if QT_CONFIG(qml_locale)
1848 case QMetaType::QLocale:
1849 return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
1850#endif
1851 case QMetaType::QPixmap:
1852 case QMetaType::QImage:
1853 // Scarce value types
1854 return QV4::Encode(newVariantObject(metaType, ptr));
1855 default:
1856 break;
1857 }
1858 }
1859
1860 if (metaType.flags() & QMetaType::IsEnumeration)
1861 return fromData(metaType.underlyingType(), ptr, container, property, flags);
1862
1863 QV4::Scope scope(this);
1864 if (metaType == QMetaType::fromType<QQmlListReference>()) {
1865 typedef QQmlListReferencePrivate QDLRP;
1866 QDLRP *p = QDLRP::get((QQmlListReference*)const_cast<void *>(ptr));
1867 if (p->object)
1868 return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType);
1869 else
1870 return QV4::Encode::null();
1871 } else if (auto flags = metaType.flags(); flags & QMetaType::IsQmlList) {
1872 // casting to QQmlListProperty<QObject> is slightly nasty, but it's the
1873 // same QQmlListReference does.
1874 const auto *p = static_cast<const QQmlListProperty<QObject> *>(ptr);
1875 if (p->object)
1876 return QV4::QmlListWrapper::create(scope.engine, *p, metaType);
1877 else
1878 return QV4::Encode::null();
1879 } else if (metaType == QMetaType::fromType<QJSValue>()) {
1881 this, *reinterpret_cast<const QJSValue *>(ptr));
1882 } else if (metaType == QMetaType::fromType<QList<QObject *> >()) {
1883 // XXX Can this be made more by using Array as a prototype and implementing
1884 // directly against QList<QObject*>?
1885 const QList<QObject *> &list = *(const QList<QObject *>*)ptr;
1887 a->arrayReserve(list.size());
1888 QV4::ScopedValue v(scope);
1889 for (int ii = 0; ii < list.size(); ++ii)
1890 a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(this, list.at(ii))));
1891 a->setArrayLengthUnchecked(list.size());
1892 return a.asReturnedValue();
1893 } else if (auto flags = metaType.flags(); flags & QMetaType::PointerToQObject) {
1894 if (flags.testFlag(QMetaType::IsConst))
1895 return QV4::QObjectWrapper::wrapConst(this, *reinterpret_cast<QObject* const *>(ptr));
1896 else
1897 return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
1898 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
1899 const QJSPrimitiveValue *primitive = static_cast<const QJSPrimitiveValue *>(ptr);
1900 switch (primitive->type()) {
1902 return Encode(primitive->asBoolean());
1904 return Encode(primitive->asInteger());
1906 return newString(primitive->asString())->asReturnedValue();
1908 return Encode::undefined();
1910 return Encode::null();
1912 return Encode(primitive->asDouble());
1913 }
1914 }
1915
1916 if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(metaType)) {
1917 if (container) {
1919 this, ptr, vtmo, metaType,
1920 container, property, Heap::ReferenceObject::Flags(flags));
1921 } else {
1922 return QV4::QQmlValueTypeWrapper::create(this, ptr, vtmo, metaType);
1923 }
1924 }
1925
1926 const QQmlType listType = QQmlMetaType::qmlListType(metaType);
1927 if (listType.isSequentialContainer())
1928 return createSequence(listType.listMetaSequence());
1929
1930 QSequentialIterable iterable;
1931 if (QMetaType::convert(metaType, ptr, QMetaType::fromType<QSequentialIterable>(), &iterable)) {
1932
1933 // If the resulting iterable is useful for anything, turn it into a QV4::Sequence.
1934 const QMetaSequence sequence = iterable.metaContainer();
1935 if (sequence.hasSize() && sequence.canGetValueAtIndex())
1936 return createSequence(sequence);
1937
1938 // As a last resort, try to read the contents of the container via an iterator
1939 // and build a JS array from them.
1940 if (sequence.hasConstIterator() && sequence.canGetValueAtConstIterator()) {
1942 for (auto it = iterable.constBegin(), end = iterable.constEnd(); it != end; ++it)
1943 a->push_back(fromVariant(*it));
1944 return a.asReturnedValue();
1945 }
1946 }
1947
1948 return QV4::Encode(newVariantObject(metaType, ptr));
1949}
1950
1952{
1953 return fromData(variant.metaType(), variant.constData());
1954}
1955
1957 const QVariant &variant, Heap::Object *parent, int property, uint flags)
1958{
1960}
1961
1963{
1964 return objectToVariant(o).toMap();
1965}
1966
1967// Converts a QVariantMap to JS.
1968// The result is a new Object object with property names being
1969// the keys of the QVariantMap, and values being the values of
1970// the QVariantMap converted to JS, recursively.
1972{
1973 QV4::Scope scope(v4);
1974 QV4::ScopedObject o(scope, v4->newObject());
1975 QV4::ScopedString s(scope);
1977 QV4::ScopedValue v(scope);
1978 for (QVariantMap::const_iterator it = vmap.constBegin(), cend = vmap.constEnd(); it != cend; ++it) {
1979 s = v4->newIdentifier(it.key());
1980 key = s->propertyKey();
1981 v = variantToJS(v4, it.value());
1982 if (key->isArrayIndex())
1983 o->arraySet(key->asArrayIndex(), v);
1984 else
1985 o->insertMember(s, v);
1986 }
1987 return o.asReturnedValue();
1988}
1989
1990// Converts the meta-type defined by the given type and data to JS.
1991// Returns the value if conversion succeeded, an empty handle otherwise.
1993{
1994 Q_ASSERT(data != nullptr);
1995
1996 if (type == QMetaType::fromType<QVariant>()) {
1997 // unwrap it: this is tested in QJSEngine, and makes the most sense for
1998 // end-user code too.
1999 return fromVariant(*reinterpret_cast<const QVariant*>(data));
2000 } else if (type == QMetaType::fromType<QUrl>()) {
2001 // Create a proper URL object here, rather than a variant.
2002 return newUrlObject(*reinterpret_cast<const QUrl *>(data))->asReturnedValue();
2003 }
2004
2005 return fromData(type, data);
2006}
2007
2009{
2010 return s_maxJSStackSize;
2011}
2012
2014{
2015 return s_maxGCStackSize;
2016}
2017
2025{
2026 if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max())) {
2027 throwRangeError(QStringLiteral("Invalid array length."));
2028 return 0;
2029 }
2030 if (len64 > qint64(this->jsStackLimit - this->jsStackTop)) {
2031 throwRangeError(QStringLiteral("Array too large for apply()."));
2032 return 0;
2033 }
2034 return len64;
2035}
2036
2038{
2039 return globalObject->asReturnedValue();
2040}
2041
2043{
2045 const DiskCacheOptions options = diskCacheOptions();
2046 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (options & DiskCache::Aot)
2048 url,
2049 (options & DiskCache::AotByteCode)
2052 &cacheError)
2053 : nullptr) {
2056 cachedUnit->qmlData, cachedUnit->aotCompiledFunctions,
2057 url.fileName(), url.toString()));
2058 }
2059
2061 if (!f.open(QIODevice::ReadOnly)) {
2062 throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString()));
2063 return nullptr;
2064 }
2065
2066 const QDateTime timeStamp = QFileInfo(f).lastModified();
2067
2068 const QString sourceCode = QString::fromUtf8(f.readAll());
2069 f.close();
2070
2071 return compileModule(url, sourceCode, timeStamp);
2072}
2073
2074
2076 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
2077{
2079 auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
2080 sourceCode, sourceTimeStamp, &diagnostics);
2081 for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
2082 if (m.isError()) {
2083 throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
2084 return nullptr;
2085 } else {
2086 qWarning() << url << ':' << m.loc.startLine << ':' << m.loc.startColumn
2087 << ": warning: " << m.message;
2088 }
2089 }
2090
2091 return ExecutableCompilationUnit::create(std::move(unit));
2092}
2093
2095{
2096 // Injection can happen from the QML type loader thread for example, but instantiation and
2097 // evaluation must be limited to the ExecutionEngine's thread.
2098 QMutexLocker moduleGuard(&moduleMutex);
2099 modules.insert(moduleUnit->finalUrl(), moduleUnit);
2100}
2101
2103 const QUrl &url, const ExecutableCompilationUnit *referrer) const
2104{
2105 QMutexLocker moduleGuard(&moduleMutex);
2106 const auto nativeModule = nativeModules.find(url);
2107 if (nativeModule != nativeModules.end())
2108 return Module { nullptr, *nativeModule };
2109
2110 const QUrl resolved = referrer
2113 auto existingModule = modules.find(resolved);
2114 if (existingModule == modules.end())
2115 return Module { nullptr, nullptr };
2116 return Module { *existingModule, nullptr };
2117}
2118
2120{
2121 QMutexLocker moduleGuard(&moduleMutex);
2122 const auto nativeModule = nativeModules.find(url);
2123 if (nativeModule != nativeModules.end())
2124 return Module { nullptr, *nativeModule };
2125
2126 const QUrl resolved = referrer
2129 auto existingModule = modules.find(resolved);
2130 if (existingModule != modules.end())
2131 return Module { *existingModule, nullptr };
2132
2133 moduleGuard.unlock();
2134
2135 auto newModule = compileModule(resolved);
2136 if (newModule) {
2137 moduleGuard.relock();
2138 modules.insert(resolved, newModule);
2139 }
2140
2141 return Module { newModule, nullptr };
2142}
2143
2145{
2146 QMutexLocker moduleGuard(&moduleMutex);
2147 const auto existingModule = nativeModules.find(url);
2148 if (existingModule != nativeModules.end())
2149 return nullptr;
2150
2152 *val = module.asReturnedValue();
2153 nativeModules.insert(url, val);
2154 return val;
2155}
2156
2157static ExecutionEngine::DiskCacheOptions transFormDiskCache(const char *v)
2158{
2159 using DiskCache = ExecutionEngine::DiskCache;
2160
2161 if (v == nullptr)
2162 return DiskCache::Enabled;
2163
2164 ExecutionEngine::DiskCacheOptions result = DiskCache::Disabled;
2165 const QList<QByteArray> options = QByteArray(v).split(',');
2166 for (const QByteArray &option : options) {
2167 if (option == "aot-bytecode")
2168 result |= DiskCache::AotByteCode;
2169 else if (option == "aot-native")
2170 result |= DiskCache::AotNative;
2171 else if (option == "aot")
2172 result |= DiskCache::Aot;
2173 else if (option == "qmlc-read")
2174 result |= DiskCache::QmlcRead;
2175 else if (option == "qmlc-write")
2176 result |= DiskCache::QmlcWrite;
2177 else if (option == "qmlc")
2178 result |= DiskCache::Qmlc;
2179 else
2180 qWarning() << "Ignoring unknown option to QML_DISK_CACHE:" << option;
2181 }
2182
2183 return result;
2184}
2185
2186ExecutionEngine::DiskCacheOptions ExecutionEngine::diskCacheOptions() const
2187{
2188 if (forceDiskCache())
2189 return DiskCache::Enabled;
2190 if (disableDiskCache() || debugger())
2191 return DiskCache::Disabled;
2192 static const DiskCacheOptions options = qmlGetConfigOption<
2193 DiskCacheOptions, transFormDiskCache>("QML_DISK_CACHE");
2194 return options;
2195}
2196
2198 QV4::ExecutionContext *context, int argc, void **args,
2200{
2201 if (!args) {
2202 Q_ASSERT(argc == 0);
2203 void *dummyArgs[] = { nullptr };
2204 QMetaType dummyTypes[] = { QMetaType::fromType<void>() };
2205 function->call(self, dummyArgs, dummyTypes, argc, context);
2206 return;
2207 }
2208 Q_ASSERT(types); // both args and types must be present
2209 // implicitly sets the return value, which is args[0]
2210 function->call(self, args, types, argc, context);
2211}
2212
2214 QV4::ExecutionContext *context, int argc,
2215 const QV4::Value *argv)
2216{
2217 QV4::Scope scope(this);
2218 QV4::ScopedObject jsSelf(scope, QV4::QObjectWrapper::wrap(this, self));
2219 Q_ASSERT(jsSelf);
2220 return function->call(jsSelf, argv, argc, context);
2221}
2222
2224{
2227}
2228
2230{
2232
2234
2235#if QT_CONFIG(qml_locale)
2239#endif
2240
2241#if QT_CONFIG(qml_xml_http_request)
2243 m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
2244#endif
2245
2247
2248 {
2249 for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
2250 if (globalObject->internalClass()->nameMap.at(i).isString()) {
2252 m_illegalNames.insert(id.toQString());
2253 }
2254 }
2255 }
2256}
2257
2259{
2260 QV4::Scope scope(this);
2261 QtObject *qtObject = new QtObject(this);
2263
2264 QV4::ScopedObject qtObjectWrapper(
2265 scope, QV4::QObjectWrapper::wrap(this, qtObject));
2266 QV4::ScopedObject qtNamespaceWrapper(
2267 scope, QV4::QMetaObjectWrapper::create(this, &Qt::staticMetaObject));
2268 QV4::ScopedObject qtObjectProtoWrapper(
2269 scope, qtObjectWrapper->getPrototypeOf());
2270
2271 qtNamespaceWrapper->setPrototypeOf(qtObjectProtoWrapper);
2272 qtObjectWrapper->setPrototypeOf(qtNamespaceWrapper);
2273
2274 globalObject->defineDefaultProperty(QStringLiteral("Qt"), qtObjectWrapper);
2275}
2276
2278{
2279 return m_illegalNames;
2280}
2281
2283{
2284 // Second stage of initialization. We're updating some more prototypes here.
2285 isInitialized = false;
2286 m_qmlEngine = engine;
2288 isInitialized = true;
2289}
2290
2292{
2294 return;
2295
2296 QV4::Scope scope(v4);
2297
2298 bool instanceOfObject = false;
2299 QV4::ScopedObject p(scope, object->getPrototypeOf());
2300 while (p) {
2301 if (p->d() == v4->objectPrototype()->d()) {
2302 instanceOfObject = true;
2303 break;
2304 }
2305 p = p->getPrototypeOf();
2306 }
2307 if (!instanceOfObject)
2308 return;
2309
2310 Heap::InternalClass *frozen = object->internalClass()->frozen();
2311 object->setInternalClass(frozen); // Immediately assign frozen to prevent it from getting GC'd
2312
2313 QV4::ScopedObject o(scope);
2314 for (uint i = 0; i < frozen->size; ++i) {
2315 if (!frozen->nameMap.at(i).isStringOrSymbol())
2316 continue;
2317 o = *object->propertyData(i);
2318 if (o)
2319 freeze_recursive(v4, o);
2320 }
2321}
2322
2324{
2325 QV4::Scope scope(this);
2326 QV4::ScopedObject o(scope, value);
2327 freeze_recursive(this, o);
2328}
2329
2331{
2332 QV4::Scope scope(this);
2333 ScopedObject object(scope, value);
2334 if (!object)
2335 return;
2336
2337 std::vector<Heap::Object *> stack { object->d() };
2338
2339 // Methods meant to be overridden
2340 const PropertyKey writableMembers[] = {
2345 };
2346 const auto writableBegin = std::begin(writableMembers);
2347 const auto writableEnd = std::end(writableMembers);
2348
2349 while (!stack.empty()) {
2350 object = stack.back();
2351 stack.pop_back();
2352
2354 continue;
2355
2356 Scoped<InternalClass> locked(scope, object->internalClass()->locked());
2357 QV4::ScopedObject member(scope);
2358
2359 // Taking this copy is cheap. It's refcounted. This avoids keeping a reference
2360 // to the original IC.
2361 const SharedInternalClassData<PropertyKey> nameMap = locked->d()->nameMap;
2362
2363 for (uint i = 0, end = locked->d()->size; i < end; ++i) {
2364 const PropertyKey key = nameMap.at(i);
2365 if (!key.isStringOrSymbol())
2366 continue;
2367 if ((member = *object->propertyData(i))) {
2368 stack.push_back(member->d());
2369 if (std::find(writableBegin, writableEnd, key) == writableEnd) {
2370 PropertyAttributes attributes = locked->d()->find(key).attributes;
2371 attributes.setConfigurable(false);
2372 attributes.setWritable(false);
2373 locked = locked->changeMember(key, attributes);
2374 }
2375 }
2376 }
2377
2378 object->setInternalClass(locked->d());
2379 }
2380}
2381
2383{
2384 if (!m_time.isValid())
2385 m_time.start();
2386 m_startedTimers[timerName] = m_time.elapsed();
2387}
2388
2389qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
2390{
2391 if (!m_startedTimers.contains(timerName)) {
2392 *wasRunning = false;
2393 return 0;
2394 }
2395 *wasRunning = true;
2396 qint64 startedAt = m_startedTimers.take(timerName);
2397 return m_time.elapsed() - startedAt;
2398}
2399
2401{
2403 int number = m_consoleCount.value(key, 0);
2404 number++;
2405 m_consoleCount.insert(key, number);
2406 return number;
2407}
2408
2410{
2411 if (m_extensionData.size() <= index)
2412 m_extensionData.resize(index + 1);
2413
2414 if (m_extensionData.at(index))
2415 delete m_extensionData.at(index);
2416
2417 m_extensionData[index] = data;
2418}
2419
2420template<typename Source>
2421bool convertToIterable(QMetaType metaType, void *data, Source *sequence)
2422{
2423 QSequentialIterable iterable;
2424 if (!QMetaType::view(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable))
2425 return false;
2426
2427 const QMetaType elementMetaType = iterable.valueMetaType();
2428 QVariant element(elementMetaType);
2429 for (qsizetype i = 0, end = sequence->getLength(); i < end; ++i) {
2430 if (!ExecutionEngine::metaTypeFromJS(sequence->get(i), elementMetaType, element.data()))
2431 element = QVariant(elementMetaType);
2432 iterable.addValue(element, QSequentialIterable::AtEnd);
2433 }
2434 return true;
2435}
2436
2437// Converts a JS value to a meta-type.
2438// data must point to a place that can store a value of the given type.
2439// Returns true if conversion succeeded, false otherwise.
2441{
2442 // check if it's one of the types we know
2443 switch (metaType.id()) {
2444 case QMetaType::Bool:
2445 *reinterpret_cast<bool*>(data) = value.toBoolean();
2446 return true;
2447 case QMetaType::Int:
2448 *reinterpret_cast<int*>(data) = value.toInt32();
2449 return true;
2450 case QMetaType::UInt:
2451 *reinterpret_cast<uint*>(data) = value.toUInt32();
2452 return true;
2453 case QMetaType::LongLong:
2454 *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
2455 return true;
2456 case QMetaType::ULongLong:
2457 *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
2458 return true;
2459 case QMetaType::Double:
2460 *reinterpret_cast<double*>(data) = value.toNumber();
2461 return true;
2462 case QMetaType::QString:
2463 if (value.isUndefined())
2464 *reinterpret_cast<QString*>(data) = QStringLiteral("undefined");
2465 else if (value.isNull())
2466 *reinterpret_cast<QString*>(data) = QStringLiteral("null");
2467 else
2468 *reinterpret_cast<QString*>(data) = value.toQString();
2469 return true;
2470 case QMetaType::QByteArray:
2471 if (const ArrayBuffer *ab = value.as<ArrayBuffer>())
2472 *reinterpret_cast<QByteArray*>(data) = ab->asByteArray();
2473 else if (const String *string = value.as<String>())
2474 *reinterpret_cast<QByteArray*>(data) = string->toQString().toUtf8();
2475 else
2476 *reinterpret_cast<QByteArray*>(data) = QByteArray();
2477 return true;
2478 case QMetaType::Float:
2479 *reinterpret_cast<float*>(data) = value.toNumber();
2480 return true;
2481 case QMetaType::Short:
2482 *reinterpret_cast<short*>(data) = short(value.toInt32());
2483 return true;
2484 case QMetaType::UShort:
2485 *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
2486 return true;
2487 case QMetaType::Char:
2488 *reinterpret_cast<char*>(data) = char(value.toInt32());
2489 return true;
2490 case QMetaType::UChar:
2491 *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
2492 return true;
2493 case QMetaType::SChar:
2494 *reinterpret_cast<signed char*>(data) = (signed char)(value.toInt32());
2495 return true;
2496 case QMetaType::QChar:
2497 if (String *s = value.stringValue()) {
2498 QString str = s->toQString();
2499 *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
2500 } else {
2501 *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
2502 }
2503 return true;
2504 case QMetaType::QDateTime:
2505 if (const QV4::DateObject *d = value.as<DateObject>()) {
2506 *reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
2507 return true;
2508 } break;
2509 case QMetaType::QDate:
2510 if (const QV4::DateObject *d = value.as<DateObject>()) {
2511 *reinterpret_cast<QDate *>(data) = DateObject::dateTimeToDate(d->toQDateTime());
2512 return true;
2513 } break;
2514 case QMetaType::QTime:
2515 if (const QV4::DateObject *d = value.as<DateObject>()) {
2516 *reinterpret_cast<QTime *>(data) = d->toQDateTime().time();
2517 return true;
2518 } break;
2519 case QMetaType::QUrl:
2520 if (String *s = value.stringValue()) {
2521 *reinterpret_cast<QUrl *>(data) = QUrl(s->toQString());
2522 return true;
2523 } else if (const QV4::UrlObject *d = value.as<UrlObject>()) {
2524 *reinterpret_cast<QUrl *>(data) = d->toQUrl();
2525 return true;
2526 } else if (const QV4::VariantObject *d = value.as<VariantObject>()) {
2527 const QVariant *variant = &d->d()->data();
2528 if (variant->metaType() == QMetaType::fromType<QUrl>()) {
2529 *reinterpret_cast<QUrl *>(data)
2530 = *reinterpret_cast<const QUrl *>(variant->constData());
2531 return true;
2532 }
2533 }
2534 break;
2535#if QT_CONFIG(regularexpression)
2536 case QMetaType::QRegularExpression:
2537 if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
2538 *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
2539 return true;
2540 } break;
2541#endif
2542 case QMetaType::QObjectStar: {
2543 if (value.isNull()) {
2544 *reinterpret_cast<QObject* *>(data) = nullptr;
2545 return true;
2546 }
2547 if (value.as<QV4::QObjectWrapper>()) {
2548 *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
2549 return true;
2550 }
2551 break;
2552 }
2553 case QMetaType::QStringList: {
2555 if (a) {
2556 *reinterpret_cast<QStringList *>(data) = a->toQStringList();
2557 return true;
2558 }
2559 break;
2560 }
2561 case QMetaType::QVariantList: {
2563 if (a) {
2564 *reinterpret_cast<QVariantList *>(data) = ExecutionEngine::toVariant(
2565 *a, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false)
2566 .toList();
2567 return true;
2568 }
2569 break;
2570 }
2571 case QMetaType::QVariantMap: {
2572 const QV4::Object *o = value.as<QV4::Object>();
2573 if (o) {
2574 *reinterpret_cast<QVariantMap *>(data) = o->engine()->variantMapFromJS(o);
2575 return true;
2576 }
2577 break;
2578 }
2580 if (value.as<QV4::Managed>()) {
2581 *reinterpret_cast<QVariant*>(data) = ExecutionEngine::toVariant(
2582 value, /*typeHint*/QMetaType{}, /*createJSValueForObjectsAndSymbols*/false);
2583 } else if (value.isNull()) {
2584 *reinterpret_cast<QVariant*>(data) = QVariant::fromValue(nullptr);
2585 } else if (value.isUndefined()) {
2586 *reinterpret_cast<QVariant*>(data) = QVariant();
2587 } else if (value.isBoolean()) {
2588 *reinterpret_cast<QVariant*>(data) = QVariant(value.booleanValue());
2589 } else if (value.isInteger()) {
2590 *reinterpret_cast<QVariant*>(data) = QVariant(value.integerValue());
2591 } else if (value.isDouble()) {
2592 *reinterpret_cast<QVariant*>(data) = QVariant(value.doubleValue());
2593 }
2594 return true;
2595 case QMetaType::QJsonValue:
2596 *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
2597 return true;
2598 case QMetaType::QJsonObject: {
2599 *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.as<Object>());
2600 return true;
2601 }
2602 case QMetaType::QJsonArray: {
2604 if (a) {
2605 *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
2606 return true;
2607 }
2608 break;
2609 }
2610#if QT_CONFIG(qml_locale)
2611 case QMetaType::QLocale: {
2612 if (const QV4::QQmlLocaleData *l = value.as<QQmlLocaleData>()) {
2613 *reinterpret_cast<QLocale *>(data) = *l->d()->locale;
2614 return true;
2615 }
2616 break;
2617 }
2618#endif
2619 default:
2620 break;
2621 }
2622
2623 if (metaType.flags() & QMetaType::IsEnumeration) {
2624 *reinterpret_cast<int *>(data) = value.toInt32();
2625 return true;
2626 }
2627
2628 if (metaType == QMetaType::fromType<QQmlListReference>()) {
2630 *reinterpret_cast<QQmlListReference *>(data) = wrapper->toListReference();
2631 return true;
2632 }
2633 }
2634
2635 if (const QQmlValueTypeWrapper *vtw = value.as<QQmlValueTypeWrapper>()) {
2636 const QMetaType valueType = vtw->type();
2637 if (valueType == metaType)
2638 return vtw->toGadget(data);
2639
2640 Heap::QQmlValueTypeWrapper *d = vtw->d();
2641 if (d->isReference())
2642 d->readReference();
2643
2644 if (void *gadgetPtr = d->gadgetPtr()) {
2645 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, gadgetPtr))
2646 return true;
2647 if (QMetaType::canConvert(valueType, metaType))
2648 return QMetaType::convert(valueType, gadgetPtr, metaType, data);
2649 } else {
2650 QVariant empty(valueType);
2651 if (QQmlValueTypeProvider::populateValueType(metaType, data, valueType, empty.data()))
2652 return true;
2653 if (QMetaType::canConvert(valueType, metaType))
2654 return QMetaType::convert(valueType, empty.data(), metaType, data);
2655 }
2656 }
2657
2658 // Try to use magic; for compatibility with qjsvalue_cast.
2659
2660 if (convertToNativeQObject(value, metaType, reinterpret_cast<void **>(data)))
2661 return true;
2662
2663 const bool isPointer = (metaType.flags() & QMetaType::IsPointer);
2664 const QV4::VariantObject *variantObject = value.as<QV4::VariantObject>();
2665 if (variantObject) {
2666 // Actually a reference, because we're poking it for its data() below and we want
2667 // the _original_ data, not some copy.
2668 QVariant &var = variantObject->d()->data();
2669
2670 if (var.metaType() == metaType) {
2671 metaType.destruct(data);
2672 metaType.construct(data, var.data());
2673 return true;
2674 }
2675
2676 if (isPointer) {
2677 const QByteArray pointedToTypeName = QByteArray(metaType.name()).chopped(1);
2678 const QMetaType valueType = QMetaType::fromName(pointedToTypeName);
2679
2680 if (valueType == var.metaType()) {
2681 // ### Qt7: Remove this. Returning pointers to potentially gc'd data is crazy.
2682 // We have T t, T* is requested, so return &t.
2683 *reinterpret_cast<const void **>(data) = var.data();
2684 return true;
2685 } else if (Object *o = value.objectValue()) {
2686 // Look in the prototype chain.
2687 QV4::Scope scope(o->engine());
2688 QV4::ScopedObject proto(scope, o->getPrototypeOf());
2689 while (proto) {
2690 bool canCast = false;
2691 if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
2692 const QVariant &v = vo->d()->data();
2693 canCast = (metaType == v.metaType());
2694 }
2695 else if (proto->as<QV4::QObjectWrapper>()) {
2696 QV4::ScopedObject p(scope, proto.getPointer());
2697 if (QObject *qobject = qtObjectFromJS(p)) {
2698 if (const QMetaObject *metaObject = metaType.metaObject())
2699 canCast = metaObject->cast(qobject) != nullptr;
2700 else
2701 canCast = qobject->qt_metacast(pointedToTypeName);
2702 }
2703 }
2704 if (canCast) {
2705 const QMetaType varType = var.metaType();
2706 if (varType.flags() & QMetaType::IsPointer) {
2707 *reinterpret_cast<const void **>(data)
2708 = *reinterpret_cast<void *const *>(var.data());
2709 } else {
2710 *reinterpret_cast<const void **>(data) = var.data();
2711 }
2712 return true;
2713 }
2714 proto = proto->getPrototypeOf();
2715 }
2716 }
2718 metaType, data, var.metaType(), var.data())) {
2719 return true;
2720 }
2721 } else if (value.isNull() && isPointer) {
2722 *reinterpret_cast<void* *>(data) = nullptr;
2723 return true;
2724 } else if (metaType == QMetaType::fromType<QJSValue>()) {
2725 QJSValuePrivate::setValue(reinterpret_cast<QJSValue*>(data), value.asReturnedValue());
2726 return true;
2727 } else if (metaType == QMetaType::fromType<QJSPrimitiveValue>()) {
2728 *reinterpret_cast<QJSPrimitiveValue *>(data) = createPrimitive(&value);
2729 return true;
2730 } else if (!isPointer) {
2732 return true;
2733 }
2734
2735 if (const QV4::Sequence *sequence = value.as<Sequence>()) {
2737 if (result.metaType() == metaType) {
2738 metaType.destruct(data);
2739 metaType.construct(data, result.constData());
2740 return true;
2741 }
2742
2743 if (convertToIterable(metaType, data, sequence))
2744 return true;
2745 }
2746
2747 if (const QV4::ArrayObject *array = value.as<ArrayObject>()) {
2748 if (convertToIterable(metaType, data, array))
2749 return true;
2750 }
2751
2752 return false;
2753}
2754
2755static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result)
2756{
2757 if (!(targetType.flags() & QMetaType::IsPointer))
2758 return false;
2759 if (QObject *qobject = qtObjectFromJS(value)) {
2760 // If the target type has a metaObject, use that for casting.
2761 if (const QMetaObject *targetMetaObject = targetType.metaObject()) {
2762 if (QObject *instance = targetMetaObject->cast(qobject)) {
2763 *result = instance;
2764 return true;
2765 }
2766 return false;
2767 }
2768
2769 // We have to call the generated qt_metacast rather than metaObject->cast() here so that
2770 // it works for types without QMetaObject, such as QStandardItem.
2771 const QByteArray targetTypeName = targetType.name();
2772 const int start = targetTypeName.startsWith("const ") ? 6 : 0;
2773 const QByteArray className = targetTypeName.mid(start, targetTypeName.size() - start - 1);
2774 if (void *instance = qobject->qt_metacast(className)) {
2775 *result = instance;
2776 return true;
2777 }
2778 }
2779 return false;
2780}
2781
2783{
2784 if (!value.isObject())
2785 return nullptr;
2786
2787 QV4::Scope scope(value.as<QV4::Managed>()->engine());
2789
2790 if (v) {
2791 QVariant variant = v->d()->data();
2792 int type = variant.userType();
2793 if (type == QMetaType::QObjectStar)
2794 return *reinterpret_cast<QObject* const *>(variant.constData());
2795 }
2797 if (wrapper)
2798 return wrapper->object();
2799
2800 QV4::Scoped<QV4::QQmlTypeWrapper> typeWrapper(scope, value);
2801 if (typeWrapper)
2802 return typeWrapper->object();
2803
2804 return nullptr;
2805}
2806
2808{
2809 QV4EngineRegistrationData() : extensionCount(0) {}
2810
2813};
2815
2817{
2818 return &registrationData()->mutex;
2819}
2820
2822{
2823 return registrationData()->extensionCount++;
2824}
2825
2826#if QT_CONFIG(qml_network)
2827QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine)
2828{
2829 return engine->qmlEngine()->networkAccessManager();
2830}
2831#endif // qml_network
2832
T loadAcquire() const noexcept
void storeRelease(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
QByteArray chopped(qsizetype len) const
Definition qbytearray.h:167
bool startsWith(QByteArrayView bv) const
Definition qbytearray.h:170
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
\inmodule QtCore
Definition qchar.h:48
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore \reentrant
Definition qdatetime.h:27
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
bool isValid() const noexcept
Returns false if the timer has never been started or invalidated by a call to invalidate().
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QDateTime lastModified() const
Returns the date and time when the file was last modified.
Definition qfileinfo.h:156
\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:975
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
Container metaContainer() const
Definition qiterable.h:504
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:283
@ JavaScriptOwnership
Definition qjsengine.h:275
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:189
static QV4::ExecutionEngine * engine(const QJSValue *jsval)
Definition qjsvalue_p.h:313
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
Definition qjsvalue_p.h:298
static void setValue(QJSValue *jsval, const QV4::Value &v)
Definition qjsvalue_p.h:282
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
QJSValue property(const QString &name) const
Returns the value of this QJSValue's property with the given name.
QVariant toVariant() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qjsvalue.cpp:580
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
QString arg(Args &&...args) const
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
const_iterator constBegin() const
Definition qmap.h:599
const_iterator constEnd() const
Definition qmap.h:603
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:320
static constexpr QMetaType fromType()
Definition qmetatype.h:2612
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:2628
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:454
@ PointerToQObject
Definition qmetatype.h:385
@ IsEnumeration
Definition qmetatype.h:386
Type
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
Definition qmetatype.h:324
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2633
constexpr const char * name() const
Definition qmetatype.h:2650
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:775
\inmodule QtCore
Definition qmutex.h:317
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:323
void relock() noexcept
Relocks an unlocked mutex locker.
Definition qmutex.h:324
\inmodule QtCore
Definition qmutex.h:285
The QNetworkAccessManager class allows the application to send network requests and receive replies.
\inmodule QtCore
Definition qobject.h:90
static void registerExtension(QV4::ExecutionEngine *engine)
void init(QV4::ExecutionEngine *)
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 QFile.
Definition qqmlfile.cpp:643
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
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:638
QMetaSequence listMetaSequence() const
Definition qqmltype.cpp:653
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.
const_iterator constBegin() const
QMetaType valueMetaType() const
void addValue(const QVariant &value, Position position=Unspecified)
Adds value to the container, at position, if possible.
const_iterator constEnd() const
Definition qset.h:18
bool remove(const T &value)
Definition qset.h:63
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
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:7822
\inmodule QtCore
static void yieldCurrentThread()
Definition qthread.cpp:976
\inmodule QtCore \reentrant
Definition qdatetime.h:189
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3431
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2494
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2722
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
static QV4::CompiledData::CompilationUnit compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList< QQmlJS::DiagnosticMessage > *diagnostics)
static QQmlRefPointer< ExecutableCompilationUnit > create()
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
Definition qv4mm_p.h:121
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:199
PersistentValueStorage * m_persistentValues
Definition qv4mm_p.h:297
ManagedType::Data * allocWithStringData(std::size_t unmanagedSize, Arg1 &&arg1)
Definition qv4mm_p.h:173
ManagedType::Data * allocIC()
Definition qv4mm_p.h:229
ObjectType::Data * allocObject(Heap::InternalClass *ic, Args &&... args)
Definition qv4mm_p.h:183
\inmodule QtCore
Definition qvariant.h:64
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:511
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
QMap< QString, QVariant > toMap() const
Returns the variant as a QVariantMap if the variant has type() \l QMetaType::QVariantMap.
int userType() const
Definition qvariant.h:336
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:531
Private d
Definition qvariant.h:665
QMetaType metaType() const
const void * constData() const
Definition qvariant.h:446
EGLContext ctx
QString str
[2]
QMap< QString, QString > map
[6]
QString text
QDate date
[1]
double pi
[0]
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Q_QML_PRIVATE_EXPORT void registerStringLocaleCompare(QV4::ExecutionEngine *engine)
Q_QML_PRIVATE_EXPORT QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale)
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
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:77
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 DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
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:162
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]
GLfloat GLfloat f
GLenum src
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
GLuint res
const GLubyte * c
GLuint GLfloat * val
GLenum array
GLenum GLsizei len
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLuint GLenum option
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
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 DebuggerProgram debugger
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
unsigned long ulong
Definition qtypes.h:30
quint64 qulonglong
Definition qtypes.h:59
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
unsigned short ushort
Definition qtypes.h:28
qint64 qlonglong
Definition qtypes.h:58
void qt_add_domexceptions(ExecutionEngine *e)
static char * v4StackTrace(const ExecutionContext *context)
static QObject * qtObjectFromJS(const QV4::Value &value)
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, bool createJSValueForObjectsAndSymbols, V4ObjectSet *visitedObjects)
static QtMetaContainerPrivate::QMetaSequenceInterface emptySequenceInterface()
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
static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects=nullptr)
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
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
Heap::String * newString(const QString &s=QString())
void injectCompiledModule(const QQmlRefPointer< ExecutableCompilationUnit > &moduleUnit)
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
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)
QIntrusiveList< ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit > compilationUnits
String * id_caller() const
Heap::Object * newMapIteratorObject(Object *o)
FunctionObject * typeErrorCtor() 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 * 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
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 JSCallData &data) 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:339
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 ReturnedValue fromJsonArray(ExecutionEngine *engine, const QJsonArray &array)
static QJsonObject toJsonObject(const QV4::Object *o)
static QJsonArray toJsonArray(const QV4::ArrayObject *a)
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 VTable * vtable() const
void defineReadonlyProperty(const QString &name, const Value &value)
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
uchar data[MaxInternalSize]
Definition qvariant.h:111
void wrapper()
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent