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

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