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