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
40#include "qqmlbuiltinfunctions_p.h"
41
42#include <QtQml/qqmlcomponent.h>
43#include <QtQml/qqmlfile.h>
44#include <private/qqmlengine_p.h>
45#include <private/qqmlcomponent_p.h>
46#include <private/qqmlloggingcategory_p.h>
47#include <private/qqmlstringconverters_p.h>
48#if QT_CONFIG(qml_locale)
49#include <private/qqmllocale_p.h>
50#endif
51#include <private/qqmldelayedcallqueue_p.h>
52#include <QFileInfo>
53
54#include <private/qqmldebugconnector_p.h>
55#include <private/qqmldebugserviceinterfaces_p.h>
56#include <private/qqmlglobal_p.h>
57
58#include <private/qqmlplatform_p.h>
59
60#include <private/qv4engine_p.h>
61#include <private/qv4functionobject_p.h>
62#include <private/qv4include_p.h>
63#include <private/qv4context_p.h>
64#include <private/qv4stringobject_p.h>
65#include <private/qv4dateobject_p.h>
66#include <private/qv4mm_p.h>
67#include <private/qv4jsonobject_p.h>
68#include <private/qv4objectproto_p.h>
69#include <private/qv4qobjectwrapper_p.h>
70#include <private/qv4stackframe_p.h>
71
72#include <QtCore/qstring.h>
73#include <QtCore/qdatetime.h>
74#include <QtCore/qcryptographichash.h>
75#include <QtCore/qrect.h>
76#include <QtCore/qsize.h>
77#include <QtCore/qpoint.h>
78#include <QtCore/qurl.h>
79#include <QtCore/qfile.h>
80#include <QtCore/qcoreapplication.h>
81#include <QtCore/qloggingcategory.h>
82
83#include <QDebug>
84
85QT_BEGIN_NAMESPACE
86
87using namespace QV4;
88
89DEFINE_OBJECT_VTABLE(QtObject);
90
91#define THROW_TYPE_ERROR_WITH_MESSAGE(msg) \
92 do { \
93 return scope.engine->throwTypeError(QString::fromUtf8(msg)); \
94 } while (false)
95
96struct StaticQtMetaObject : public QObject
97{
98 static const QMetaObject *get()
99 { return &staticQtMetaObject; }
100};
101
102void Heap::QtObject::init(QQmlEngine *qmlEngine)
103{
104 Heap::Object::init();
105 enumeratorIterator = 0;
106 keyIterator = 0;
107 Scope scope(internalClass->engine);
108 ScopedObject o(scope, this);
109
110 {
111 ScopedString str(scope);
112 ScopedValue v(scope);
113 o->put(name: (str = scope.engine->newString(QStringLiteral("Asynchronous"))), v: (v = QV4::Value::fromInt32(i: 0)));
114 o->put(name: (str = scope.engine->newString(QStringLiteral("Synchronous"))), v: (v = QV4::Value::fromInt32(i: 1)));
115 }
116
117 o->defineDefaultProperty(QStringLiteral("include"), code: QV4Include::method_include);
118 o->defineDefaultProperty(QStringLiteral("isQtObject"), code: QV4::QtObject::method_isQtObject);
119 o->defineDefaultProperty(QStringLiteral("rgba"), code: QV4::QtObject::method_rgba);
120 o->defineDefaultProperty(QStringLiteral("hsla"), code: QV4::QtObject::method_hsla);
121 o->defineDefaultProperty(QStringLiteral("hsva"), code: QV4::QtObject::method_hsva);
122 o->defineDefaultProperty(QStringLiteral("colorEqual"), code: QV4::QtObject::method_colorEqual);
123 o->defineDefaultProperty(QStringLiteral("rect"), code: QV4::QtObject::method_rect);
124 o->defineDefaultProperty(QStringLiteral("point"), code: QV4::QtObject::method_point);
125 o->defineDefaultProperty(QStringLiteral("size"), code: QV4::QtObject::method_size);
126 o->defineDefaultProperty(QStringLiteral("font"), code: QV4::QtObject::method_font);
127
128 o->defineDefaultProperty(QStringLiteral("vector2d"), code: QV4::QtObject::method_vector2d);
129 o->defineDefaultProperty(QStringLiteral("vector3d"), code: QV4::QtObject::method_vector3d);
130 o->defineDefaultProperty(QStringLiteral("vector4d"), code: QV4::QtObject::method_vector4d);
131 o->defineDefaultProperty(QStringLiteral("quaternion"), code: QV4::QtObject::method_quaternion);
132 o->defineDefaultProperty(QStringLiteral("matrix4x4"), code: QV4::QtObject::method_matrix4x4);
133
134 o->defineDefaultProperty(QStringLiteral("formatDate"), code: QV4::QtObject::method_formatDate);
135 o->defineDefaultProperty(QStringLiteral("formatTime"), code: QV4::QtObject::method_formatTime);
136 o->defineDefaultProperty(QStringLiteral("formatDateTime"), code: QV4::QtObject::method_formatDateTime);
137
138 o->defineDefaultProperty(QStringLiteral("openUrlExternally"), code: QV4::QtObject::method_openUrlExternally);
139 o->defineDefaultProperty(QStringLiteral("fontFamilies"), code: QV4::QtObject::method_fontFamilies);
140 o->defineDefaultProperty(QStringLiteral("md5"), code: QV4::QtObject::method_md5);
141 o->defineDefaultProperty(QStringLiteral("btoa"), code: QV4::QtObject::method_btoa);
142 o->defineDefaultProperty(QStringLiteral("atob"), code: QV4::QtObject::method_atob);
143 o->defineDefaultProperty(QStringLiteral("resolvedUrl"), code: QV4::QtObject::method_resolvedUrl);
144#if QT_CONFIG(qml_locale)
145 o->defineDefaultProperty(QStringLiteral("locale"), code: QV4::QtObject::method_locale);
146#endif
147 o->defineDefaultProperty(QStringLiteral("binding"), code: QV4::QtObject::method_binding);
148
149 if (qmlEngine) {
150 o->defineDefaultProperty(QStringLiteral("lighter"), code: QV4::QtObject::method_lighter);
151 o->defineDefaultProperty(QStringLiteral("darker"), code: QV4::QtObject::method_darker);
152 o->defineDefaultProperty(QStringLiteral("tint"), code: QV4::QtObject::method_tint);
153 o->defineDefaultProperty(QStringLiteral("quit"), code: QV4::QtObject::method_quit);
154 o->defineDefaultProperty(QStringLiteral("exit"), code: QV4::QtObject::method_exit);
155 o->defineDefaultProperty(QStringLiteral("createQmlObject"), code: QV4::QtObject::method_createQmlObject);
156 o->defineDefaultProperty(QStringLiteral("createComponent"), code: QV4::QtObject::method_createComponent);
157 }
158
159 o->defineAccessorProperty(QStringLiteral("platform"), getter: QV4::QtObject::method_get_platform, setter: nullptr);
160 o->defineAccessorProperty(QStringLiteral("application"), getter: QV4::QtObject::method_get_application, setter: nullptr);
161 o->defineAccessorProperty(QStringLiteral("inputMethod"), getter: QV4::QtObject::method_get_inputMethod, setter: nullptr);
162 o->defineAccessorProperty(QStringLiteral("styleHints"), getter: QV4::QtObject::method_get_styleHints, setter: nullptr);
163
164 o->defineDefaultProperty(QStringLiteral("callLater"), code: QV4::QtObject::method_callLater);
165}
166
167void QtObject::addAll()
168{
169 bool dummy = false;
170 findAndAdd(name: nullptr, foundProperty&: dummy);
171}
172
173ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) const
174{
175 Scope scope(engine());
176 ScopedObject o(scope, this);
177 ScopedString key(scope);
178 ScopedValue value(scope);
179
180 const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
181 for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount;
182 ++d()->enumeratorIterator) {
183 QMetaEnum enumerator = qtMetaObject->enumerator(index: d()->enumeratorIterator);
184 for (int keyCount = enumerator.keyCount(); d()->keyIterator < keyCount; ++d()->keyIterator) {
185 key = scope.engine->newString(s: QString::fromUtf8(str: enumerator.key(index: d()->keyIterator)));
186 value = QV4::Value::fromInt32(i: enumerator.value(index: d()->keyIterator));
187 o->put(name: key, v: value);
188 if (name && key->toQString() == *name) {
189 ++d()->keyIterator;
190 foundProperty = true;
191 return value->asReturnedValue();
192 }
193 }
194 d()->keyIterator = 0;
195 }
196 d()->enumeratorIterator = Heap::QtObject::Finished;
197 foundProperty = false;
198 return Encode::undefined();
199}
200
201ReturnedValue QtObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
202{
203 bool hasProp = false;
204 if (hasProperty == nullptr) {
205 hasProperty = &hasProp;
206 }
207
208 ReturnedValue ret = QV4::Object::virtualGet(m, id, receiver, hasProperty);
209 if (*hasProperty) {
210 return ret;
211 }
212
213 auto that = static_cast<const QtObject*>(m);
214 if (!that->d()->isComplete()) {
215 const QString key = id.toQString();
216 ret = that->findAndAdd(name: &key, foundProperty&: *hasProperty);
217 }
218
219 return ret;
220}
221
222OwnPropertyKeyIterator *QtObject::virtualOwnPropertyKeys(const Object *m, Value *target)
223{
224 auto that = static_cast<const QtObject*>(m);
225 if (!that->d()->isComplete())
226 const_cast<QtObject *>(that)->addAll();
227
228 return Object::virtualOwnPropertyKeys(m, target);
229}
230
231/*!
232 \qmlmethod bool Qt::isQtObject(object)
233
234 Returns \c true if \a object is a valid reference to a Qt or QML object,
235 \c false otherwise.
236*/
237ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *, const Value *argv, int argc)
238{
239 if (argc == 0)
240 RETURN_RESULT(QV4::Encode(false));
241
242 return QV4::Encode(argv[0].as<QV4::QObjectWrapper>() != nullptr);
243}
244
245/*!
246 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
247
248 Returns a color with the specified \a red, \a green, \a blue, and \a alpha
249 components. All components should be in the range 0-1 (inclusive).
250*/
251ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, const Value *argv, int argc)
252{
253 QV4::Scope scope(f);
254 if (argc < 3 || argc > 4)
255 THROW_GENERIC_ERROR("Qt.rgba(): Invalid arguments");
256
257 double r = argv[0].toNumber();
258 double g = argv[1].toNumber();
259 double b = argv[2].toNumber();
260 double a = (argc == 4) ? argv[3].toNumber() : 1;
261
262 if (r < 0.0) r=0.0;
263 if (r > 1.0) r=1.0;
264 if (g < 0.0) g=0.0;
265 if (g > 1.0) g=1.0;
266 if (b < 0.0) b=0.0;
267 if (b > 1.0) b=1.0;
268 if (a < 0.0) a=0.0;
269 if (a > 1.0) a=1.0;
270
271 return scope.engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
272}
273
274/*!
275 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
276
277 Returns a color with the specified \a hue, \a saturation, \a lightness, and \a alpha
278 components. All components should be in the range 0-1 (inclusive).
279*/
280ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, const Value *argv, int argc)
281{
282 QV4::Scope scope(b);
283 int argCount = argc;
284 if (argCount < 3 || argCount > 4)
285 THROW_GENERIC_ERROR("Qt.hsla(): Invalid arguments");
286
287 double h = argv[0].toNumber();
288 double s = argv[1].toNumber();
289 double l = argv[2].toNumber();
290 double a = (argCount == 4) ? argv[3].toNumber() : 1;
291
292 if (h < 0.0) h=0.0;
293 if (h > 1.0) h=1.0;
294 if (s < 0.0) s=0.0;
295 if (s > 1.0) s=1.0;
296 if (l < 0.0) l=0.0;
297 if (l > 1.0) l=1.0;
298 if (a < 0.0) a=0.0;
299 if (a > 1.0) a=1.0;
300
301 return scope.engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
302}
303
304/*!
305 \since 5.5
306 \qmlmethod color Qt::hsva(real hue, real saturation, real value, real alpha)
307
308 Returns a color with the specified \a hue, \a saturation, \a value and \a alpha
309 components. All components should be in the range 0-1 (inclusive).
310
311*/
312ReturnedValue QtObject::method_hsva(const FunctionObject *b, const Value *, const Value *argv, int argc)
313{
314 QV4::Scope scope(b);
315 int argCount = argc;
316 if (argCount < 3 || argCount > 4)
317 THROW_GENERIC_ERROR("Qt.hsva(): Invalid arguments");
318
319 double h = argv[0].toNumber();
320 double s = argv[1].toNumber();
321 double v = argv[2].toNumber();
322 double a = (argCount == 4) ? argv[3].toNumber() : 1;
323
324 h = qBound(min: 0.0, val: h, max: 1.0);
325 s = qBound(min: 0.0, val: s, max: 1.0);
326 v = qBound(min: 0.0, val: v, max: 1.0);
327 a = qBound(min: 0.0, val: a, max: 1.0);
328
329 return scope.engine->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a));
330}
331
332/*!
333 \qmlmethod color Qt::colorEqual(color lhs, string rhs)
334
335 Returns \c true if both \a lhs and \a rhs yield equal color values. Both
336 arguments may be either color values or string values. If a string value
337 is supplied it must be convertible to a color, as described for the
338 \l{colorbasictypedocs}{color} basic type.
339*/
340ReturnedValue QtObject::method_colorEqual(const FunctionObject *b, const Value *, const Value *argv, int argc)
341{
342 QV4::Scope scope(b);
343 if (argc != 2)
344 THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
345
346 bool ok = false;
347
348 QVariant lhs = scope.engine->toVariant(value: argv[0], typeHint: -1);
349 if (lhs.userType() == QMetaType::QString) {
350 lhs = QQmlStringConverters::colorFromString(lhs.toString(), ok: &ok);
351 if (!ok) {
352 THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
353 }
354 } else if (lhs.userType() != QMetaType::QColor) {
355 THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
356 }
357
358 QVariant rhs = scope.engine->toVariant(value: argv[1], typeHint: -1);
359 if (rhs.userType() == QMetaType::QString) {
360 rhs = QQmlStringConverters::colorFromString(rhs.toString(), ok: &ok);
361 if (!ok) {
362 THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
363 }
364 } else if (rhs.userType() != QMetaType::QColor) {
365 THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
366 }
367
368 bool equal = (lhs == rhs);
369 return QV4::Encode(equal);
370}
371
372/*!
373 \qmlmethod rect Qt::rect(real x, real y, real width, real height)
374
375 Returns a rect with the top-left corner at \a x, \a y and the specified \a width and \a height.
376*/
377ReturnedValue QtObject::method_rect(const FunctionObject *b, const Value *, const Value *argv, int argc)
378{
379 QV4::Scope scope(b);
380 if (argc != 4)
381 THROW_GENERIC_ERROR("Qt.rect(): Invalid arguments");
382
383 double x = argv[0].toNumber();
384 double y = argv[1].toNumber();
385 double w = argv[2].toNumber();
386 double h = argv[3].toNumber();
387
388 return scope.engine->fromVariant(QVariant::fromValue(value: QRectF(x, y, w, h)));
389}
390
391/*!
392 \qmlmethod point Qt::point(real x, real y)
393
394 Returns a point with the specified \a x and \a y coordinates.
395*/
396ReturnedValue QtObject::method_point(const FunctionObject *b, const Value *, const Value *argv, int argc)
397{
398 QV4::Scope scope(b);
399 if (argc != 2)
400 THROW_GENERIC_ERROR("Qt.point(): Invalid arguments");
401
402 double x = argv[0].toNumber();
403 double y = argv[1].toNumber();
404
405 return scope.engine->fromVariant(QVariant::fromValue(value: QPointF(x, y)));
406}
407
408/*!
409 \qmlmethod size Qt::size(real width, real height)
410
411 Returns a size with the specified \a width and \a height.
412*/
413ReturnedValue QtObject::method_size(const FunctionObject *b, const Value *, const Value *argv, int argc)
414{
415 QV4::Scope scope(b);
416 if (argc != 2)
417 THROW_GENERIC_ERROR("Qt.size(): Invalid arguments");
418
419 double w = argv[0].toNumber();
420 double h = argv[1].toNumber();
421
422 return scope.engine->fromVariant(QVariant::fromValue(value: QSizeF(w, h)));
423}
424
425/*!
426 \qmlmethod font Qt::font(object fontSpecifier)
427
428 Returns a font with the properties specified in the \a fontSpecifier object
429 or the nearest matching font. The \a fontSpecifier object should contain
430 key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's
431 subproperty names, and the values are valid values for each subproperty.
432 Invalid keys will be ignored.
433*/
434ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, const Value *argv, int argc)
435{
436 QV4::Scope scope(b);
437 if (argc != 1 || !argv[0].isObject())
438 THROW_GENERIC_ERROR("Qt.font(): Invalid arguments");
439
440 QV4::ExecutionEngine *v4 = scope.engine;
441 bool ok = false;
442 QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, argv[0], v4, &ok);
443 if (!ok)
444 THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
445 return scope.engine->fromVariant(v);
446}
447
448
449
450/*!
451 \qmlmethod vector2d Qt::vector2d(real x, real y)
452
453 Returns a vector2d with the specified \a x and \a y values.
454*/
455ReturnedValue QtObject::method_vector2d(const FunctionObject *b, const Value *, const Value *argv, int argc)
456{
457 QV4::Scope scope(b);
458 if (argc != 2)
459 THROW_GENERIC_ERROR("Qt.vector2d(): Invalid arguments");
460
461 float xy[3]; // qvector2d uses float internally
462 xy[0] = argv[0].toNumber();
463 xy[1] = argv[1].toNumber();
464
465 const void *params[] = { xy };
466 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
467}
468
469/*!
470 \qmlmethod vector3d Qt::vector3d(real x, real y, real z)
471
472 Returns a vector3d with the specified \a x, \a y, and \a z values.
473*/
474ReturnedValue QtObject::method_vector3d(const FunctionObject *b, const Value *, const Value *argv, int argc)
475{
476 QV4::Scope scope(b);
477 if (argc != 3)
478 THROW_GENERIC_ERROR("Qt.vector3d(): Invalid arguments");
479
480 float xyz[3]; // qvector3d uses float internally
481 xyz[0] = argv[0].toNumber();
482 xyz[1] = argv[1].toNumber();
483 xyz[2] = argv[2].toNumber();
484
485 const void *params[] = { xyz };
486 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
487}
488
489/*!
490 \qmlmethod vector4d Qt::vector4d(real x, real y, real z, real w)
491
492 Returns a vector4d with the specified \a x, \a y, \a z, and \a w values.
493*/
494ReturnedValue QtObject::method_vector4d(const FunctionObject *b, const Value *, const Value *argv, int argc)
495{
496 QV4::Scope scope(b);
497 if (argc != 4)
498 THROW_GENERIC_ERROR("Qt.vector4d(): Invalid arguments");
499
500 float xyzw[4]; // qvector4d uses float internally
501 xyzw[0] = argv[0].toNumber();
502 xyzw[1] = argv[1].toNumber();
503 xyzw[2] = argv[2].toNumber();
504 xyzw[3] = argv[3].toNumber();
505
506 const void *params[] = { xyzw };
507 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
508}
509
510/*!
511 \qmlmethod quaternion Qt::quaternion(real scalar, real x, real y, real z)
512
513 Returns a quaternion with the specified \a scalar, \a x, \a y, and \a z values.
514*/
515ReturnedValue QtObject::method_quaternion(const FunctionObject *b, const Value *, const Value *argv, int argc)
516{
517 QV4::Scope scope(b);
518 if (argc != 4)
519 THROW_GENERIC_ERROR("Qt.quaternion(): Invalid arguments");
520
521 qreal sxyz[4]; // qquaternion uses qreal internally
522 sxyz[0] = argv[0].toNumber();
523 sxyz[1] = argv[1].toNumber();
524 sxyz[2] = argv[2].toNumber();
525 sxyz[3] = argv[3].toNumber();
526
527 const void *params[] = { sxyz };
528 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
529}
530
531/*!
532 \qmlmethod matrix4x4 Qt::matrix4x4(real m11, real m12, real m13, real m14, real m21, real m22, real m23, real m24, real m31, real m32, real m33, real m34, real m41, real m42, real m43, real m44)
533
534 Returns a matrix4x4 with the specified values.
535
536 The arguments correspond to their positions in the matrix:
537
538 \table
539 \row \li \a m11 \li \a m12 \li \a m13 \li \a m14
540 \row \li \a m21 \li \a m22 \li \a m23 \li \a m24
541 \row \li \a m31 \li \a m32 \li \a m33 \li \a m34
542 \row \li \a m41 \li \a m42 \li \a m43 \li \a m44
543 \endtable
544
545 Alternatively, the function may be called with a single argument
546 where that argument is a JavaScript array which contains the sixteen
547 matrix values.
548
549 Finally, the function may be called with no arguments and the resulting
550 matrix will be the identity matrix.
551*/
552ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *, const Value *argv, int argc)
553{
554 QV4::Scope scope(b);
555
556 if (argc == 0) {
557 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, nullptr));
558 }
559
560 if (argc == 1 && argv[0].isObject()) {
561 bool ok = false;
562 QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, argv[0], scope.engine, &ok);
563 if (!ok)
564 THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
565 return scope.engine->fromVariant(v);
566 }
567
568 if (argc != 16)
569 THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid arguments");
570
571 qreal vals[16]; // qmatrix4x4 uses qreal internally
572 vals[0] = argv[0].toNumber();
573 vals[1] = argv[1].toNumber();
574 vals[2] = argv[2].toNumber();
575 vals[3] = argv[3].toNumber();
576 vals[4] = argv[4].toNumber();
577 vals[5] = argv[5].toNumber();
578 vals[6] = argv[6].toNumber();
579 vals[7] = argv[7].toNumber();
580 vals[8] = argv[8].toNumber();
581 vals[9] = argv[9].toNumber();
582 vals[10] = argv[10].toNumber();
583 vals[11] = argv[11].toNumber();
584 vals[12] = argv[12].toNumber();
585 vals[13] = argv[13].toNumber();
586 vals[14] = argv[14].toNumber();
587 vals[15] = argv[15].toNumber();
588
589 const void *params[] = { vals };
590 return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
591}
592
593/*!
594 \qmlmethod color Qt::lighter(color baseColor, real factor)
595
596 Returns a color lighter than \a baseColor by the \a factor provided.
597
598 If the factor is greater than 1.0, this functions returns a lighter color.
599 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
600 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
601 If the factor is 0 or negative, the return value is unspecified.
602
603 The function converts the current RGB color to HSV, multiplies the value (V) component
604 by factor and converts the color back to RGB.
605
606 If \a factor is not supplied, returns a color that is 50% lighter than \a baseColor (factor 1.5).
607*/
608ReturnedValue QtObject::method_lighter(const FunctionObject *b, const Value *, const Value *argv, int argc)
609{
610 QV4::Scope scope(b);
611 if (argc != 1 && argc != 2)
612 THROW_GENERIC_ERROR("Qt.lighter(): Invalid arguments");
613
614 QVariant v = scope.engine->toVariant(value: argv[0], typeHint: -1);
615 if (v.userType() == QMetaType::QString) {
616 bool ok = false;
617 v = QQmlStringConverters::colorFromString(v.toString(), ok: &ok);
618 if (!ok) {
619 return QV4::Encode::null();
620 }
621 } else if (v.userType() != QMetaType::QColor) {
622 return QV4::Encode::null();
623 }
624
625 qreal factor = 1.5;
626 if (argc == 2)
627 factor = argv[1].toNumber();
628
629 return scope.engine->fromVariant(QQml_colorProvider()->lighter(v, factor));
630}
631
632/*!
633 \qmlmethod color Qt::darker(color baseColor, real factor)
634
635 Returns a color darker than \a baseColor by the \a factor provided.
636
637 If the factor is greater than 1.0, this function returns a darker color.
638 Setting factor to 3.0 returns a color that has one-third the brightness.
639 If the factor is less than 1.0, the return color is lighter, but we recommend using
640 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
641 value is unspecified.
642
643 The function converts the current RGB color to HSV, divides the value (V) component
644 by factor and converts the color back to RGB.
645
646 If \a factor is not supplied, returns a color that is 50% darker than \a baseColor (factor 2.0).
647*/
648ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, const Value *argv, int argc)
649{
650 QV4::Scope scope(b);
651 if (argc != 1 && argc != 2)
652 THROW_GENERIC_ERROR("Qt.darker(): Invalid arguments");
653
654 QVariant v = scope.engine->toVariant(value: argv[0], typeHint: -1);
655 if (v.userType() == QMetaType::QString) {
656 bool ok = false;
657 v = QQmlStringConverters::colorFromString(v.toString(), ok: &ok);
658 if (!ok) {
659 return QV4::Encode::null();
660 }
661 } else if (v.userType() != QMetaType::QColor) {
662 return QV4::Encode::null();
663 }
664
665 qreal factor = 2.0;
666 if (argc == 2)
667 factor = argv[1].toNumber();
668
669 return scope.engine->fromVariant(QQml_colorProvider()->darker(v, factor));
670}
671
672/*!
673 \qmlmethod color Qt::tint(color baseColor, color tintColor)
674
675 This function allows tinting one color (\a baseColor) with another (\a tintColor).
676
677 The tint color should usually be mostly transparent, or you will not be
678 able to see the underlying color. The below example provides a slight red
679 tint by having the tint color be pure red which is only 1/16th opaque.
680
681 \qml
682 Item {
683 Rectangle {
684 x: 0; width: 80; height: 80
685 color: "lightsteelblue"
686 }
687 Rectangle {
688 x: 100; width: 80; height: 80
689 color: Qt.tint("lightsteelblue", "#10FF0000")
690 }
691 }
692 \endqml
693 \image declarative-rect_tint.png
694
695 Tint is most useful when a subtle change is intended to be conveyed due to some event;
696 you can then use tinting to more effectively tune the visible color.
697*/
698ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, const Value *argv, int argc)
699{
700 QV4::Scope scope(b);
701 if (argc != 2)
702 THROW_GENERIC_ERROR("Qt.tint(): Invalid arguments");
703
704 // base color
705 QVariant v1 = scope.engine->toVariant(value: argv[0], typeHint: -1);
706 if (v1.userType() == QMetaType::QString) {
707 bool ok = false;
708 v1 = QQmlStringConverters::colorFromString(v1.toString(), ok: &ok);
709 if (!ok) {
710 return QV4::Encode::null();
711 }
712 } else if (v1.userType() != QMetaType::QColor) {
713 return QV4::Encode::null();
714 }
715
716 // tint color
717 QVariant v2 = scope.engine->toVariant(value: argv[1], typeHint: -1);
718 if (v2.userType() == QMetaType::QString) {
719 bool ok = false;
720 v2 = QQmlStringConverters::colorFromString(v2.toString(), ok: &ok);
721 if (!ok) {
722 return QV4::Encode::null();
723 }
724 } else if (v2.userType() != QMetaType::QColor) {
725 return QV4::Encode::null();
726 }
727
728 return scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2));
729}
730
731namespace {
732template <typename T>
733QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format) {
734 switch (format) {
735 case Qt::TextDate:
736 case Qt::ISODate:
737 case Qt::RFC2822Date:
738 case Qt::ISODateWithMs:
739 return formatThis.toString(format);
740 // ### Qt 6: Remove all locale dependent cases
741 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
742 case Qt::SystemLocaleDate:
743 // case Qt::LocalDate: covered by SystemLocaleDate
744 return QLocale::system().toString(formatThis);
745 case Qt::LocaleDate:
746 case Qt::DefaultLocaleShortDate:
747 return QLocale().toString(formatThis, QLocale::ShortFormat);
748 case Qt::SystemLocaleShortDate:
749 return QLocale::system().toString(formatThis, QLocale::ShortFormat);
750 case Qt::SystemLocaleLongDate:
751 return QLocale::system().toString(formatThis, QLocale::LongFormat);
752 case Qt::DefaultLocaleLongDate:
753 return QLocale().toString(formatThis, QLocale::LongFormat);
754 }
755 QT_WARNING_POP
756 Q_UNREACHABLE();
757 return QString();
758}
759
760template <typename T>
761ReturnedValue formatDateTimeObject(const T &formatThis, const QV4::Scope &scope, const QString &functionName, int argc, const Value *argv) {
762
763 QString formatted;
764 if (argc >= 2) {
765 QV4::ScopedString s(scope, argv[1]);
766 if (s) {
767 if (argc == 3)
768 scope.engine->throwError(message: QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(args: functionName));
769 QString format = s->toQString();
770 formatted = formatThis.toString(format);
771 } else if (argv[1].isNumber()) {
772 if (argc == 3)
773 scope.engine->throwError(message: QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(args: functionName));
774 quint32 intFormat = argv[1].asDouble();
775 Qt::DateFormat format = Qt::DateFormat(intFormat);
776 formatted = formatDateTimeObjectUsingDateFormat(formatThis, format);
777 } else {
778 QLocale::FormatType formatOptions = QLocale::ShortFormat;
779 if (argc == 3) {
780 if (argv[2].isNumber())
781 formatOptions = QLocale::FormatType(quint32(argv[2].asDouble()));
782 else
783 scope.engine->throwError(message: QLatin1String("%1(): Third argument must be a Locale format option").arg(args: functionName));
784 }
785 auto enginePriv = QQmlEnginePrivate::get(e: scope.engine->qmlEngine());
786 auto localeMetaTypeId = qMetaTypeId<QLocale>();
787 QVariant locale = enginePriv->v4engine()->toVariant(value: argv[1], typeHint: localeMetaTypeId);
788 if (!locale.canConvert(targetTypeId: localeMetaTypeId))
789 scope.engine->throwError(message: QLatin1String("%1(): Bad second argument (must be either string, number or locale)").arg(args: functionName));
790 formatted = locale.value<QLocale>().toString(formatThis, formatOptions);
791 }
792 } else {
793 formatted = QLocale().toString(formatThis, QLocale::ShortFormat);
794 }
795
796 return Encode(scope.engine->newString(s: formatted));
797}
798
799}
800
801/*!
802\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption)
803
804Returns a string representation of \a date, optionally formatted using \a format.
805
806The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
807property, a QDate, or QDateTime value. The \a format and \a localeFormatOption
808parameter may be any of the possible format values as described for
809\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
810
811If \a format is not specified, \a date is formatted using
812\l {QLocale::FormatType}{Locale.ShortFormat} using the
813default locale.
814
815\sa Locale
816*/
817ReturnedValue QtObject::method_formatDate(const FunctionObject *b, const Value *, const Value *argv, int argc)
818{
819 QV4::Scope scope(b);
820 if (argc < 1)
821 THROW_GENERIC_ERROR("Qt.formatDate(): Missing argument");
822 if (argc > 3)
823 THROW_GENERIC_ERROR("Qt.formatDate(): Stray arguments; formatDate takes at most 3 arguments.");
824
825 QDate date = scope.engine->toVariant(value: argv[0], typeHint: -1).toDateTime().date();
826 return formatDateTimeObject(formatThis: date, scope, functionName: QLatin1String("Qt.formatDate"), argc, argv);
827}
828
829/*!
830\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption)
831
832Returns a string representation of \a time, optionally formatted using
833\a format, and, if provided, \a localeFormatOption.
834
835The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
836value. The \a format and \a localeFormatOption parameter may be any of the
837possible format values as described for
838\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
839
840If \a format is not specified, \a time is formatted using
841\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale.
842
843\sa Locale
844*/
845ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
846{
847 QV4::Scope scope(b);
848 if (argc < 1)
849 THROW_GENERIC_ERROR("Qt.formatTime(): Missing argument");
850 if (argc > 3)
851 THROW_GENERIC_ERROR("Qt.formatTime(): Stray arguments; formatTime takes at most 3 arguments.");
852
853 QVariant argVariant = scope.engine->toVariant(value: argv[0], typeHint: -1);
854 QTime time;
855 if (argv[0].as<DateObject>() || (argVariant.userType() == QMetaType::QString))
856 time = argVariant.toDateTime().time();
857 else // if (argVariant.type() == QVariant::Time), or invalid.
858 time = argVariant.toTime();
859 return formatDateTimeObject(formatThis: time, scope, functionName: QLatin1String("Qt.formatTime"), argc, argv);
860}
861
862/*!
863\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption)
864
865Returns a string representation of \a dateTime, optionally formatted using
866\a format and \a localeFormatOption.
867
868The \a dateTime parameter may be a JavaScript \c Date object, a \l{date}{date}
869property, a QDate, QTime, or QDateTime value.
870
871If \a format is not provided, \a dateTime is formatted using
872\l {QLocale::FormatType}{Locale.ShortFormat} using the
873default locale. Otherwise, \a format should be either:
874
875\list
876\li One of the Qt::DateFormat enumeration values, such as
877 \c Qt.RFC2822Date or \c Qt.ISODate.
878\li A string that specifies the format of the returned string, as detailed below.
879\li A \c locale object.
880\endlist
881
882If \a format specifies a locale object, \dateTime is formatted
883with \l{QLocale::toString}. In this case, \a localeFormatOption can hold a value
884of type \l {QLocale::FormatType} to further tune the formatting. If none is
885provided, \l {QLocale::FormatType}{Locale.ShortFormat} is used.
886
887If \a format specifies a format string, it should use the following expressions
888to specify the date:
889
890 \table
891 \header \li Expression \li Output
892 \row \li d \li the day as number without a leading zero (1 to 31)
893 \row \li dd \li the day as number with a leading zero (01 to 31)
894 \row \li ddd
895 \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
896 Uses QDate::shortDayName().
897 \row \li dddd
898 \li the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
899 Uses QDate::longDayName().
900 \row \li M \li the month as number without a leading zero (1-12)
901 \row \li MM \li the month as number with a leading zero (01-12)
902 \row \li MMM
903 \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
904 Uses QDate::shortMonthName().
905 \row \li MMMM
906 \li the long localized month name (e.g. 'January' to 'December').
907 Uses QDate::longMonthName().
908 \row \li yy \li the year as two digit number (00-99)
909 \row \li yyyy \li the year as four digit number
910 \endtable
911
912In addition the following expressions can be used to specify the time:
913
914 \table
915 \header \li Expression \li Output
916 \row \li h
917 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
918 \row \li hh
919 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
920 \row \li m \li the minute without a leading zero (0 to 59)
921 \row \li mm \li the minute with a leading zero (00 to 59)
922 \row \li s \li the second without a leading zero (0 to 59)
923 \row \li ss \li the second with a leading zero (00 to 59)
924 \row \li z \li the milliseconds without leading zeroes (0 to 999)
925 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
926 \row \li AP
927 \li use AM/PM display. \e AP will be replaced by either "AM" or "PM".
928 \row \li ap
929 \li use am/pm display. \e ap will be replaced by either "am" or "pm".
930 \row \li t
931 \li include a time-zone indicator.
932 \endtable
933
934 All other input characters will be ignored. Any sequence of characters that
935 are enclosed in single quotes will be treated as text and not be used as an
936 expression. Two consecutive single quotes ("''") are replaced by a single quote
937 in the output.
938
939For example, if the following date/time value was specified:
940
941 \code
942 // 21 May 2001 14:13:09
943 var dateTime = new Date(2001, 5, 21, 14, 13, 09)
944 \endcode
945
946This \a dateTime value could be passed to \c Qt.formatDateTime(),
947\l {QtQml::Qt::formatDate()}{Qt.formatDate()} or \l {QtQml::Qt::formatTime()}{Qt.formatTime()}
948with the \a format values below to produce the following results:
949
950 \table
951 \header \li Format \li Result
952 \row \li "dd.MM.yyyy" \li 21.05.2001
953 \row \li "ddd MMMM d yy" \li Tue May 21 01
954 \row \li "hh:mm:ss.zzz" \li 14:13:09.042
955 \row \li "h:m:s ap" \li 2:13:9 pm
956 \endtable
957
958 \sa Locale
959*/
960ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
961{
962 QV4::Scope scope(b);
963 if (argc < 1)
964 THROW_GENERIC_ERROR("Qt.formatDateTime(): Missing argument");
965 if (argc > 3)
966 THROW_GENERIC_ERROR("Qt.formatDateTime(): Stray arguments; formatDate takes at most 3 arguments.");
967
968 QDateTime dt = scope.engine->toVariant(value: argv[0], typeHint: -1).toDateTime();
969 return formatDateTimeObject(formatThis: dt, scope, functionName: QLatin1String("Qt.formatDateTime"), argc, argv);
970}
971
972/*!
973 \qmlmethod bool Qt::openUrlExternally(url target)
974
975 Attempts to open the specified \a target url in an external application, based on the user's
976 desktop preferences. Returns \c true if it succeeds, \c false otherwise.
977
978 \warning A return value of \c true indicates that the application has successfully requested
979 the operating system to open the URL in an external application. The external application may
980 still fail to launch or fail to open the requested URL. This result will not be reported back
981 to the application.
982*/
983ReturnedValue QtObject::method_openUrlExternally(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
984{
985 QV4::Scope scope(b);
986 if (argc != 1)
987 return QV4::Encode(false);
988
989 ScopedValue result(scope, method_resolvedUrl(b, thisObject, argv, argc));
990 QUrl url(result->toQStringNoThrow());
991 return scope.engine->fromVariant(QQml_guiProvider()->openUrlExternally(url));
992}
993
994/*!
995 \qmlmethod url Qt::resolvedUrl(url url)
996
997 Returns \a url resolved relative to the URL of the caller.
998*/
999ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value *, const Value *argv, int argc)
1000{
1001 QV4::Scope scope(b);
1002 if (argc != 1)
1003 return Encode::undefined();
1004
1005 QUrl url = scope.engine->toVariant(value: argv[0], typeHint: -1).toUrl();
1006 QQmlEngine *e = scope.engine->qmlEngine();
1007 QQmlEnginePrivate *p = nullptr;
1008 if (e) p = QQmlEnginePrivate::get(e);
1009 if (p) {
1010 QQmlContextData *ctxt = scope.engine->callingQmlContext();
1011 if (ctxt)
1012 return Encode(scope.engine->newString(s: ctxt->resolvedUrl(url).toString()));
1013 else
1014 return Encode(scope.engine->newString(s: url.toString()));
1015 }
1016
1017 return Encode(scope.engine->newString(s: e->baseUrl().resolved(relative: url).toString()));
1018}
1019
1020/*!
1021\qmlmethod list<string> Qt::fontFamilies()
1022
1023Returns a list of the font families available to the application.
1024*/
1025ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, const Value *, const Value *, int argc)
1026{
1027 QV4::Scope scope(b);
1028 if (argc != 0)
1029 THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments");
1030
1031 return scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
1032}
1033
1034/*!
1035\qmlmethod string Qt::md5(data)
1036Returns a hex string of the md5 hash of \a data.
1037*/
1038ReturnedValue QtObject::method_md5(const FunctionObject *b, const Value *, const Value *argv, int argc)
1039{
1040 QV4::Scope scope(b);
1041 if (argc != 1)
1042 THROW_GENERIC_ERROR("Qt.md5(): Invalid arguments");
1043
1044 QByteArray data = argv[0].toQStringNoThrow().toUtf8();
1045 QByteArray result = QCryptographicHash::hash(data, method: QCryptographicHash::Md5);
1046 return Encode(scope.engine->newString(s: QLatin1String(result.toHex())));
1047}
1048
1049/*!
1050\qmlmethod string Qt::btoa(data)
1051Binary to ASCII - this function returns a base64 encoding of \a data.
1052*/
1053ReturnedValue QtObject::method_btoa(const FunctionObject *b, const Value *, const Value *argv, int argc)
1054{
1055 QV4::Scope scope(b);
1056 if (argc != 1)
1057 THROW_GENERIC_ERROR("Qt.btoa(): Invalid arguments");
1058
1059 QByteArray data = argv[0].toQStringNoThrow().toUtf8();
1060
1061 return Encode(scope.engine->newString(s: QLatin1String(data.toBase64())));
1062}
1063
1064/*!
1065\qmlmethod string Qt::atob(data)
1066ASCII to binary - this function decodes the base64 encoded \a data string and returns it.
1067*/
1068ReturnedValue QtObject::method_atob(const FunctionObject *b, const Value *, const Value *argv, int argc)
1069{
1070 QV4::Scope scope(b);
1071 if (argc != 1)
1072 THROW_GENERIC_ERROR("Qt.atob(): Invalid arguments");
1073
1074 QByteArray data = argv[0].toQStringNoThrow().toLatin1();
1075
1076 return Encode(scope.engine->newString(s: QString::fromUtf8(str: QByteArray::fromBase64(base64: data))));
1077}
1078
1079/*!
1080\qmlmethod Qt::quit()
1081This function causes the QQmlEngine::quit() signal to be emitted.
1082Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit;
1083to quit a C++ application when this method is called, connect the
1084QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
1085
1086\sa exit()
1087*/
1088ReturnedValue QtObject::method_quit(const FunctionObject *b, const Value *, const Value *, int)
1089{
1090 QQmlEnginePrivate::get(e: b->engine()->qmlEngine())->sendQuit();
1091 return Encode::undefined();
1092}
1093
1094/*!
1095 \qmlmethod Qt::exit(int retCode)
1096
1097 This function causes the QQmlEngine::exit(int) signal to be emitted.
1098 Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit
1099 the specified return code (\a retCode). To exit from the event loop with a specified
1100 return code when this method is called, a C++ application can connect the
1101 QQmlEngine::exit(int) signal to the QCoreApplication::exit(int) slot.
1102
1103 \sa quit()
1104*/
1105ReturnedValue QtObject::method_exit(const FunctionObject *b, const Value *, const Value *argv, int argc)
1106{
1107 QV4::Scope scope(b);
1108 if (argc != 1)
1109 THROW_GENERIC_ERROR("Qt.exit(): Invalid arguments");
1110
1111 int retCode = argv[0].toNumber();
1112
1113 QQmlEnginePrivate::get(e: scope.engine->qmlEngine())->sendExit(retCode);
1114 return QV4::Encode::undefined();
1115}
1116
1117/*!
1118\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
1119
1120Returns a new object created from the given \a qml string which will have the specified \a parent,
1121or \c null if there was an error in creating the object.
1122
1123If \a filepath is specified, it will be used for error reporting for the created object.
1124
1125Example (where \c parentItem is the id of an existing QML item):
1126
1127\snippet qml/createQmlObject.qml 0
1128
1129In the case of an error, a QQmlError object is thrown. This object has an additional property,
1130\c qmlErrors, which is an array of the errors encountered.
1131Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
1132For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
1133{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
1134
1135Note that this function returns immediately, and therefore may not work if
1136the \a qml string loads new components (that is, external QML files that have not yet been loaded).
1137If this is the case, consider using \l{QtQml::Qt::createComponent()}{Qt.createComponent()} instead.
1138
1139See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
1140*/
1141ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Value *, const Value *argv, int argc)
1142{
1143 QV4::Scope scope(b);
1144 if (argc < 2 || argc > 3)
1145 THROW_GENERIC_ERROR("Qt.createQmlObject(): Invalid arguments");
1146
1147 struct Error {
1148 static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
1149 Scope scope(v4);
1150 QString errorstr;
1151 // '+=' reserves extra capacity. Follow-up appending will be probably free.
1152 errorstr += QLatin1String("Qt.createQmlObject(): failed to create object: ");
1153
1154 QV4::ScopedArrayObject qmlerrors(scope, v4->newArrayObject());
1155 QV4::ScopedObject qmlerror(scope);
1156 QV4::ScopedString s(scope);
1157 QV4::ScopedValue v(scope);
1158 for (int ii = 0; ii < errors.count(); ++ii) {
1159 const QQmlError &error = errors.at(i: ii);
1160 errorstr += QLatin1String("\n ") + error.toString();
1161 qmlerror = v4->newObject();
1162 qmlerror->put(name: (s = v4->newString(QStringLiteral("lineNumber"))), v: (v = QV4::Value::fromInt32(i: error.line())));
1163 qmlerror->put(name: (s = v4->newString(QStringLiteral("columnNumber"))), v: (v = QV4::Value::fromInt32(i: error.column())));
1164 qmlerror->put(name: (s = v4->newString(QStringLiteral("fileName"))), v: (v = v4->newString(s: error.url().toString())));
1165 qmlerror->put(name: (s = v4->newString(QStringLiteral("message"))), v: (v = v4->newString(s: error.description())));
1166 qmlerrors->put(idx: ii, v: qmlerror);
1167 }
1168
1169 v = v4->newString(s: errorstr);
1170 ScopedObject errorObject(scope, v4->newErrorObject(value: v));
1171 errorObject->put(name: (s = v4->newString(QStringLiteral("qmlErrors"))), v: qmlerrors);
1172 return errorObject.asReturnedValue();
1173 }
1174 };
1175
1176 QQmlEngine *engine = scope.engine->qmlEngine();
1177
1178 QQmlContextData *context = scope.engine->callingQmlContext();
1179 if (!context) {
1180 QQmlEngine *qmlEngine = scope.engine->qmlEngine();
1181 if (qmlEngine)
1182 context = QQmlContextData::get(context: QQmlEnginePrivate::get(e: qmlEngine)->rootContext);
1183 }
1184 Q_ASSERT(context);
1185 QQmlContext *effectiveContext = nullptr;
1186 if (context->isPragmaLibraryContext)
1187 effectiveContext = engine->rootContext();
1188 else
1189 effectiveContext = context->asQQmlContext();
1190 Q_ASSERT(effectiveContext);
1191
1192 QString qml = argv[0].toQStringNoThrow();
1193 if (qml.isEmpty())
1194 RETURN_RESULT(Encode::null());
1195
1196 QUrl url;
1197 if (argc > 2)
1198 url = QUrl(argv[2].toQStringNoThrow());
1199 else
1200 url = QUrl(QLatin1String("inline"));
1201
1202 if (url.isValid() && url.isRelative())
1203 url = context->resolvedUrl(url);
1204
1205 QObject *parentArg = nullptr;
1206 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, argv[1]);
1207 if (!!qobjectWrapper)
1208 parentArg = qobjectWrapper->object();
1209 if (!parentArg)
1210 THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object");
1211
1212 QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(e: engine)->typeLoader.getType(
1213 qml.toUtf8(), url, mode: QQmlTypeLoader::Synchronous);
1214 Q_ASSERT(typeData->isCompleteOrError());
1215 QQmlComponent component(engine);
1216 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(c: &component);
1217 componentPrivate->fromTypeData(data: typeData);
1218 componentPrivate->progress = 1.0;
1219
1220 if (component.isError()) {
1221 ScopedValue v(scope, Error::create(v4: scope.engine, errors: component.errors()));
1222 RETURN_RESULT(scope.engine->throwError(v));
1223 }
1224
1225 if (!component.isReady())
1226 THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready");
1227
1228 if (!effectiveContext->isValid()) {
1229 THROW_GENERIC_ERROR("Qt.createQmlObject(): Cannot create a component in an invalid context");
1230 }
1231
1232 QObject *obj = component.beginCreate(effectiveContext);
1233 if (obj) {
1234 QQmlData::get(object: obj, create: true)->explicitIndestructibleSet = false;
1235 QQmlData::get(object: obj)->indestructible = false;
1236
1237
1238 obj->setParent(parentArg);
1239
1240 QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
1241 for (int ii = 0; ii < functions.count(); ++ii) {
1242 if (QQmlPrivate::Parented == functions.at(i: ii)(obj, parentArg))
1243 break;
1244 }
1245 }
1246 component.completeCreate();
1247
1248 if (component.isError()) {
1249 ScopedValue v(scope, Error::create(v4: scope.engine, errors: component.errors()));
1250 return scope.engine->throwError(value: v);
1251 }
1252
1253 Q_ASSERT(obj);
1254
1255 return QV4::QObjectWrapper::wrap(engine: scope.engine, object: obj);
1256}
1257
1258/*!
1259\qmlmethod object Qt::createComponent(url, mode, parent)
1260
1261Returns a \l Component object created using the QML file at the specified \a url,
1262or \c null if an empty string was given.
1263
1264The returned component's \l Component::status property indicates whether the
1265component was successfully created. If the status is \c Component.Error,
1266see \l Component::errorString() for an error description.
1267
1268If the optional \a mode parameter is set to \c Component.Asynchronous, the
1269component will be loaded in a background thread. The Component::status property
1270will be \c Component.Loading while it is loading. The status will change to
1271\c Component.Ready if the component loads successfully, or \c Component.Error
1272if loading fails. This parameter defaults to \c Component.PreferSynchronous
1273if omitted.
1274
1275If \a mode is set to \c Component.PreferSynchronous, Qt will attempt to load
1276the component synchronously, but may end up loading it asynchronously if
1277necessary. Scenarios that may cause asynchronous loading include, but are not
1278limited to, the following:
1279
1280\list
1281\li The URL refers to a network resource
1282\li The component is being created as a result of another component that is
1283being loaded asynchronously
1284\endlist
1285
1286If the optional \a parent parameter is given, it should refer to the object
1287that will become the parent for the created \l Component object. If no mode
1288was passed, this can be the second argument.
1289
1290Call \l {Component::createObject()}{Component.createObject()} on the returned
1291component to create an object instance of the component.
1292
1293For example:
1294
1295\snippet qml/createComponent-simple.qml 0
1296
1297See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
1298
1299To create a QML object from an arbitrary string of QML (instead of a file),
1300use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
1301*/
1302ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Value *, const Value *argv, int argc)
1303{
1304 QV4::Scope scope(b);
1305 if (argc < 1 || argc > 3)
1306 THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
1307
1308 QQmlEngine *engine = scope.engine->qmlEngine();
1309
1310 QQmlContextData *context = scope.engine->callingQmlContext();
1311 if (!context) {
1312 QQmlEngine *qmlEngine = scope.engine->qmlEngine();
1313 if (qmlEngine)
1314 context = QQmlContextData::get(context: QQmlEnginePrivate::get(e: qmlEngine)->rootContext);
1315 }
1316 Q_ASSERT(context);
1317 QQmlContextData *effectiveContext = context;
1318 if (context->isPragmaLibraryContext)
1319 effectiveContext = nullptr;
1320
1321 QString arg = argv[0].toQStringNoThrow();
1322 if (arg.isEmpty())
1323 RETURN_RESULT(QV4::Encode::null());
1324
1325 QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous;
1326 QObject *parentArg = nullptr;
1327
1328 int consumedCount = 1;
1329 if (argc > 1) {
1330 ScopedValue lastArg(scope, argv[argc-1]);
1331
1332 // The second argument could be the mode enum
1333 if (argv[1].isInteger()) {
1334 int mode = argv[1].integerValue();
1335 if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
1336 THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
1337 compileMode = QQmlComponent::CompilationMode(mode);
1338 consumedCount += 1;
1339 } else {
1340 // The second argument could be the parent only if there are exactly two args
1341 if ((argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
1342 THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
1343 }
1344
1345 if (consumedCount < argc) {
1346 if (lastArg->isObject()) {
1347 Scoped<QObjectWrapper> qobjectWrapper(scope, lastArg);
1348 if (qobjectWrapper)
1349 parentArg = qobjectWrapper->object();
1350 if (!parentArg)
1351 THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
1352 } else if (lastArg->isNull()) {
1353 parentArg = nullptr;
1354 } else {
1355 THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
1356 }
1357 }
1358 }
1359
1360 QUrl url = context->resolvedUrl(QUrl(arg));
1361 QQmlComponent *c = new QQmlComponent(engine, url, compileMode, parentArg);
1362 QQmlComponentPrivate::get(c)->creationContext = effectiveContext;
1363 QQmlData::get(object: c, create: true)->explicitIndestructibleSet = false;
1364 QQmlData::get(object: c)->indestructible = false;
1365
1366 return QV4::QObjectWrapper::wrap(engine: scope.engine, object: c);
1367}
1368
1369ReturnedValue QtObject::method_get_uiLanguage(const FunctionObject *b, const Value * /*thisObject*/, const Value * /*argv*/, int /*argc*/)
1370{
1371 QV4::Scope scope(b);
1372 QJSEngine *jsEngine = scope.engine->jsEngine();
1373 if (!jsEngine)
1374 return Encode::null();
1375
1376 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(e: scope.engine);
1377 if (ep && ep->propertyCapture) {
1378 static int propertyIndex = -1;
1379 static int notifySignalIndex = -1;
1380 if (propertyIndex < 0) {
1381 QMetaProperty metaProperty =
1382 QQmlEngine::staticMetaObject.property(index: QQmlEngine::staticMetaObject.indexOfProperty(name: "uiLanguage"));
1383 propertyIndex = metaProperty.propertyIndex();
1384 notifySignalIndex = metaProperty.notifySignalIndex();
1385 }
1386 ep->propertyCapture->captureProperty(QQmlEnginePrivate::get(p: ep), propertyIndex, notifySignalIndex);
1387 }
1388
1389 return Encode(scope.engine->newString(s: QJSEnginePrivate::get(e: jsEngine)->uiLanguage));
1390}
1391
1392ReturnedValue QtObject::method_set_uiLanguage(const FunctionObject *b, const Value * /*thisObject*/, const Value *argv, int argc)
1393{
1394 Scope scope(b);
1395 if (!argc)
1396 THROW_TYPE_ERROR();
1397 QJSEngine *jsEngine = scope.engine->jsEngine();
1398 if (!jsEngine)
1399 THROW_TYPE_ERROR();
1400 jsEngine->setUiLanguage(argv[0].toQString());
1401 return Encode::undefined();
1402}
1403
1404#if QT_CONFIG(qml_locale)
1405/*!
1406 \qmlmethod Qt::locale(name)
1407
1408 Returns a JS object representing the locale with the specified
1409 \a name, which has the format "language[_territory][.codeset][@modifier]"
1410 or "C", where:
1411
1412 \list
1413 \li \c language is a lowercase, two-letter, ISO 639 language code,
1414 \li \c territory is an uppercase, two-letter, ISO 3166 country code, and
1415 \li \c codeset and \c modifier are ignored.
1416 \endlist
1417
1418 If the string violates the locale format, or language is not a
1419 valid ISO 369 code, the "C" locale is used instead. If country
1420 is not present, or is not a valid ISO 3166 code, the most
1421 appropriate country is chosen for the specified language.
1422
1423 \sa Locale
1424*/
1425ReturnedValue QtObject::method_locale(const FunctionObject *b, const Value *, const Value *argv, int argc)
1426{
1427 QV4::Scope scope(b);
1428 QString code;
1429 if (argc > 1)
1430 THROW_GENERIC_ERROR("locale() requires 0 or 1 argument");
1431 if (argc == 1 && !argv[0].isString())
1432 THROW_TYPE_ERROR_WITH_MESSAGE("locale(): argument (locale code) must be a string");
1433
1434 if (argc == 1)
1435 code = argv[0].toQStringNoThrow();
1436
1437 return QQmlLocale::locale(engine: scope.engine, localeName: code);
1438}
1439#endif
1440
1441void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *bindingFunction)
1442{
1443 Scope scope(bindingFunction->engine());
1444 ScopedContext context(scope, bindingFunction->scope());
1445 FunctionObject::init(scope: context, function: bindingFunction->function());
1446 this->bindingFunction.set(e: internalClass->engine, newVal: bindingFunction->d());
1447}
1448
1449QQmlSourceLocation QQmlBindingFunction::currentLocation() const
1450{
1451 QV4::CppStackFrame *frame = engine()->currentStackFrame;
1452 if (frame->v4Function) // synchronous loading:
1453 return QQmlSourceLocation(frame->source(), frame->lineNumber(), 0);
1454 else // async loading:
1455 return bindingFunction()->function->sourceLocation();
1456}
1457
1458DEFINE_OBJECT_VTABLE(QQmlBindingFunction);
1459
1460/*!
1461 \qmlmethod Qt::binding(function)
1462
1463 Returns a JavaScript object representing a \l{Property Binding}{property binding},
1464 with a \a function that evaluates the binding.
1465
1466 There are two main use-cases for the function: firstly, to apply a
1467 property binding imperatively from JavaScript code:
1468
1469 \snippet qml/qtBinding.1.qml 0
1470
1471 and secondly, to apply a property binding when initializing property values
1472 of dynamically constructed objects (via \l{Component::createObject()}
1473 {Component.createObject()} or \l{Loader::setSource()}{Loader.setSource()}).
1474
1475 For example, assuming the existence of a DynamicText component:
1476 \snippet qml/DynamicText.qml 0
1477
1478 the output from:
1479 \snippet qml/qtBinding.2.qml 0
1480
1481 and from:
1482 \snippet qml/qtBinding.3.qml 0
1483
1484 should both be:
1485 \code
1486 Root text extra text
1487 Modified root text extra text
1488 Dynamic text extra text
1489 Modified dynamic text extra text
1490 \endcode
1491
1492 This function cannot be used in property binding declarations
1493 (see the documentation on \l{qml-javascript-assignment}{binding
1494 declarations and binding assignments}) except when the result is
1495 stored in an array bound to a var property.
1496
1497 \snippet qml/qtBinding.4.qml 0
1498
1499 \since 5.0
1500*/
1501ReturnedValue QtObject::method_binding(const FunctionObject *b, const Value *, const Value *argv, int argc)
1502{
1503 QV4::Scope scope(b);
1504 if (argc != 1)
1505 THROW_GENERIC_ERROR("binding() requires 1 argument");
1506 const QV4::FunctionObject *f = argv[0].as<FunctionObject>();
1507 if (!f)
1508 THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function");
1509
1510 return Encode(scope.engine->memoryManager->allocate<QQmlBindingFunction>(args: f));
1511}
1512
1513
1514ReturnedValue QtObject::method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *, int)
1515{
1516 QV4::Scope scope(b);
1517 // ### inefficient. Should be just a value based getter
1518 const Object *o = thisObject->as<Object>();
1519 if (!o)
1520 THROW_TYPE_ERROR();
1521 const QtObject *qt = o->as<QtObject>();
1522 if (!qt)
1523 THROW_TYPE_ERROR();
1524
1525 if (!qt->d()->platform)
1526 // Only allocate a platform object once
1527 qt->d()->platform = new QQmlPlatform(scope.engine->jsEngine());
1528
1529 return QV4::QObjectWrapper::wrap(engine: scope.engine, object: qt->d()->platform);
1530}
1531
1532ReturnedValue QtObject::method_get_application(const FunctionObject *b, const Value *thisObject, const Value *, int)
1533{
1534 QV4::Scope scope(b);
1535 // ### inefficient. Should be just a value based getter
1536 const Object *o = thisObject->as<Object>();
1537 if (!o)
1538 THROW_TYPE_ERROR();
1539 const QtObject *qt = o->as<QtObject>();
1540 if (!qt)
1541 THROW_TYPE_ERROR();
1542
1543 if (!qt->d()->application)
1544 // Only allocate an application object once
1545 qt->d()->application = QQml_guiProvider()->application(parent: scope.engine->jsEngine());
1546
1547 return QV4::QObjectWrapper::wrap(engine: scope.engine, object: qt->d()->application);
1548}
1549
1550ReturnedValue QtObject::method_get_inputMethod(const FunctionObject *b, const Value *, const Value *, int)
1551{
1552 QObject *o = QQml_guiProvider()->inputMethod();
1553 return QV4::QObjectWrapper::wrap(engine: b->engine(), object: o);
1554}
1555
1556ReturnedValue QtObject::method_get_styleHints(const FunctionObject *b, const Value *, const Value *, int)
1557{
1558 QObject *o = QQml_guiProvider()->styleHints();
1559 return QV4::QObjectWrapper::wrap(engine: b->engine(), object: o);
1560}
1561
1562
1563void QV4::Heap::ConsoleObject::init()
1564{
1565 Object::init();
1566 QV4::Scope scope(internalClass->engine);
1567 QV4::ScopedObject o(scope, this);
1568
1569 o->defineDefaultProperty(QStringLiteral("debug"), code: QV4::ConsoleObject::method_log);
1570 o->defineDefaultProperty(QStringLiteral("log"), code: QV4::ConsoleObject::method_log);
1571 o->defineDefaultProperty(QStringLiteral("info"), code: QV4::ConsoleObject::method_info);
1572 o->defineDefaultProperty(QStringLiteral("warn"), code: QV4::ConsoleObject::method_warn);
1573 o->defineDefaultProperty(QStringLiteral("error"), code: QV4::ConsoleObject::method_error);
1574 o->defineDefaultProperty(QStringLiteral("assert"), code: QV4::ConsoleObject::method_assert);
1575
1576 o->defineDefaultProperty(QStringLiteral("count"), code: QV4::ConsoleObject::method_count);
1577 o->defineDefaultProperty(QStringLiteral("profile"), code: QV4::ConsoleObject::method_profile);
1578 o->defineDefaultProperty(QStringLiteral("profileEnd"), code: QV4::ConsoleObject::method_profileEnd);
1579 o->defineDefaultProperty(QStringLiteral("time"), code: QV4::ConsoleObject::method_time);
1580 o->defineDefaultProperty(QStringLiteral("timeEnd"), code: QV4::ConsoleObject::method_timeEnd);
1581 o->defineDefaultProperty(QStringLiteral("trace"), code: QV4::ConsoleObject::method_trace);
1582 o->defineDefaultProperty(QStringLiteral("exception"), code: QV4::ConsoleObject::method_exception);
1583}
1584
1585
1586enum ConsoleLogTypes {
1587 Log,
1588 Info,
1589 Warn,
1590 Error
1591};
1592
1593static QString jsStack(QV4::ExecutionEngine *engine) {
1594 QString stack;
1595
1596 QVector<QV4::StackFrame> stackTrace = engine->stackTrace(frameLimit: 10);
1597
1598 for (int i = 0; i < stackTrace.count(); i++) {
1599 const QV4::StackFrame &frame = stackTrace.at(i);
1600
1601 QString stackFrame;
1602 if (frame.column >= 0)
1603 stackFrame = QStringLiteral("%1 (%2:%3:%4)").arg(args: frame.function,
1604 args: frame.source,
1605 args: QString::number(frame.line),
1606 args: QString::number(frame.column));
1607 else
1608 stackFrame = QStringLiteral("%1 (%2:%3)").arg(args: frame.function,
1609 args: frame.source,
1610 args: QString::number(frame.line));
1611
1612 if (i)
1613 stack += QLatin1Char('\n');
1614 stack += stackFrame;
1615 }
1616 return stack;
1617}
1618
1619static QString serializeArray(Object *array, ExecutionEngine *v4, QSet<QV4::Heap::Object *> &alreadySeen) {
1620 Scope scope(v4);
1621 ScopedValue val(scope);
1622 QString result;
1623
1624 alreadySeen.insert(value: array->d());
1625 result += QLatin1Char('[');
1626 const uint length = array->getLength();
1627 for (uint i = 0; i < length; ++i) {
1628 if (i != 0)
1629 result += QLatin1Char(',');
1630 val = array->get(idx: i);
1631 if (val->isManaged() && val->managed()->isArrayLike())
1632 if (!alreadySeen.contains(value: val->objectValue()->d()))
1633 result += serializeArray(array: val->objectValue(), v4, alreadySeen);
1634 else
1635 result += QLatin1String("[Circular]");
1636 else
1637 result += val->toQStringNoThrow();
1638 }
1639 result += QLatin1Char(']');
1640 alreadySeen.remove(value: array->d());
1641 return result;
1642};
1643
1644static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, const Value *argv, int argc,
1645 ConsoleLogTypes logType, bool printStack = false)
1646{
1647 QLoggingCategory *loggingCategory = nullptr;
1648 QString result;
1649 QV4::Scope scope(b);
1650 QV4::ExecutionEngine *v4 = scope.engine;
1651
1652 int start = 0;
1653 if (argc > 0) {
1654 if (const QObjectWrapper* wrapper = argv[0].as<QObjectWrapper>()) {
1655 if (QQmlLoggingCategory* category = qobject_cast<QQmlLoggingCategory*>(object: wrapper->object())) {
1656 if (category->category())
1657 loggingCategory = category->category();
1658 else
1659 THROW_GENERIC_ERROR("A QmlLoggingCatgory was provided without a valid name");
1660 start = 1;
1661 }
1662 }
1663 }
1664
1665
1666 for (int i = start, ei = argc; i < ei; ++i) {
1667 if (i != start)
1668 result.append(c: QLatin1Char(' '));
1669
1670 QSet<QV4::Heap::Object *> alreadySeenElements;
1671 if (argv[i].isManaged() && argv[i].managed()->isArrayLike())
1672 result.append(s: serializeArray(array: argv[i].objectValue(), v4, alreadySeen&: alreadySeenElements));
1673 else
1674 result.append(s: argv[i].toQStringNoThrow());
1675 }
1676
1677 if (printStack)
1678 result += QLatin1Char('\n') + jsStack(engine: v4);
1679
1680 static QLoggingCategory qmlLoggingCategory("qml");
1681 static QLoggingCategory jsLoggingCategory("js");
1682
1683 if (!loggingCategory)
1684 loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
1685 QV4::CppStackFrame *frame = v4->currentStackFrame;
1686 const QByteArray baSource = frame->source().toUtf8();
1687 const QByteArray baFunction = frame->function().toUtf8();
1688 QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData(), loggingCategory->categoryName());
1689
1690 switch (logType) {
1691 case Log:
1692 if (loggingCategory->isDebugEnabled())
1693 logger.debug(msg: "%s", result.toUtf8().constData());
1694 break;
1695 case Info:
1696 if (loggingCategory->isInfoEnabled())
1697 logger.info(msg: "%s", result.toUtf8().constData());
1698 break;
1699 case Warn:
1700 if (loggingCategory->isWarningEnabled())
1701 logger.warning(msg: "%s", result.toUtf8().constData());
1702 break;
1703 case Error:
1704 if (loggingCategory->isCriticalEnabled())
1705 logger.critical(msg: "%s", result.toUtf8().constData());
1706 break;
1707 default:
1708 break;
1709 }
1710
1711 return Encode::undefined();
1712}
1713
1714DEFINE_OBJECT_VTABLE(ConsoleObject);
1715
1716ReturnedValue ConsoleObject::method_error(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1717{
1718 return writeToConsole(b, thisObject, argv, argc, logType: Error);
1719}
1720
1721ReturnedValue ConsoleObject::method_log(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1722{
1723 //console.log
1724 //console.debug
1725 //print
1726 return writeToConsole(b, thisObject, argv, argc, logType: Log);
1727}
1728
1729ReturnedValue ConsoleObject::method_info(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1730{
1731 return writeToConsole(b, thisObject, argv, argc, logType: Info);
1732}
1733
1734ReturnedValue ConsoleObject::method_profile(const FunctionObject *b, const Value *, const Value *, int)
1735{
1736 QV4::Scope scope(b);
1737 QV4::ExecutionEngine *v4 = scope.engine;
1738
1739 QV4::CppStackFrame *frame = v4->currentStackFrame;
1740 const QByteArray baSource = frame->source().toUtf8();
1741 const QByteArray baFunction = frame->function().toUtf8();
1742 QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData());
1743 QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
1744 if (!service) {
1745 logger.warning(msg: "Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
1746 } else {
1747 service->startProfiling(engine: v4->jsEngine());
1748 logger.debug(msg: "Profiling started.");
1749 }
1750
1751 return QV4::Encode::undefined();
1752}
1753
1754ReturnedValue ConsoleObject::method_profileEnd(const FunctionObject *b, const Value *, const Value *, int)
1755{
1756 QV4::Scope scope(b);
1757 QV4::ExecutionEngine *v4 = scope.engine;
1758
1759 QV4::CppStackFrame *frame = v4->currentStackFrame;
1760 const QByteArray baSource = frame->source().toUtf8();
1761 const QByteArray baFunction = frame->function().toUtf8();
1762 QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData());
1763
1764 QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
1765 if (!service) {
1766 logger.warning(msg: "Ignoring console.profileEnd(): the debug service is disabled.");
1767 } else {
1768 service->stopProfiling(engine: v4->jsEngine());
1769 logger.debug(msg: "Profiling ended.");
1770 }
1771
1772 return QV4::Encode::undefined();
1773}
1774
1775ReturnedValue ConsoleObject::method_time(const FunctionObject *b, const Value *, const Value *argv, int argc)
1776{
1777 QV4::Scope scope(b);
1778 if (argc != 1)
1779 THROW_GENERIC_ERROR("console.time(): Invalid arguments");
1780
1781 QString name = argv[0].toQStringNoThrow();
1782 scope.engine->startTimer(timerName: name);
1783 return QV4::Encode::undefined();
1784}
1785
1786ReturnedValue ConsoleObject::method_timeEnd(const FunctionObject *b, const Value *, const Value *argv, int argc)
1787{
1788 QV4::Scope scope(b);
1789 if (argc != 1)
1790 THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments");
1791
1792 QString name = argv[0].toQStringNoThrow();
1793 bool wasRunning;
1794 qint64 elapsed = scope.engine->stopTimer(timerName: name, wasRunning: &wasRunning);
1795 if (wasRunning) {
1796 qDebug(msg: "%s: %llims", qPrintable(name), elapsed);
1797 }
1798 return QV4::Encode::undefined();
1799}
1800
1801ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value *, const Value *argv, int argc)
1802{
1803 // first argument: name to print. Ignore any additional arguments
1804 QString name;
1805 if (argc > 0)
1806 name = argv[0].toQStringNoThrow();
1807
1808 Scope scope(b);
1809 QV4::ExecutionEngine *v4 = scope.engine;
1810
1811 QV4::CppStackFrame *frame = v4->currentStackFrame;
1812
1813 QString scriptName = frame->source();
1814
1815 int value = v4->consoleCountHelper(file: scriptName, line: frame->lineNumber(), column: 0);
1816 QString message = name + QLatin1String(": ") + QString::number(value);
1817
1818 QMessageLogger(qPrintable(scriptName), frame->lineNumber(),
1819 qPrintable(frame->function()))
1820 .debug(msg: "%s", qPrintable(message));
1821
1822 return QV4::Encode::undefined();
1823}
1824
1825ReturnedValue ConsoleObject::method_trace(const FunctionObject *b, const Value *, const Value *, int argc)
1826{
1827 QV4::Scope scope(b);
1828 if (argc != 0)
1829 THROW_GENERIC_ERROR("console.trace(): Invalid arguments");
1830
1831 QV4::ExecutionEngine *v4 = scope.engine;
1832
1833 QString stack = jsStack(engine: v4);
1834
1835 QV4::CppStackFrame *frame = v4->currentStackFrame;
1836 QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(),
1837 frame->function().toUtf8().constData())
1838 .debug(msg: "%s", qPrintable(stack));
1839
1840 return QV4::Encode::undefined();
1841}
1842
1843ReturnedValue ConsoleObject::method_warn(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1844{
1845 return writeToConsole(b, thisObject, argv, argc, logType: Warn);
1846}
1847
1848ReturnedValue ConsoleObject::method_assert(const FunctionObject *b, const Value *, const Value *argv, int argc)
1849{
1850 QV4::Scope scope(b);
1851 if (argc == 0)
1852 THROW_GENERIC_ERROR("console.assert(): Missing argument");
1853
1854 QV4::ExecutionEngine *v4 = scope.engine;
1855
1856 if (!argv[0].toBoolean()) {
1857 QString message;
1858 for (int i = 1, ei = argc; i < ei; ++i) {
1859 if (i != 1)
1860 message.append(c: QLatin1Char(' '));
1861
1862 message.append(s: argv[i].toQStringNoThrow());
1863 }
1864
1865 QString stack = jsStack(engine: v4);
1866
1867 QV4::CppStackFrame *frame = v4->currentStackFrame;
1868 QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(),
1869 frame->function().toUtf8().constData())
1870 .critical(msg: "%s\n%s",qPrintable(message), qPrintable(stack));
1871
1872 }
1873 return QV4::Encode::undefined();
1874}
1875
1876ReturnedValue ConsoleObject::method_exception(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1877{
1878 QV4::Scope scope(b);
1879 if (argc == 0)
1880 THROW_GENERIC_ERROR("console.exception(): Missing argument");
1881
1882 return writeToConsole(b, thisObject, argv, argc, logType: Error, printStack: true);
1883}
1884
1885
1886
1887void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions extensions)
1888{
1889 ExecutionEngine *v4 = globalObject->engine();
1890 Scope scope(v4);
1891
1892 if (extensions.testFlag(flag: QJSEngine::TranslationExtension)) {
1893 #if QT_CONFIG(translation)
1894 globalObject->defineDefaultProperty(QStringLiteral("qsTranslate"), code: QV4::GlobalExtensions::method_qsTranslate);
1895 globalObject->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), code: QV4::GlobalExtensions::method_qsTranslateNoOp);
1896 globalObject->defineDefaultProperty(QStringLiteral("qsTr"), code: QV4::GlobalExtensions::method_qsTr);
1897 globalObject->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), code: QV4::GlobalExtensions::method_qsTrNoOp);
1898 globalObject->defineDefaultProperty(QStringLiteral("qsTrId"), code: QV4::GlobalExtensions::method_qsTrId);
1899 globalObject->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), code: QV4::GlobalExtensions::method_qsTrIdNoOp);
1900
1901 ScopedString qtName(scope, v4->newString(QStringLiteral("Qt")));
1902 ScopedObject qt(scope, globalObject->get(name: qtName));
1903 if (!qt) {
1904 qt = v4->newObject();
1905 globalObject->defineDefaultProperty(name: qtName, value: qt);
1906 }
1907 qt->defineAccessorProperty(QStringLiteral("uiLanguage"), getter: QV4::QtObject::method_get_uiLanguage, setter: QV4::QtObject::method_set_uiLanguage);
1908
1909 // string prototype extension
1910 scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), code: QV4::GlobalExtensions::method_string_arg);
1911 #endif
1912 }
1913
1914 if (extensions.testFlag(flag: QJSEngine::ConsoleExtension)) {
1915 globalObject->defineDefaultProperty(QStringLiteral("print"), code: QV4::ConsoleObject::method_log);
1916
1917
1918 QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocate<QV4::ConsoleObject>());
1919 globalObject->defineDefaultProperty(QStringLiteral("console"), value: console);
1920 }
1921
1922 if (extensions.testFlag(flag: QJSEngine::GarbageCollectionExtension)) {
1923 globalObject->defineDefaultProperty(QStringLiteral("gc"), code: QV4::GlobalExtensions::method_gc);
1924 }
1925}
1926
1927
1928#if QT_CONFIG(translation)
1929/*!
1930 \qmlmethod string Qt::qsTranslate(string context, string sourceText, string disambiguation, int n)
1931
1932 Returns a translated version of \a sourceText within the given \a context, optionally based on a
1933 \a disambiguation string and value of \a n for strings containing plurals;
1934 otherwise returns \a sourceText itself if no appropriate translated string
1935 is available.
1936
1937 If the same \a sourceText is used in different roles within the
1938 same translation \a context, an additional identifying string may be passed in
1939 for \a disambiguation.
1940
1941 Example:
1942 \snippet qml/qsTranslate.qml 0
1943
1944 \sa {Internationalization and Localization with Qt Quick}
1945*/
1946ReturnedValue GlobalExtensions::method_qsTranslate(const FunctionObject *b, const Value *, const Value *argv, int argc)
1947{
1948 QV4::Scope scope(b);
1949 if (argc < 2)
1950 THROW_GENERIC_ERROR("qsTranslate() requires at least two arguments");
1951 if (!argv[0].isString())
1952 THROW_GENERIC_ERROR("qsTranslate(): first argument (context) must be a string");
1953 if (!argv[1].isString())
1954 THROW_GENERIC_ERROR("qsTranslate(): second argument (sourceText) must be a string");
1955 if ((argc > 2) && !argv[2].isString())
1956 THROW_GENERIC_ERROR("qsTranslate(): third argument (disambiguation) must be a string");
1957
1958 QString context = argv[0].toQStringNoThrow();
1959 QString text = argv[1].toQStringNoThrow();
1960 QString comment;
1961 if (argc > 2) comment = argv[2].toQStringNoThrow();
1962
1963 int i = 3;
1964 if (argc > i && argv[i].isString()) {
1965 qWarning(msg: "qsTranslate(): specifying the encoding as fourth argument is deprecated");
1966 ++i;
1967 }
1968
1969 int n = -1;
1970 if (argc > i)
1971 n = argv[i].toInt32();
1972
1973 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(e: scope.engine->qmlEngine()) : nullptr))
1974 if (ep->propertyCapture)
1975 ep->propertyCapture->captureTranslation();
1976
1977 QString result = QCoreApplication::translate(context: context.toUtf8().constData(),
1978 key: text.toUtf8().constData(),
1979 disambiguation: comment.toUtf8().constData(),
1980 n);
1981
1982 return Encode(scope.engine->newString(s: result));
1983}
1984
1985/*!
1986 \qmlmethod string Qt::qsTranslateNoOp(string context, string sourceText, string disambiguation)
1987
1988 Marks \a sourceText for dynamic translation in the given \a context; i.e, the stored \a sourceText
1989 will not be altered.
1990
1991 If the same \a sourceText is used in different roles within the
1992 same translation context, an additional identifying string may be passed in
1993 for \a disambiguation.
1994
1995 Returns the \a sourceText.
1996
1997 QT_TRANSLATE_NOOP is used in conjunction with the dynamic translation functions
1998 qsTr() and qsTranslate(). It identifies a string as requiring
1999 translation (so it can be identified by \c lupdate), but leaves the actual
2000 translation to the dynamic functions.
2001
2002 Example:
2003 \snippet qml/qtTranslateNoOp.qml 0
2004
2005 \sa {Internationalization and Localization with Qt Quick}
2006*/
2007ReturnedValue GlobalExtensions::method_qsTranslateNoOp(const FunctionObject *b, const Value *, const Value *argv, int argc)
2008{
2009 QV4::Scope scope(b);
2010 if (argc < 2)
2011 return QV4::Encode::undefined();
2012 else
2013 return argv[1].asReturnedValue();
2014}
2015
2016/*!
2017 \qmlmethod string Qt::qsTr(string sourceText, string disambiguation, int n)
2018
2019 Returns a translated version of \a sourceText, optionally based on a
2020 \a disambiguation string and value of \a n for strings containing plurals;
2021 otherwise returns \a sourceText itself if no appropriate translated string
2022 is available.
2023
2024 If the same \a sourceText is used in different roles within the
2025 same translation context, an additional identifying string may be passed in
2026 for \a disambiguation.
2027
2028 Example:
2029 \snippet qml/qsTr.qml 0
2030
2031 \sa {Internationalization and Localization with Qt Quick}
2032*/
2033ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value *, const Value *argv, int argc)
2034{
2035 QV4::Scope scope(b);
2036 if (argc < 1)
2037 THROW_GENERIC_ERROR("qsTr() requires at least one argument");
2038 if (!argv[0].isString())
2039 THROW_GENERIC_ERROR("qsTr(): first argument (sourceText) must be a string");
2040 if ((argc > 1) && !argv[1].isString())
2041 THROW_GENERIC_ERROR("qsTr(): second argument (disambiguation) must be a string");
2042 if ((argc > 2) && !argv[2].isNumber())
2043 THROW_GENERIC_ERROR("qsTr(): third argument (n) must be a number");
2044
2045 QString context;
2046 CppStackFrame *frame = scope.engine->currentStackFrame;
2047 // The first non-empty source URL in the call stack determines the translation context.
2048 while (frame && context.isEmpty()) {
2049 if (CompiledData::CompilationUnitBase *baseUnit = frame->v4Function->compilationUnit) {
2050 const auto *unit = static_cast<const CompiledData::CompilationUnit *>(baseUnit);
2051 QString fileName = unit->fileName();
2052 QUrl url(unit->fileName());
2053 if (url.isValid() && url.isRelative()) {
2054 context = url.fileName();
2055 } else {
2056 context = QQmlFile::urlToLocalFileOrQrc(fileName);
2057 if (context.isEmpty() && fileName.startsWith(s: QLatin1String(":/")))
2058 context = fileName;
2059 }
2060 context = QFileInfo(context).baseName();
2061 }
2062 frame = frame->parent;
2063 }
2064
2065 if (context.isEmpty()) {
2066 if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
2067 QString path = ctxt->urlString();
2068 int lastSlash = path.lastIndexOf(c: QLatin1Char('/'));
2069 int lastDot = path.lastIndexOf(c: QLatin1Char('.'));
2070 int length = lastDot - (lastSlash + 1);
2071 context = (lastSlash > -1) ? path.mid(position: lastSlash + 1, n: (length > -1) ? length : -1) : QString();
2072 }
2073 }
2074
2075 QString text = argv[0].toQStringNoThrow();
2076 QString comment;
2077 if (argc > 1)
2078 comment = argv[1].toQStringNoThrow();
2079 int n = -1;
2080 if (argc > 2)
2081 n = argv[2].toInt32();
2082
2083 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(e: scope.engine->qmlEngine()) : nullptr))
2084 if (ep->propertyCapture)
2085 ep->propertyCapture->captureTranslation();
2086
2087 QString result = QCoreApplication::translate(context: context.toUtf8().constData(), key: text.toUtf8().constData(),
2088 disambiguation: comment.toUtf8().constData(), n);
2089
2090 return Encode(scope.engine->newString(s: result));
2091}
2092
2093/*!
2094 \qmlmethod string Qt::qsTrNoOp(string sourceText, string disambiguation)
2095
2096 Marks \a sourceText for dynamic translation; i.e, the stored \a sourceText
2097 will not be altered.
2098
2099 If the same \a sourceText is used in different roles within the
2100 same translation context, an additional identifying string may be passed in
2101 for \a disambiguation.
2102
2103 Returns the \a sourceText.
2104
2105 QT_TR_NOOP is used in conjunction with the dynamic translation functions
2106 qsTr() and qsTranslate(). It identifies a string as requiring
2107 translation (so it can be identified by \c lupdate), but leaves the actual
2108 translation to the dynamic functions.
2109
2110 Example:
2111 \snippet qml/qtTrNoOp.qml 0
2112
2113 \sa {Internationalization and Localization with Qt Quick}
2114*/
2115ReturnedValue GlobalExtensions::method_qsTrNoOp(const FunctionObject *, const Value *, const Value *argv, int argc)
2116{
2117 if (argc < 1)
2118 return QV4::Encode::undefined();
2119 else
2120 return argv[0].asReturnedValue();
2121}
2122
2123/*!
2124 \qmlmethod string Qt::qsTrId(string id, int n)
2125
2126 Returns a translated string identified by \a id.
2127 If no matching string is found, the id itself is returned. This
2128 should not happen under normal conditions.
2129
2130 If \a n >= 0, all occurrences of \c %n in the resulting string
2131 are replaced with a decimal representation of \a n. In addition,
2132 depending on \a n's value, the translation text may vary.
2133
2134 Example:
2135 \snippet qml/qsTrId.qml 0
2136
2137 It is possible to supply a source string template like:
2138
2139 \tt{//% <string>}
2140
2141 or
2142
2143 \tt{\\begincomment% <string> \\endcomment}
2144
2145 Example:
2146 \snippet qml/qsTrId.1.qml 0
2147
2148 Creating binary translation (QM) files suitable for use with this function requires passing
2149 the \c -idbased option to the \c lrelease tool.
2150
2151 \sa QT_TRID_NOOP(), {Internationalization and Localization with Qt Quick}
2152*/
2153ReturnedValue GlobalExtensions::method_qsTrId(const FunctionObject *b, const Value *, const Value *argv, int argc)
2154{
2155 QV4::Scope scope(b);
2156 if (argc < 1)
2157 THROW_GENERIC_ERROR("qsTrId() requires at least one argument");
2158 if (!argv[0].isString())
2159 THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): first argument (id) must be a string");
2160 if (argc > 1 && !argv[1].isNumber())
2161 THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): second argument (n) must be a number");
2162
2163 int n = -1;
2164 if (argc > 1)
2165 n = argv[1].toInt32();
2166
2167 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(e: scope.engine->qmlEngine()) : nullptr))
2168 if (ep->propertyCapture)
2169 ep->propertyCapture->captureTranslation();
2170
2171 return Encode(scope.engine->newString(s: qtTrId(id: argv[0].toQStringNoThrow().toUtf8().constData(), n)));
2172}
2173
2174/*!
2175 \qmlmethod string Qt::qsTrIdNoOp(string id)
2176
2177 Marks \a id for dynamic translation.
2178
2179 Returns the \a id.
2180
2181 QT_TRID_NOOP is used in conjunction with the dynamic translation function
2182 qsTrId(). It identifies a string as requiring translation (so it can be identified
2183 by \c lupdate), but leaves the actual translation to qsTrId().
2184
2185 Example:
2186 \snippet qml/qtTrIdNoOp.qml 0
2187
2188 \sa qsTrId(), {Internationalization and Localization with Qt Quick}
2189*/
2190ReturnedValue GlobalExtensions::method_qsTrIdNoOp(const FunctionObject *, const Value *, const Value *argv, int argc)
2191{
2192 if (argc < 1)
2193 return QV4::Encode::undefined();
2194 else
2195 return argv[0].asReturnedValue();
2196}
2197#endif // translation
2198
2199
2200ReturnedValue GlobalExtensions::method_gc(const FunctionObject *b, const Value *, const Value *, int)
2201{
2202 b->engine()->memoryManager->runGC();
2203
2204 return QV4::Encode::undefined();
2205}
2206
2207
2208
2209ReturnedValue GlobalExtensions::method_string_arg(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
2210{
2211 QV4::Scope scope(b);
2212 if (argc != 1)
2213 THROW_GENERIC_ERROR("String.arg(): Invalid arguments");
2214
2215 QString value = thisObject->toQString();
2216
2217 QV4::ScopedValue arg(scope, argv[0]);
2218 if (arg->isInteger())
2219 RETURN_RESULT(scope.engine->newString(value.arg(arg->integerValue())));
2220 else if (arg->isDouble())
2221 RETURN_RESULT(scope.engine->newString(value.arg(arg->doubleValue())));
2222 else if (arg->isBoolean())
2223 RETURN_RESULT(scope.engine->newString(value.arg(arg->booleanValue())));
2224
2225 RETURN_RESULT(scope.engine->newString(value.arg(arg->toQString())));
2226}
2227
2228/*!
2229\qmlmethod Qt::callLater(function)
2230\qmlmethod Qt::callLater(function, argument1, argument2, ...)
2231\since 5.8
2232Use this function to eliminate redundant calls to a function or signal.
2233
2234The function passed as the first argument to Qt.callLater()
2235will be called later, once the QML engine returns to the event loop.
2236
2237When this function is called multiple times in quick succession with the
2238same function as its first argument, that function will be called only once.
2239
2240For example:
2241\snippet qml/qtLater.qml 0
2242
2243Any additional arguments passed to Qt.callLater() will
2244be passed on to the function invoked. Note that if redundant calls
2245are eliminated, then only the last set of arguments will be passed to the
2246function.
2247*/
2248ReturnedValue QtObject::method_callLater(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
2249{
2250 return b->engine()->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
2251}
2252
2253QT_END_NAMESPACE
2254
2255

source code of qtdeclarative/src/qml/qml/v8/qqmlbuiltinfunctions.cpp