1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#include <qv4engine_p.h>
40
41#include <private/qv4compileddata_p.h>
42#include <private/qv4codegen_p.h>
43#include <private/qqmljsdiagnosticmessage_p.h>
44
45#include <QtCore/QTextStream>
46#include <QDateTime>
47#include <QDir>
48#include <QFileInfo>
49#include <QLoggingCategory>
50#if QT_CONFIG(regularexpression)
51#include <QRegularExpression>
52#endif
53
54#include <qv4qmlcontext_p.h>
55#include <qv4value_p.h>
56#include <qv4object_p.h>
57#include <qv4objectproto_p.h>
58#include <qv4objectiterator_p.h>
59#include <qv4setiterator_p.h>
60#include <qv4mapiterator_p.h>
61#include <qv4arrayiterator_p.h>
62#include <qv4arrayobject_p.h>
63#include <qv4booleanobject_p.h>
64#include <qv4globalobject_p.h>
65#include <qv4errorobject_p.h>
66#include <qv4functionobject_p.h>
67#include "qv4function_p.h"
68#include <qv4mathobject_p.h>
69#include <qv4numberobject_p.h>
70#include <qv4regexpobject_p.h>
71#include <qv4regexp_p.h>
72#include "qv4symbol_p.h"
73#include "qv4setobject_p.h"
74#include "qv4mapobject_p.h"
75#include <qv4variantobject_p.h>
76#include <qv4runtime_p.h>
77#include <private/qv4mm_p.h>
78#include <qv4argumentsobject_p.h>
79#include <qv4dateobject_p.h>
80#include <qv4jsonobject_p.h>
81#include <qv4stringobject_p.h>
82#include <qv4identifiertable_p.h>
83#include "qv4debugging_p.h"
84#include "qv4profiling_p.h"
85#include "qv4executableallocator_p.h"
86#include "qv4iterator_p.h"
87#include "qv4stringiterator_p.h"
88#include "qv4generatorobject_p.h"
89#include "qv4reflect_p.h"
90#include "qv4proxy_p.h"
91#include "qv4stackframe_p.h"
92#include "qv4atomics_p.h"
93
94#if QT_CONFIG(qml_sequence_object)
95#include "qv4sequenceobject_p.h"
96#endif
97
98#include "qv4qobjectwrapper_p.h"
99#include "qv4memberdata_p.h"
100#include "qv4arraybuffer_p.h"
101#include "qv4dataview_p.h"
102#include "qv4promiseobject_p.h"
103#include "qv4typedarray_p.h"
104#include <private/qjsvalue_p.h>
105#include <private/qqmltypewrapper_p.h>
106#include <private/qqmlvaluetypewrapper_p.h>
107#include <private/qqmlvaluetype_p.h>
108#include <private/qqmllistwrapper_p.h>
109#include <private/qqmllist_p.h>
110#include <private/qqmltypeloader_p.h>
111#include <private/qqmlbuiltinfunctions_p.h>
112#if QT_CONFIG(qml_locale)
113#include <private/qqmllocale_p.h>
114#endif
115#if QT_CONFIG(qml_xml_http_request)
116#include <private/qv4domerrors_p.h>
117#include <private/qqmlxmlhttprequest_p.h>
118#endif
119#include <private/qv4sqlerrors_p.h>
120#include <qqmlfile.h>
121
122#if USE(PTHREADS)
123# include <pthread.h>
124#if !defined(Q_OS_INTEGRITY)
125# include <sys/resource.h>
126#endif
127#if HAVE(PTHREAD_NP_H)
128# include <pthread_np.h>
129#endif
130#endif
131
132#ifdef V4_USE_VALGRIND
133#include <valgrind/memcheck.h>
134#endif
135
136Q_DECLARE_METATYPE(QList<int>)
137
138QT_BEGIN_NAMESPACE
139
140using namespace QV4;
141
142static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
143
144ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
145{
146 return b->engine()->throwTypeError();
147}
148
149qint32 ExecutionEngine::maxCallDepth = -1;
150
151template <typename ReturnType>
152ReturnType convertJSValueToVariantType(const QJSValue &value)
153{
154 return value.toVariant().value<ReturnType>();
155}
156
157static void saveJSValue(QDataStream &stream, const void *data)
158{
159 const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
160 quint32 isNullOrUndefined = 0;
161 if (jsv->isNull())
162 isNullOrUndefined |= 0x1;
163 if (jsv->isUndefined())
164 isNullOrUndefined |= 0x2;
165 stream << isNullOrUndefined;
166 if (!isNullOrUndefined)
167 reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
168}
169
170static void restoreJSValue(QDataStream &stream, void *data)
171{
172 QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
173
174 quint32 isNullOrUndefined;
175 stream >> isNullOrUndefined;
176
177 if (isNullOrUndefined & 0x1) {
178 *jsv = QJSValue(QJSValue::NullValue);
179 } else if (isNullOrUndefined & 0x2) {
180 *jsv = QJSValue();
181 } else {
182 QVariant v;
183 v.load(stream);
184 QJSValuePrivate::setVariant(jsv, v);
185 }
186}
187
188ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
189 : executableAllocator(new QV4::ExecutableAllocator)
190 , regExpAllocator(new QV4::ExecutableAllocator)
191 , bumperPointerAllocator(new WTF::BumpPointerAllocator)
192 , jsStack(new WTF::PageAllocation)
193 , gcStack(new WTF::PageAllocation)
194 , globalCode(nullptr)
195 , publicEngine(jsEngine)
196 , m_engineId(engineSerial.fetchAndAddOrdered(1))
197 , regExpCache(nullptr)
198 , m_multiplyWrappedQObjects(nullptr)
199#if QT_CONFIG(qml_jit)
200 , m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
201#endif
202#if QT_CONFIG(qml_xml_http_request)
203 , m_xmlHttpRequestData(nullptr)
204#endif
205 , m_qmlEngine(nullptr)
206{
207 bool ok = false;
208 const int envMaxJSStackSize = qEnvironmentVariableIntValue("QV4_JS_MAX_STACK_SIZE", &ok);
209 if (ok && envMaxJSStackSize > 0)
210 m_maxJSStackSize = envMaxJSStackSize;
211
212 const int envMaxGCStackSize = qEnvironmentVariableIntValue("QV4_GC_MAX_STACK_SIZE", &ok);
213 if (ok && envMaxGCStackSize > 0)
214 m_maxGCStackSize = envMaxGCStackSize;
215
216 memoryManager = new QV4::MemoryManager(this);
217
218 if (maxCallDepth == -1) {
219 ok = false;
220 maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
221 if (!ok || maxCallDepth <= 0) {
222#if defined(QT_NO_DEBUG) && !defined(__SANITIZE_ADDRESS__) && !QT_HAS_FEATURE(address_sanitizer)
223 maxCallDepth = 1234;
224#else
225 // no (tail call) optimization is done, so there'll be a lot mare stack frames active
226 maxCallDepth = 200;
227#endif
228 }
229 }
230 Q_ASSERT(maxCallDepth > 0);
231
232 // reserve space for the JS stack
233 // we allow it to grow to a bit more than m_maxJSStackSize, as we can overshoot due to ScopedValues
234 // allocated outside of JIT'ed methods.
235 *jsStack = WTF::PageAllocation::allocate(m_maxJSStackSize + 256*1024, WTF::OSAllocator::JSVMStackPages,
236 /* writable */ true, /* executable */ false,
237 /* includesGuardPages */ true);
238 jsStackBase = (Value *)jsStack->base();
239#ifdef V4_USE_VALGRIND
240 VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, m_maxJSStackSize + 256*1024);
241#endif
242
243 jsStackTop = jsStackBase;
244
245 *gcStack = WTF::PageAllocation::allocate(m_maxGCStackSize, WTF::OSAllocator::JSVMStackPages,
246 /* writable */ true, /* executable */ false,
247 /* includesGuardPages */ true);
248
249 {
250 ok = false;
251 jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
252 if (!ok)
253 jitCallCountThreshold = 3;
254 if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
255 jitCallCountThreshold = std::numeric_limits<int>::max();
256 }
257
258 exceptionValue = jsAlloca(1);
259 *exceptionValue = Encode::undefined();
260 globalObject = static_cast<Object *>(jsAlloca(1));
261 jsObjects = jsAlloca(NJSObjects);
262 typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
263 typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
264 jsStrings = jsAlloca(NJSStrings);
265 jsSymbols = jsAlloca(NJSSymbols);
266
267 // set up stack limits
268 jsStackLimit = jsStackBase + m_maxJSStackSize/sizeof(Value);
269
270 identifierTable = new IdentifierTable(this);
271
272 memset(classes, 0, sizeof(classes));
273 classes[Class_Empty] = memoryManager->allocIC<InternalClass>();
274 classes[Class_Empty]->init(this);
275
276 classes[Class_MemberData] = classes[Class_Empty]->changeVTable(QV4::MemberData::staticVTable());
277 classes[Class_SimpleArrayData] = classes[Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
278 classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
279 classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
280 classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
281 classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable());
282
283 Scope scope(this);
284 Scoped<InternalClass> ic(scope);
285 ic = classes[Class_Empty]->changeVTable(QV4::Object::staticVTable());
286 jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic->d());
287 classes[Class_Object] = ic->changePrototype(objectPrototype()->d());
288 classes[Class_QmlContextWrapper] = classes[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
289
290 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
291 jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic->d(), /*init =*/ false);
292 classes[Class_String] = classes[Class_Empty]->changeVTable(QV4::String::staticVTable())->changePrototype(stringPrototype()->d());
293 Q_ASSERT(stringPrototype()->d() && classes[Class_String]->prototype);
294
295 jsObjects[SymbolProto] = memoryManager->allocate<SymbolPrototype>();
296 classes[Class_Symbol] = classes[EngineBase::Class_Empty]->changeVTable(QV4::Symbol::staticVTable())->changePrototype(symbolPrototype()->d());
297
298 jsStrings[String_Empty] = newIdentifier(QString());
299 jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
300 jsStrings[String_null] = newIdentifier(QStringLiteral("null"));
301 jsStrings[String_true] = newIdentifier(QStringLiteral("true"));
302 jsStrings[String_false] = newIdentifier(QStringLiteral("false"));
303 jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
304 jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
305 jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
306 jsStrings[String_default] = newIdentifier(QStringLiteral("default"));
307 jsStrings[String_symbol] = newIdentifier(QStringLiteral("symbol"));
308 jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
309 jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
310 jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
311 jsStrings[String_prototype] = newIdentifier(QStringLiteral("prototype"));
312 jsStrings[String_constructor] = newIdentifier(QStringLiteral("constructor"));
313 jsStrings[String_arguments] = newIdentifier(QStringLiteral("arguments"));
314 jsStrings[String_caller] = newIdentifier(QStringLiteral("caller"));
315 jsStrings[String_callee] = newIdentifier(QStringLiteral("callee"));
316 jsStrings[String_this] = newIdentifier(QStringLiteral("this"));
317 jsStrings[String___proto__] = newIdentifier(QStringLiteral("__proto__"));
318 jsStrings[String_enumerable] = newIdentifier(QStringLiteral("enumerable"));
319 jsStrings[String_configurable] = newIdentifier(QStringLiteral("configurable"));
320 jsStrings[String_writable] = newIdentifier(QStringLiteral("writable"));
321 jsStrings[String_value] = newIdentifier(QStringLiteral("value"));
322 jsStrings[String_get] = newIdentifier(QStringLiteral("get"));
323 jsStrings[String_set] = newIdentifier(QStringLiteral("set"));
324 jsStrings[String_eval] = newIdentifier(QStringLiteral("eval"));
325 jsStrings[String_uintMax] = newIdentifier(QStringLiteral("4294967295"));
326 jsStrings[String_name] = newIdentifier(QStringLiteral("name"));
327 jsStrings[String_index] = newIdentifier(QStringLiteral("index"));
328 jsStrings[String_input] = newIdentifier(QStringLiteral("input"));
329 jsStrings[String_toString] = newIdentifier(QStringLiteral("toString"));
330 jsStrings[String_toLocaleString] = newIdentifier(QStringLiteral("toLocaleString"));
331 jsStrings[String_destroy] = newIdentifier(QStringLiteral("destroy"));
332 jsStrings[String_valueOf] = newIdentifier(QStringLiteral("valueOf"));
333 jsStrings[String_byteLength] = newIdentifier(QStringLiteral("byteLength"));
334 jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
335 jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
336 jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
337 jsStrings[String_next] = newIdentifier(QStringLiteral("next"));
338 jsStrings[String_done] = newIdentifier(QStringLiteral("done"));
339 jsStrings[String_return] = newIdentifier(QStringLiteral("return"));
340 jsStrings[String_throw] = newIdentifier(QStringLiteral("throw"));
341 jsStrings[String_global] = newIdentifier(QStringLiteral("global"));
342 jsStrings[String_ignoreCase] = newIdentifier(QStringLiteral("ignoreCase"));
343 jsStrings[String_multiline] = newIdentifier(QStringLiteral("multiline"));
344 jsStrings[String_unicode] = newIdentifier(QStringLiteral("unicode"));
345 jsStrings[String_sticky] = newIdentifier(QStringLiteral("sticky"));
346 jsStrings[String_source] = newIdentifier(QStringLiteral("source"));
347 jsStrings[String_flags] = newIdentifier(QStringLiteral("flags"));
348
349 jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
350 jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
351 jsSymbols[Symbol_iterator] = Symbol::create(this, QStringLiteral("@Symbol.iterator"));
352 jsSymbols[Symbol_match] = Symbol::create(this, QStringLiteral("@Symbol.match"));
353 jsSymbols[Symbol_replace] = Symbol::create(this, QStringLiteral("@Symbol.replace"));
354 jsSymbols[Symbol_search] = Symbol::create(this, QStringLiteral("@Symbol.search"));
355 jsSymbols[Symbol_species] = Symbol::create(this, QStringLiteral("@Symbol.species"));
356 jsSymbols[Symbol_split] = Symbol::create(this, QStringLiteral("@Symbol.split"));
357 jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
358 jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
359 jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
360 jsSymbols[Symbol_revokableProxy] = Symbol::create(this, QStringLiteral("@Proxy.revokableProxy"));
361
362 ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
363 Q_ASSERT(ic->d()->prototype);
364 ic = ic->addMember(id_length()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
365 Q_ASSERT(ic->d()->prototype);
366 jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(ic->d());
367 classes[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d());
368 jsObjects[PropertyListProto] = memoryManager->allocate<PropertyListPrototype>();
369
370 Scoped<InternalClass> argsClass(scope);
371 argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype());
372 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
373 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
374 classes[Class_ArgumentsObject] = argsClass->addMember(id_callee()->propertyKey(), Attr_Data|Attr_NotEnumerable);
375 argsClass = newInternalClass(StrictArgumentsObject::staticVTable(), objectPrototype());
376 argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
377 argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
378 classes[Class_StrictArgumentsObject] = argsClass->addMember(id_callee()->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
379
380 *static_cast<Value *>(globalObject) = newObject();
381 Q_ASSERT(globalObject->d()->vtable());
382 initRootContext();
383
384 ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
385 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly);
386 classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
387 Q_ASSERT(classes[Class_StringObject]->verifyIndex(id_length()->propertyKey(), Heap::StringObject::LengthPropertyIndex));
388
389 classes[Class_SymbolObject] = newInternalClass(QV4::SymbolObject::staticVTable(), symbolPrototype());
390
391 jsObjects[NumberProto] = memoryManager->allocate<NumberPrototype>();
392 jsObjects[BooleanProto] = memoryManager->allocate<BooleanPrototype>();
393 jsObjects[DateProto] = memoryManager->allocate<DatePrototype>();
394
395#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
396 InternalClassEntry *index = nullptr;
397#else
398 InternalClassEntry _index;
399 auto *index = &_index;
400#endif
401 ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
402 auto addProtoHasInstance = [&] {
403 // Add an invalid prototype slot, so that all function objects have the same layout
404 // This helps speed up instanceof operations and other things where we need to query
405 // prototype property (as we always know it's location)
406 ic = ic->addMember(id_prototype()->propertyKey(), Attr_Invalid, index);
407 Q_ASSERT(index->index == Heap::FunctionObject::Index_Prototype);
408 // add an invalid @hasInstance slot, so that we can quickly track whether the
409 // hasInstance method has been reimplemented. This is required for a fast
410 // instanceof implementation
411 ic = ic->addMember(symbol_hasInstance()->propertyKey(), Attr_Invalid, index);
412 Q_ASSERT(index->index == Heap::FunctionObject::Index_HasInstance);
413 };
414 addProtoHasInstance();
415 jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic->d());
416 ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
417 addProtoHasInstance();
418 classes[Class_FunctionObject] = ic->d();
419 ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, index);
420 Q_ASSERT(index->index == Heap::ArrowFunction::Index_Name);
421 ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, index);
422 Q_ASSERT(index->index == Heap::ArrowFunction::Index_Length);
423 classes[Class_ArrowFunction] = ic->changeVTable(ArrowFunction::staticVTable());
424 ic = ic->changeVTable(MemberFunction::staticVTable());
425 classes[Class_MemberFunction] = ic->d();
426 ic = ic->changeVTable(GeneratorFunction::staticVTable());
427 classes[Class_GeneratorFunction] = ic->d();
428 ic = ic->changeVTable(MemberGeneratorFunction::staticVTable());
429 classes[Class_MemberGeneratorFunction] = ic->d();
430
431 ic = ic->changeMember(id_prototype()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
432 ic = ic->changeVTable(ScriptFunction::staticVTable());
433 classes[Class_ScriptFunction] = ic->d();
434 ic = ic->changeVTable(ConstructorFunction::staticVTable());
435 classes[Class_ConstructorFunction] = ic->d();
436
437 classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor()->propertyKey(), Attr_NotEnumerable, index);
438 Q_ASSERT(index->index == Heap::FunctionObject::Index_ProtoConstructor);
439
440 jsObjects[GeneratorProto] = memoryManager->allocObject<GeneratorPrototype>(classes[Class_Object]);
441 classes[Class_GeneratorObject] = newInternalClass(QV4::GeneratorObject::staticVTable(), generatorPrototype());
442
443 ScopedString str(scope);
444 classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
445 ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
446 ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, index);
447 Q_ASSERT(index->index == RegExpObject::Index_LastIndex);
448 jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(classes[Class_Object]);
449 classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
450
451 ic = classes[Class_ArrayObject]->addMember(id_index()->propertyKey(), Attr_Data, index);
452 Q_ASSERT(index->index == RegExpObject::Index_ArrayIndex);
453 classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, index);
454 Q_ASSERT(index->index == RegExpObject::Index_ArrayInput);
455
456 ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
457 ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, index);
458 Q_ASSERT(index->index == ErrorObject::Index_Stack);
459 Q_ASSERT(index->setterIndex == ErrorObject::Index_StackSetter);
460 ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
461 Q_ASSERT(index->index == ErrorObject::Index_FileName);
462 ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
463 classes[Class_ErrorObject] = ic->d();
464 Q_ASSERT(index->index == ErrorObject::Index_LineNumber);
465 classes[Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
466 Q_ASSERT(index->index == ErrorObject::Index_Message);
467 ic = newInternalClass(Object::staticVTable(), objectPrototype());
468 ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
469 Q_ASSERT(index->index == ErrorPrototype::Index_Constructor);
470 ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
471 Q_ASSERT(index->index == ErrorPrototype::Index_Message);
472 classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
473 Q_ASSERT(index->index == ErrorPrototype::Index_Name);
474
475 classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
476 classes[Class_ProxyFunctionObject] = classes[Class_Empty]->changeVTable(ProxyFunctionObject::staticVTable());
477
478 jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(this, str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack, 0);
479
480 jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(classes[Class_ErrorProto]);
481 ic = classes[Class_ErrorProto]->changePrototype(errorPrototype()->d());
482 jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(ic->d());
483 jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(ic->d());
484 jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(ic->d());
485 jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(ic->d());
486 jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(ic->d());
487 jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(ic->d());
488
489 jsObjects[VariantProto] = memoryManager->allocate<VariantPrototype>();
490 Q_ASSERT(variantPrototype()->getPrototypeOf() == objectPrototype()->d());
491
492#if QT_CONFIG(qml_sequence_object)
493 ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this));
494 jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic->d()));
495#endif
496
497 ExecutionContext *global = rootContext();
498
499 jsObjects[Object_Ctor] = memoryManager->allocate<ObjectCtor>(global);
500 jsObjects[String_Ctor] = memoryManager->allocate<StringCtor>(global);
501 jsObjects[Symbol_Ctor] = memoryManager->allocate<SymbolCtor>(global);
502 jsObjects[Number_Ctor] = memoryManager->allocate<NumberCtor>(global);
503 jsObjects[Boolean_Ctor] = memoryManager->allocate<BooleanCtor>(global);
504 jsObjects[Array_Ctor] = memoryManager->allocate<ArrayCtor>(global);
505 jsObjects[Function_Ctor] = memoryManager->allocate<FunctionCtor>(global);
506 jsObjects[GeneratorFunction_Ctor] = memoryManager->allocate<GeneratorFunctionCtor>(global);
507 jsObjects[Date_Ctor] = memoryManager->allocate<DateCtor>(global);
508 jsObjects[RegExp_Ctor] = memoryManager->allocate<RegExpCtor>(global);
509 jsObjects[Error_Ctor] = memoryManager->allocate<ErrorCtor>(global);
510 jsObjects[EvalError_Ctor] = memoryManager->allocate<EvalErrorCtor>(global);
511 jsObjects[RangeError_Ctor] = memoryManager->allocate<RangeErrorCtor>(global);
512 jsObjects[ReferenceError_Ctor] = memoryManager->allocate<ReferenceErrorCtor>(global);
513 jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(global);
514 jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global);
515 jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global);
516 jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>();
517
518 ic = newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype());
519 jsObjects[ForInIteratorProto] = memoryManager->allocObject<ForInIteratorPrototype>(ic);
520 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
521 jsObjects[MapIteratorProto] = memoryManager->allocObject<MapIteratorPrototype>(ic);
522 ic = newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype());
523 jsObjects[SetIteratorProto] = memoryManager->allocObject<SetIteratorPrototype>(ic);
524 ic = newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype());
525 jsObjects[ArrayIteratorProto] = memoryManager->allocObject<ArrayIteratorPrototype>(ic);
526 ic = newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype());
527 jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(ic);
528
529 str = newString(QStringLiteral("get [Symbol.species]"));
530 jsObjects[GetSymbolSpecies] = FunctionObject::createBuiltinFunction(this, str, ArrayPrototype::method_get_species, 0);
531
532 static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
533 static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
534 static_cast<SymbolPrototype *>(symbolPrototype())->init(this, symbolCtor());
535 static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
536 static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
537 static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
538 static_cast<PropertyListPrototype *>(propertyListPrototype())->init(this);
539 static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
540 static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
541 static_cast<GeneratorPrototype *>(generatorPrototype())->init(this, generatorFunctionCtor());
542 static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
543 static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
544 static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
545 static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor());
546 static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor());
547 static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
548 static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
549 static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
550
551 static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
552 static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
553 static_cast<MapIteratorPrototype *>(mapIteratorPrototype())->init(this);
554 static_cast<SetIteratorPrototype *>(setIteratorPrototype())->init(this);
555 static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this);
556 static_cast<StringIteratorPrototype *>(stringIteratorPrototype())->init(this);
557
558 static_cast<VariantPrototype *>(variantPrototype())->init();
559
560#if QT_CONFIG(qml_sequence_object)
561 sequencePrototype()->cast<SequencePrototype>()->init();
562#endif
563
564 jsObjects[WeakMap_Ctor] = memoryManager->allocate<WeakMapCtor>(global);
565 jsObjects[WeakMapProto] = memoryManager->allocate<WeakMapPrototype>();
566 static_cast<WeakMapPrototype *>(weakMapPrototype())->init(this, weakMapCtor());
567
568 jsObjects[Map_Ctor] = memoryManager->allocate<MapCtor>(global);
569 jsObjects[MapProto] = memoryManager->allocate<MapPrototype>();
570 static_cast<MapPrototype *>(mapPrototype())->init(this, mapCtor());
571
572 jsObjects[WeakSet_Ctor] = memoryManager->allocate<WeakSetCtor>(global);
573 jsObjects[WeakSetProto] = memoryManager->allocate<WeakSetPrototype>();
574 static_cast<WeakSetPrototype *>(weakSetPrototype())->init(this, weakSetCtor());
575
576 jsObjects[Set_Ctor] = memoryManager->allocate<SetCtor>(global);
577 jsObjects[SetProto] = memoryManager->allocate<SetPrototype>();
578 static_cast<SetPrototype *>(setPrototype())->init(this, setCtor());
579
580 //
581 // promises
582 //
583
584 jsObjects[Promise_Ctor] = memoryManager->allocate<PromiseCtor>(global);
585 jsObjects[PromiseProto] = memoryManager->allocate<PromisePrototype>();
586 static_cast<PromisePrototype *>(promisePrototype())->init(this, promiseCtor());
587
588 // typed arrays
589
590 jsObjects[SharedArrayBuffer_Ctor] = memoryManager->allocate<SharedArrayBufferCtor>(global);
591 jsObjects[SharedArrayBufferProto] = memoryManager->allocate<SharedArrayBufferPrototype>();
592 static_cast<SharedArrayBufferPrototype *>(sharedArrayBufferPrototype())->init(this, sharedArrayBufferCtor());
593
594 jsObjects[ArrayBuffer_Ctor] = memoryManager->allocate<ArrayBufferCtor>(global);
595 jsObjects[ArrayBufferProto] = memoryManager->allocate<ArrayBufferPrototype>();
596 static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
597
598 jsObjects[DataView_Ctor] = memoryManager->allocate<DataViewCtor>(global);
599 jsObjects[DataViewProto] = memoryManager->allocate<DataViewPrototype>();
600 static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
601 jsObjects[ValueTypeProto] = (Heap::Base *) nullptr;
602 jsObjects[SignalHandlerProto] = (Heap::Base *) nullptr;
603
604 jsObjects[IntrinsicTypedArray_Ctor] = memoryManager->allocate<IntrinsicTypedArrayCtor>(global);
605 jsObjects[IntrinsicTypedArrayProto] = memoryManager->allocate<IntrinsicTypedArrayPrototype>();
606 static_cast<IntrinsicTypedArrayPrototype *>(intrinsicTypedArrayPrototype())
607 ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
608
609 for (int i = 0; i < NTypedArrayTypes; ++i) {
610 static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
611 static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
612 typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
613 }
614
615 //
616 // set up the global object
617 //
618 rootContext()->d()->activation.set(scope.engine, globalObject->d());
619 Q_ASSERT(globalObject->d()->vtable());
620
621 globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
622 globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
623 globalObject->defineDefaultProperty(QStringLiteral("Symbol"), *symbolCtor());
624 FunctionObject *numberObject = numberCtor();
625 globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
626 globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
627 globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
628 globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
629 globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor());
630 globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor());
631 globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor());
632 globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor());
633 globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor());
634 globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor());
635 globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor());
636 globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
637 globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
638 globalObject->defineDefaultProperty(QStringLiteral("Promise"), *promiseCtor());
639
640 globalObject->defineDefaultProperty(QStringLiteral("SharedArrayBuffer"), *sharedArrayBufferCtor());
641 globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
642 globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
643 globalObject->defineDefaultProperty(QStringLiteral("WeakSet"), *weakSetCtor());
644 globalObject->defineDefaultProperty(QStringLiteral("Set"), *setCtor());
645 globalObject->defineDefaultProperty(QStringLiteral("WeakMap"), *weakMapCtor());
646 globalObject->defineDefaultProperty(QStringLiteral("Map"), *mapCtor());
647
648 for (int i = 0; i < NTypedArrayTypes; ++i)
649 globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name()), typedArrayCtors[i]);
650 ScopedObject o(scope);
651 globalObject->defineDefaultProperty(QStringLiteral("Atomics"), (o = memoryManager->allocate<Atomics>()));
652 globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>()));
653 globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>()));
654 globalObject->defineDefaultProperty(QStringLiteral("Reflect"), (o = memoryManager->allocate<Reflect>()));
655 globalObject->defineDefaultProperty(QStringLiteral("Proxy"), (o = memoryManager->allocate<Proxy>(rootContext())));
656
657 globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Value::undefinedValue());
658 globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Value::fromDouble(std::numeric_limits<double>::quiet_NaN()));
659 globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Value::fromDouble(Q_INFINITY));
660
661
662 jsObjects[Eval_Function] = memoryManager->allocate<EvalFunction>(global);
663 globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
664
665 // ES6: 20.1.2.12 & 20.1.2.13:
666 // parseInt and parseFloat must be the same FunctionObject on the global &
667 // Number object.
668 {
669 QString piString(QStringLiteral("parseInt"));
670 QString pfString(QStringLiteral("parseFloat"));
671 Scope scope(this);
672 ScopedString pi(scope, newIdentifier(piString));
673 ScopedString pf(scope, newIdentifier(pfString));
674 ScopedFunctionObject parseIntFn(scope, FunctionObject::createBuiltinFunction(this, pi, GlobalFunctions::method_parseInt, 2));
675 ScopedFunctionObject parseFloatFn(scope, FunctionObject::createBuiltinFunction(this, pf, GlobalFunctions::method_parseFloat, 1));
676 globalObject->defineDefaultProperty(piString, parseIntFn);
677 globalObject->defineDefaultProperty(pfString, parseFloatFn);
678 numberObject->defineDefaultProperty(piString, parseIntFn);
679 numberObject->defineDefaultProperty(pfString, parseFloatFn);
680 }
681
682 globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
683 globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
684 globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
685 globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
686 globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
687 globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
688 globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
689 globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
690
691 ScopedFunctionObject t(scope, memoryManager->allocate<FunctionObject>(rootContext(), nullptr, ::throwTypeError));
692 t->defineReadonlyProperty(id_length(), Value::fromInt32(0));
693 t->setInternalClass(t->internalClass()->cryopreserved());
694 jsObjects[ThrowerObject] = t;
695
696 ScopedProperty pd(scope);
697 pd->value = thrower();
698 pd->set = thrower();
699 functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
700 functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
701
702 qMetaTypeId<QJSValue>();
703 qMetaTypeId<QList<int> >();
704
705 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
706 QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
707 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
708 QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
709 if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
710 QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
711 QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
712
713 QV4::QObjectWrapper::initializeBindings(this);
714
715 m_delayedCallQueue.init(this);
716}
717
718ExecutionEngine::~ExecutionEngine()
719{
720 modules.clear();
721 qDeleteAll(m_extensionData);
722 delete m_multiplyWrappedQObjects;
723 m_multiplyWrappedQObjects = nullptr;
724 delete identifierTable;
725 delete memoryManager;
726
727 while (!compilationUnits.isEmpty())
728 (*compilationUnits.begin())->unlink();
729
730 delete bumperPointerAllocator;
731 delete regExpCache;
732 delete regExpAllocator;
733 delete executableAllocator;
734 jsStack->deallocate();
735 delete jsStack;
736 gcStack->deallocate();
737 delete gcStack;
738
739#if QT_CONFIG(qml_xml_http_request)
740 qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
741 m_xmlHttpRequestData = nullptr;
742#endif
743}
744
745ExecutionContext *ExecutionEngine::currentContext() const
746{
747 return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
748}
749
750#if QT_CONFIG(qml_debug)
751void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
752{
753 Q_ASSERT(!m_debugger);
754 m_debugger.reset(debugger);
755}
756
757void ExecutionEngine::setProfiler(Profiling::Profiler *profiler)
758{
759 Q_ASSERT(!m_profiler);
760 m_profiler.reset(profiler);
761}
762#endif // QT_CONFIG(qml_debug)
763
764void ExecutionEngine::initRootContext()
765{
766 Scope scope(this);
767 Scoped<ExecutionContext> r(scope, memoryManager->allocManaged<ExecutionContext>(sizeof(ExecutionContext::Data)));
768 r->d_unchecked()->init(Heap::ExecutionContext::Type_GlobalContext);
769 r->d()->activation.set(this, globalObject->d());
770 jsObjects[RootContext] = r;
771 jsObjects[ScriptContext] = r;
772 jsObjects[IntegerNull] = Encode((int)0);
773}
774
775Heap::InternalClass *ExecutionEngine::newClass(Heap::InternalClass *other)
776{
777 Heap::InternalClass *ic = memoryManager->allocIC<InternalClass>();
778 ic->init(other);
779 return ic;
780}
781
782Heap::InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype)
783{
784 Scope scope(this);
785 Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable));
786 return ic->changePrototype(prototype ? prototype->d() : nullptr);
787}
788
789Heap::Object *ExecutionEngine::newObject()
790{
791 return memoryManager->allocate<Object>();
792}
793
794Heap::Object *ExecutionEngine::newObject(Heap::InternalClass *internalClass)
795{
796 return memoryManager->allocObject<Object>(internalClass);
797}
798
799Heap::String *ExecutionEngine::newString(const QString &s)
800{
801 return memoryManager->allocWithStringData<String>(s.length() * sizeof(QChar), s);
802}
803
804Heap::String *ExecutionEngine::newIdentifier(const QString &text)
805{
806 Scope scope(this);
807 ScopedString s(scope, memoryManager->allocWithStringData<String>(text.length() * sizeof(QChar), text));
808 s->toPropertyKey();
809 return s->d();
810}
811
812Heap::Object *ExecutionEngine::newStringObject(const String *string)
813{
814 return memoryManager->allocate<StringObject>(string);
815}
816
817Heap::Object *ExecutionEngine::newSymbolObject(const Symbol *symbol)
818{
819 return memoryManager->allocObject<SymbolObject>(classes[Class_SymbolObject], symbol);
820}
821
822Heap::Object *ExecutionEngine::newNumberObject(double value)
823{
824 return memoryManager->allocate<NumberObject>(value);
825}
826
827Heap::Object *ExecutionEngine::newBooleanObject(bool b)
828{
829 return memoryManager->allocate<BooleanObject>(b);
830}
831
832Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
833{
834 Scope scope(this);
835 ScopedArrayObject object(scope, memoryManager->allocate<ArrayObject>());
836
837 if (count) {
838 if (count < 0x1000)
839 object->arrayReserve(count);
840 object->setArrayLengthUnchecked(count);
841 }
842 return object->d();
843}
844
845Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length)
846{
847 Scope scope(this);
848 ScopedArrayObject a(scope, memoryManager->allocate<ArrayObject>());
849
850 if (length) {
851 size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
852 Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
853 d->init();
854 d->type = Heap::ArrayData::Simple;
855 d->offset = 0;
856 d->values.alloc = length;
857 d->values.size = length;
858 // this doesn't require a write barrier, things will be ok, when the new array data gets inserted into
859 // the parent object
860 memcpy(&d->values.values, values, length*sizeof(Value));
861 a->d()->arrayData.set(this, d);
862 a->setArrayLengthUnchecked(length);
863 }
864 return a->d();
865}
866
867Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
868{
869 return memoryManager->allocate<ArrayObject>(list);
870}
871
872Heap::ArrayObject *ExecutionEngine::newArrayObject(Heap::InternalClass *internalClass)
873{
874 return memoryManager->allocObject<ArrayObject>(internalClass);
875}
876
877Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
878{
879 return memoryManager->allocate<ArrayBuffer>(array);
880}
881
882Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length)
883{
884 return memoryManager->allocate<ArrayBuffer>(length);
885}
886
887
888Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
889{
890 return memoryManager->allocate<DateObject>(value);
891}
892
893Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
894{
895 Scope scope(this);
896 Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(dt));
897 return object->d();
898}
899
900Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t)
901{
902 Scope scope(this);
903 Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(t));
904 return object->d();
905}
906
907Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
908{
909 Scope scope(this);
910 Scoped<RegExp> re(scope, RegExp::create(this, pattern, static_cast<CompiledData::RegExp::Flags>(flags)));
911 return newRegExpObject(re);
912}
913
914Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re)
915{
916 return memoryManager->allocate<RegExpObject>(re);
917}
918
919Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
920{
921 return memoryManager->allocate<RegExpObject>(re);
922}
923
924#if QT_CONFIG(regularexpression)
925Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
926{
927 return memoryManager->allocate<RegExpObject>(re);
928}
929#endif
930
931Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
932{
933 return ErrorObject::create<ErrorObject>(this, value, errorCtor());
934}
935
936Heap::Object *ExecutionEngine::newErrorObject(const QString &message)
937{
938 return ErrorObject::create<ErrorObject>(this, message);
939}
940
941Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
942{
943 return ErrorObject::create<SyntaxErrorObject>(this, message);
944}
945
946Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
947{
948 return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
949}
950
951
952Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
953{
954 return ErrorObject::create<ReferenceErrorObject>(this, message);
955}
956
957Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column)
958{
959 return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
960}
961
962
963Heap::Object *ExecutionEngine::newTypeErrorObject(const QString &message)
964{
965 return ErrorObject::create<TypeErrorObject>(this, message);
966}
967
968Heap::Object *ExecutionEngine::newRangeErrorObject(const QString &message)
969{
970 return ErrorObject::create<RangeErrorObject>(this, message);
971}
972
973Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message)
974{
975 return ErrorObject::create<URIErrorObject>(this, message, uRIErrorCtor());
976}
977
978Heap::PromiseObject *ExecutionEngine::newPromiseObject()
979{
980 if (!m_reactionHandler) {
981 m_reactionHandler.reset(new Promise::ReactionHandler);
982 }
983
984 Scope scope(this);
985 Scoped<PromiseObject> object(scope, memoryManager->allocate<PromiseObject>(this));
986 return object->d();
987}
988
989Heap::Object *ExecutionEngine::newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability)
990{
991 if (!m_reactionHandler) {
992 m_reactionHandler.reset(new Promise::ReactionHandler);
993 }
994
995 Scope scope(this);
996 Scoped<CapabilitiesExecutorWrapper> executor(scope, memoryManager->allocate<CapabilitiesExecutorWrapper>());
997 executor->d()->capabilities.set(this, capability->d());
998 executor->insertMember(id_length(), Primitive::fromInt32(2), Attr_NotWritable|Attr_NotEnumerable);
999
1000 ScopedObject object(scope, thisObject->callAsConstructor(executor, 1));
1001 return object->d();
1002}
1003
1004Promise::ReactionHandler *ExecutionEngine::getPromiseReactionHandler()
1005{
1006 Q_ASSERT(m_reactionHandler);
1007 return m_reactionHandler.data();
1008}
1009
1010Heap::Object *ExecutionEngine::newURIErrorObject(const QString &message)
1011{
1012 return ErrorObject::create<URIErrorObject>(this, message);
1013}
1014
1015Heap::Object *ExecutionEngine::newEvalErrorObject(const QString &message)
1016{
1017 return ErrorObject::create<EvalErrorObject>(this, message);
1018}
1019
1020Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
1021{
1022 return memoryManager->allocate<VariantObject>(v);
1023}
1024
1025Heap::Object *ExecutionEngine::newForInIteratorObject(Object *o)
1026{
1027 Scope scope(this);
1028 ScopedObject obj(scope, memoryManager->allocate<ForInIteratorObject>(o));
1029 return obj->d();
1030}
1031
1032Heap::Object *ExecutionEngine::newMapIteratorObject(Object *o)
1033{
1034 return memoryManager->allocate<MapIteratorObject>(o->d(), this);
1035}
1036
1037Heap::Object *ExecutionEngine::newSetIteratorObject(Object *o)
1038{
1039 return memoryManager->allocate<SetIteratorObject>(o->d(), this);
1040}
1041
1042Heap::Object *ExecutionEngine::newArrayIteratorObject(Object *o)
1043{
1044 return memoryManager->allocate<ArrayIteratorObject>(o->d(), this);
1045}
1046
1047Heap::QmlContext *ExecutionEngine::qmlContext() const
1048{
1049 if (!currentStackFrame)
1050 return nullptr;
1051 Heap::ExecutionContext *ctx = currentContext()->d();
1052
1053 if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer)
1054 return nullptr;
1055
1056 while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext)
1057 ctx = ctx->outer;
1058
1059 Q_ASSERT(ctx);
1060 if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
1061 return nullptr;
1062
1063 return static_cast<Heap::QmlContext *>(ctx);
1064}
1065
1066QObject *ExecutionEngine::qmlScopeObject() const
1067{
1068 Heap::QmlContext *ctx = qmlContext();
1069 if (!ctx)
1070 return nullptr;
1071
1072 return ctx->qml()->scopeObject;
1073}
1074
1075QQmlContextData *ExecutionEngine::callingQmlContext() const
1076{
1077 Heap::QmlContext *ctx = qmlContext();
1078 if (!ctx)
1079 return nullptr;
1080
1081 return ctx->qml()->context->contextData();
1082}
1083
1084StackTrace ExecutionEngine::stackTrace(int frameLimit) const
1085{
1086 Scope scope(const_cast<ExecutionEngine *>(this));
1087 ScopedString name(scope);
1088 StackTrace stack;
1089
1090 CppStackFrame *f = currentStackFrame;
1091 while (f && frameLimit) {
1092 QV4::StackFrame frame;
1093 frame.source = f->source();
1094 frame.function = f->function();
1095 frame.line = qAbs(f->lineNumber());
1096 frame.column = -1;
1097 stack.append(frame);
1098 if (f->isTailCalling) {
1099 QV4::StackFrame frame;
1100 frame.function = QStringLiteral("[elided tail calls]");
1101 stack.append(frame);
1102 }
1103 --frameLimit;
1104 f = f->parent;
1105 }
1106
1107 return stack;
1108}
1109
1110/* Helper and "C" linkage exported function to format a GDBMI stacktrace for
1111 * invocation by a debugger.
1112 * Sample GDB invocation: print qt_v4StackTrace((void*)0x7fffffffb290)
1113 * Sample CDB invocation: .call Qt5Qmld!qt_v4StackTrace(0x7fffffffb290) ; gh
1114 * Note: The helper is there to suppress MSVC warning 4190 about anything
1115 * with UDT return types in a "C" linkage function. */
1116
1117static inline char *v4StackTrace(const ExecutionContext *context)
1118{
1119 QString result;
1120 QTextStream str(&result);
1121 str << "stack=[";
1122 if (context && context->engine()) {
1123 const QVector<StackFrame> stackTrace = context->engine()->stackTrace(20);
1124 for (int i = 0; i < stackTrace.size(); ++i) {
1125 if (i)
1126 str << ',';
1127 const QUrl url(stackTrace.at(i).source);
1128 const QString fileName = url.isLocalFile() ? url.toLocalFile() : url.toString();
1129 str << "frame={level=\"" << i << "\",func=\"" << stackTrace.at(i).function
1130 << "\",file=\"" << fileName << "\",fullname=\"" << fileName
1131 << "\",line=\"" << stackTrace.at(i).line << "\",language=\"js\"}";
1132 }
1133 }
1134 str << ']';
1135 return qstrdup(result.toLocal8Bit().constData());
1136}
1137
1138extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
1139{
1140 return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
1141}
1142
1143extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
1144{
1145 auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
1146 return v4StackTrace(engine->currentContext());
1147}
1148
1149QUrl ExecutionEngine::resolvedUrl(const QString &file)
1150{
1151 QUrl src(file);
1152 if (!src.isRelative())
1153 return src;
1154
1155 QUrl base;
1156 CppStackFrame *f = currentStackFrame;
1157 while (f) {
1158 if (f->v4Function) {
1159 base = f->v4Function->finalUrl();
1160 break;
1161 }
1162 f = f->parent;
1163 }
1164
1165 if (base.isEmpty() && globalCode)
1166 base = globalCode->finalUrl();
1167
1168 if (base.isEmpty())
1169 return src;
1170
1171 return base.resolved(src);
1172}
1173
1174void ExecutionEngine::markObjects(MarkStack *markStack)
1175{
1176 for (int i = 0; i < NClasses; ++i)
1177 if (classes[i])
1178 classes[i]->mark(markStack);
1179 markStack->drain();
1180
1181 identifierTable->markObjects(markStack);
1182
1183 for (auto compilationUnit: compilationUnits) {
1184 compilationUnit->markObjects(markStack);
1185 markStack->drain();
1186 }
1187}
1188
1189ReturnedValue ExecutionEngine::throwError(const Value &value)
1190{
1191 // we can get in here with an exception already set, as the runtime
1192 // doesn't check after every operation that can throw.
1193 // in this case preserve the first exception to give correct error
1194 // information
1195 if (hasException)
1196 return Encode::undefined();
1197
1198 hasException = true;
1199 *exceptionValue = value;
1200 QV4::Scope scope(this);
1201 QV4::Scoped<ErrorObject> error(scope, value);
1202 if (!!error)
1203 exceptionStackTrace = *error->d()->stackTrace;
1204 else
1205 exceptionStackTrace = stackTrace();
1206
1207 if (QV4::Debugging::Debugger *debug = debugger())
1208 debug->aboutToThrow();
1209
1210 return Encode::undefined();
1211}
1212
1213ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
1214{
1215 Q_ASSERT(hasException);
1216 if (trace)
1217 *trace = exceptionStackTrace;
1218 exceptionStackTrace.clear();
1219 hasException = false;
1220 ReturnedValue res = exceptionValue->asReturnedValue();
1221 *exceptionValue = Value::emptyValue();
1222 return res;
1223}
1224
1225ReturnedValue ExecutionEngine::throwError(const QString &message)
1226{
1227 Scope scope(this);
1228 ScopedValue v(scope, newString(message));
1229 v = newErrorObject(v);
1230 return throwError(v);
1231}
1232
1233ReturnedValue ExecutionEngine::throwSyntaxError(const QString &message, const QString &fileName, int line, int column)
1234{
1235 Scope scope(this);
1236 ScopedObject error(scope, newSyntaxErrorObject(message, fileName, line, column));
1237 return throwError(error);
1238}
1239
1240ReturnedValue ExecutionEngine::throwSyntaxError(const QString &message)
1241{
1242 Scope scope(this);
1243 ScopedObject error(scope, newSyntaxErrorObject(message));
1244 return throwError(error);
1245}
1246
1247
1248ReturnedValue ExecutionEngine::throwTypeError()
1249{
1250 Scope scope(this);
1251 ScopedObject error(scope, newTypeErrorObject(QStringLiteral("Type error")));
1252 return throwError(error);
1253}
1254
1255ReturnedValue ExecutionEngine::throwTypeError(const QString &message)
1256{
1257 Scope scope(this);
1258 ScopedObject error(scope, newTypeErrorObject(message));
1259 return throwError(error);
1260}
1261
1262ReturnedValue ExecutionEngine::throwReferenceError(const QString &name)
1263{
1264 Scope scope(this);
1265 QString msg = name + QLatin1String(" is not defined");
1266 ScopedObject error(scope, newReferenceErrorObject(msg));
1267 return throwError(error);
1268}
1269
1270ReturnedValue ExecutionEngine::throwReferenceError(const Value &value)
1271{
1272 Scope scope(this);
1273 ScopedString s(scope, value.toString(this));
1274 QString msg = s->toQString() + QLatin1String(" is not defined");
1275 ScopedObject error(scope, newReferenceErrorObject(msg));
1276 return throwError(error);
1277}
1278
1279ReturnedValue ExecutionEngine::throwReferenceError(const QString &message, const QString &fileName, int line, int column)
1280{
1281 Scope scope(this);
1282 QString msg = message;
1283 ScopedObject error(scope, newReferenceErrorObject(msg, fileName, line, column));
1284 return throwError(error);
1285}
1286
1287ReturnedValue ExecutionEngine::throwRangeError(const QString &message)
1288{
1289 Scope scope(this);
1290 ScopedObject error(scope, newRangeErrorObject(message));
1291 return throwError(error);
1292}
1293
1294ReturnedValue ExecutionEngine::throwRangeError(const Value &value)
1295{
1296 Scope scope(this);
1297 ScopedString s(scope, value.toString(this));
1298 QString msg = s->toQString() + QLatin1String(" out of range");
1299 ScopedObject error(scope, newRangeErrorObject(msg));
1300 return throwError(error);
1301}
1302
1303ReturnedValue ExecutionEngine::throwURIError(const Value &msg)
1304{
1305 Scope scope(this);
1306 ScopedObject error(scope, newURIErrorObject(msg));
1307 return throwError(error);
1308}
1309
1310ReturnedValue ExecutionEngine::throwUnimplemented(const QString &message)
1311{
1312 Scope scope(this);
1313 ScopedValue v(scope, newString(QLatin1String("Unimplemented ") + message));
1314 v = newErrorObject(v);
1315 return throwError(v);
1316}
1317
1318
1319QQmlError ExecutionEngine::catchExceptionAsQmlError()
1320{
1321 QV4::StackTrace trace;
1322 QV4::Scope scope(this);
1323 QV4::ScopedValue exception(scope, catchException(&trace));
1324 QQmlError error;
1325 if (!trace.isEmpty()) {
1326 QV4::StackFrame frame = trace.constFirst();
1327 error.setUrl(QUrl(frame.source));
1328 error.setLine(frame.line);
1329 error.setColumn(frame.column);
1330 }
1331 QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
1332 error.setDescription(exception->toQStringNoThrow());
1333 return error;
1334}
1335
1336// Variant conversion code
1337
1338typedef QSet<QV4::Heap::Object *> V4ObjectSet;
1339static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
1340static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
1341static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr);
1342static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
1343 const QByteArray &targetType,
1344 void **result);
1345static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst);
1346static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst);
1347static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap);
1348static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value)
1349{
1350 return v4->metaTypeToJS(value.userType(), value.constData());
1351}
1352
1353
1354QVariant ExecutionEngine::toVariant(const Value &value, int typeHint, bool createJSValueForObjects)
1355{
1356 return ::toVariant(this, value, typeHint, createJSValueForObjects, nullptr);
1357}
1358
1359
1360static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects)
1361{
1362 Q_ASSERT (!value.isEmpty());
1363 QV4::Scope scope(e);
1364
1365 if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
1366 return v->d()->data();
1367
1368 if (typeHint == QVariant::Bool)
1369 return QVariant(value.toBoolean());
1370
1371 if (typeHint == QMetaType::QJsonValue)
1372 return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
1373
1374 if (typeHint == qMetaTypeId<QJSValue>())
1375 return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
1376
1377 if (value.as<QV4::Object>()) {
1378 QV4::ScopedObject object(scope, value);
1379 if (typeHint == QMetaType::QJsonObject
1380 && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
1381 return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
1382 } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
1383 return QVariant::fromValue<QObject *>(wrapper->object());
1384 } else if (object->as<QV4::QQmlContextWrapper>()) {
1385 return QVariant();
1386 } else if (QV4::QQmlTypeWrapper *w = object->as<QV4::QQmlTypeWrapper>()) {
1387 return w->toVariant();
1388 } else if (QV4::QQmlValueTypeWrapper *v = object->as<QV4::QQmlValueTypeWrapper>()) {
1389 return v->toVariant();
1390 } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
1391 return l->toVariant();
1392#if QT_CONFIG(qml_sequence_object)
1393 } else if (object->isListType()) {
1394 return QV4::SequencePrototype::toVariant(object);
1395#endif
1396 }
1397 }
1398
1399 if (value.as<ArrayObject>()) {
1400 QV4::ScopedArrayObject a(scope, value);
1401 if (typeHint == qMetaTypeId<QList<QObject *> >()) {
1402 QList<QObject *> list;
1403 uint length = a->getLength();
1404 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
1405 for (uint ii = 0; ii < length; ++ii) {
1406 qobjectWrapper = a->get(ii);
1407 if (!!qobjectWrapper) {
1408 list << qobjectWrapper->object();
1409 } else {
1410 list << 0;
1411 }
1412 }
1413
1414 return QVariant::fromValue<QList<QObject*> >(list);
1415 } else if (typeHint == QMetaType::QJsonArray) {
1416 return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
1417 }
1418
1419#if QT_CONFIG(qml_sequence_object)
1420 bool succeeded = false;
1421 QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded);
1422 if (succeeded)
1423 return retn;
1424#endif
1425 }
1426
1427 if (value.isUndefined())
1428 return QVariant();
1429 if (value.isNull())
1430 return QVariant::fromValue(nullptr);
1431 if (value.isBoolean())
1432 return value.booleanValue();
1433 if (value.isInteger())
1434 return value.integerValue();
1435 if (value.isNumber())
1436 return value.asDouble();
1437 if (String *s = value.stringValue()) {
1438 const QString &str = s->toQString();
1439 // QChars are stored as a strings
1440 if (typeHint == QVariant::Char && str.size() == 1)
1441 return str.at(0);
1442 return str;
1443 }
1444#if QT_CONFIG(qml_locale)
1445 if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
1446 return *ld->d()->locale;
1447#endif
1448 if (const QV4::DateObject *d = value.as<DateObject>())
1449 return d->toQDateTime();
1450 if (const ArrayBuffer *d = value.as<ArrayBuffer>())
1451 return d->asByteArray();
1452 // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
1453
1454 QV4::ScopedObject o(scope, value);
1455 Q_ASSERT(o);
1456
1457 if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) {
1458#if QT_CONFIG(regularexpression)
1459 if (typeHint != QMetaType::QRegExp)
1460 return re->toQRegularExpression();
1461#endif
1462 return re->toQRegExp();
1463 }
1464
1465 if (createJSValueForObjects)
1466 return QVariant::fromValue(QJSValue(scope.engine, o->asReturnedValue()));
1467
1468 return objectToVariant(e, o, visitedObjects);
1469}
1470
1471static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
1472{
1473 Q_ASSERT(o);
1474
1475 V4ObjectSet recursionGuardSet;
1476 if (!visitedObjects) {
1477 visitedObjects = &recursionGuardSet;
1478 } else if (visitedObjects->contains(o->d())) {
1479 // Avoid recursion.
1480 // For compatibility with QVariant{List,Map} conversion, we return an
1481 // empty object (and no error is thrown).
1482 if (o->as<ArrayObject>())
1483 return QVariantList();
1484 return QVariantMap();
1485 }
1486 visitedObjects->insert(o->d());
1487
1488 QVariant result;
1489
1490 if (o->as<ArrayObject>()) {
1491 QV4::Scope scope(e);
1492 QV4::ScopedArrayObject a(scope, o->asReturnedValue());
1493 QV4::ScopedValue v(scope);
1494 QVariantList list;
1495
1496 int length = a->getLength();
1497 for (int ii = 0; ii < length; ++ii) {
1498 v = a->get(ii);
1499 list << ::toVariant(e, v, -1, /*createJSValueForObjects*/false, visitedObjects);
1500 }
1501
1502 result = list;
1503 } else if (!o->as<FunctionObject>()) {
1504 QVariantMap map;
1505 QV4::Scope scope(e);
1506 QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
1507 QV4::ScopedValue name(scope);
1508 QV4::ScopedValue val(scope);
1509 while (1) {
1510 name = it.nextPropertyNameAsString(val);
1511 if (name->isNull())
1512 break;
1513
1514 QString key = name->toQStringNoThrow();
1515 map.insert(key, ::toVariant(e, val, /*type hint*/-1, /*createJSValueForObjects*/false, visitedObjects));
1516 }
1517
1518 result = map;
1519 }
1520
1521 visitedObjects->remove(o->d());
1522 return result;
1523}
1524
1525QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
1526{
1527 int type = variant.userType();
1528 const void *ptr = variant.constData();
1529
1530 if (type < QMetaType::User) {
1531 switch (QMetaType::Type(type)) {
1532 case QMetaType::UnknownType:
1533 case QMetaType::Void:
1534 return QV4::Encode::undefined();
1535 case QMetaType::Nullptr:
1536 case QMetaType::VoidStar:
1537 return QV4::Encode::null();
1538 case QMetaType::Bool:
1539 return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
1540 case QMetaType::Int:
1541 return QV4::Encode(*reinterpret_cast<const int*>(ptr));
1542 case QMetaType::UInt:
1543 return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
1544 case QMetaType::LongLong:
1545 return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
1546 case QMetaType::ULongLong:
1547 return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
1548 case QMetaType::Double:
1549 return QV4::Encode(*reinterpret_cast<const double*>(ptr));
1550 case QMetaType::QString:
1551 return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
1552 case QMetaType::QByteArray:
1553 return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue();
1554 case QMetaType::Float:
1555 return QV4::Encode(*reinterpret_cast<const float*>(ptr));
1556 case QMetaType::Short:
1557 return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
1558 case QMetaType::UShort:
1559 return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
1560 case QMetaType::Char:
1561 return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
1562 case QMetaType::UChar:
1563 return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
1564 case QMetaType::QChar:
1565 return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue();
1566 case QMetaType::QDateTime:
1567 return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(ptr)));
1568 case QMetaType::QDate:
1569 return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr), QTime(0, 0, 0), Qt::UTC)));
1570 case QMetaType::QTime:
1571 return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr)));
1572 case QMetaType::