Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qdeclarativebuiltinfunctions.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativebuiltinfunctions_p.h"
43
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <private/qdeclarativeengine_p.h>
46 #include <private/qdeclarativecomponent_p.h>
47 #include <private/qdeclarativestringconverters_p.h>
48 #include <private/qdeclarativelocale_p.h>
49 #include <private/qv8engine_p.h>
50
51 #include <private/qv8profilerservice_p.h>
52 #include <private/qdeclarativedebugtrace_p.h>
53
54 #include <QtCore/qstring.h>
55 #include <QtCore/qdatetime.h>
56 #include <QtCore/qcryptographichash.h>
57 #include <QtCore/qrect.h>
58 #include <QtCore/qsize.h>
59 #include <QtCore/qpoint.h>
60 #include <QtCore/qurl.h>
61 #include <QtCore/qfile.h>
62 #include <QtCore/qcoreapplication.h>
63
64 #include <QtGui/qcolor.h>
65 #include <QtGui/qvector3d.h>
66 #include <QtGui/qvector4d.h>
67 #include <QtGui/qdesktopservices.h>
68 #include <QtGui/qfontdatabase.h>
69
70 QT_BEGIN_NAMESPACE
71
72 // send more information such as file, line etc for console APIs
73 DEFINE_BOOL_CONFIG_OPTION(qmlConsoleExtended, QML_CONSOLE_EXTENDED)
74
75 namespace QDeclarativeBuiltinFunctions {
76
77 enum ConsoleLogTypes {
78     Log,
79     Warn,
80     Error
81 };
82
83 static QString extendMessage(const QString &msg) {
84     if (qmlConsoleExtended()) {
85         v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1);
86         if (stackTrace->GetFrameCount()) {
87             v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
88             int line = frame->GetLineNumber();
89             QString scriptName = QString::fromUtf16(*v8::String::Value(frame->GetScriptName()));
90
91             return QString::fromLatin1("%1 (%2:%3)").arg(msg).arg(scriptName).arg(line);
92         }
93     }
94     return msg;
95 }
96
97 static void printStack() {
98     //The v8 default is currently 10 stack frames.
99     v8::Handle<v8::StackTrace> stackTrace =
100         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
101     int stackCount = stackTrace->GetFrameCount();
102
103     for (int i = 0; i < stackCount; i++) {
104         v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(i);
105         v8::String::Utf8Value func_name(frame->GetFunctionName());
106         v8::String::Utf8Value script_name(frame->GetScriptName());
107         int lineNumber = frame->GetLineNumber();
108         int columnNumber = frame->GetColumn();
109         qDebug("%s (%s:%d:%d)\n", *func_name, *script_name, lineNumber, columnNumber);
110     }
111 }
112
113 v8::Handle<v8::Value> console(ConsoleLogTypes logType, const v8::Arguments &args)
114 {
115     v8::HandleScope handleScope;
116
117     QString result;
118     for (int i = 0; i < args.Length(); ++i) {
119         if (i != 0)
120             result.append(QLatin1Char(' '));
121
122         v8::Local<v8::Value> value = args[i];
123         //Check for Object Type
124         if (value->IsObject() && !value->IsFunction()
125                 && !value->IsArray() && !value->IsDate()
126                 && !value->IsRegExp()) {
127             result.append(QLatin1String("Object"));
128         } else {
129             v8::Local<v8::String> jsstr = value->ToString();
130             QString tmp = V8ENGINE()->toString(jsstr);
131             if (value->IsArray())
132                 result.append(QString::fromLatin1("[%1]").arg(tmp));
133             else
134                 result.append(tmp);
135         }
136     }
137
138     result = extendMessage(result);
139
140     switch (logType) {
141     case Log:
142         qDebug("%s", qPrintable(result));
143         break;
144     case Warn:
145         qWarning("%s", qPrintable(result));
146         break;
147     case Error:
148         qCritical("%s", qPrintable(result));
149         break;
150     default:
151         break;
152     }
153
154     return v8::Undefined();
155 }
156
157 v8::Handle<v8::Value> gc(const v8::Arguments &args)
158 {
159     Q_UNUSED(args);
160     QV8Engine::gc();
161     return v8::Undefined();
162 }
163
164 v8::Handle<v8::Value> consoleError(const v8::Arguments &args)
165 {
166     return console(Error, args);
167 }
168
169 v8::Handle<v8::Value> consoleLog(const v8::Arguments &args)
170 {
171     //console.log
172     //console.debug
173     //console.info
174     //print
175     return console(Log, args);
176 }
177
178 v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args)
179 {
180     //DeclarativeDebugTrace cannot handle nested profiling
181     //although v8 can handle several profiling at once,
182     //we do not allow that. Hence, we pass an empty(default) title
183     Q_UNUSED(args);
184     QString title;
185
186     if (QDeclarativeDebugTrace::startProfiling()) {
187         QV8ProfilerService::instance()->startProfiling(title);
188         qDebug("Profiling started.");
189     } else {
190         qWarning("Profiling is already in progress. First, end current profiling session.");
191     }
192
193     return v8::Undefined();
194 }
195
196 v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args)
197 {
198     //DeclarativeDebugTrace cannot handle nested profiling
199     //although v8 can handle several profiling at once,
200     //we do not allow that. Hence, we pass an empty(default) title
201     Q_UNUSED(args);
202     QString title;
203
204     if (QDeclarativeDebugTrace::stopProfiling()) {
205         QV8ProfilerService *profiler = QV8ProfilerService::instance();
206         profiler->stopProfiling(title);
207         QDeclarativeDebugTrace::sendProfilingData();
208         profiler->sendProfilingData();
209         qDebug("Profiling ended.");
210     } else {
211         qWarning("Profiling was not started.");
212     }
213
214     return v8::Undefined();
215 }
216
217 v8::Handle<v8::Value> consoleTime(const v8::Arguments &args)
218 {
219     if (args.Length() != 1)
220         V8THROW_ERROR("console.time(): Invalid arguments");
221     QString name = V8ENGINE()->toString(args[0]);
222     V8ENGINE()->startTimer(name);
223     return v8::Undefined();
224 }
225
226 v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args)
227 {
228     if (args.Length() != 1)
229         V8THROW_ERROR("console.time(): Invalid arguments");
230     QString name = V8ENGINE()->toString(args[0]);
231     bool wasRunning;
232     qint64 elapsed = V8ENGINE()->stopTimer(name, &wasRunning);
233     if (wasRunning) {
234         qDebug("%s: %llims", qPrintable(name), elapsed);
235     }
236     return v8::Undefined();
237 }
238
239 v8::Handle<v8::Value> consoleCount(const v8::Arguments &args)
240 {
241     // first argument: name to print. Ignore any additional arguments
242     QString name;
243     if (args.Length() > 0)
244         name = V8ENGINE()->toString(args[0]);
245
246     v8::Handle<v8::StackTrace> stackTrace =
247         v8::StackTrace::CurrentStackTrace(1, v8::StackTrace::kOverview);
248
249     if (stackTrace->GetFrameCount()) {
250         v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
251
252         QString scriptName = V8ENGINE()->toString(frame->GetScriptName());
253         int line = frame->GetLineNumber();
254         int column = frame->GetColumn();
255
256         int value = V8ENGINE()->consoleCountHelper(scriptName, line, column);
257         QString message = name + QLatin1String(": ") + QString::number(value);
258         if (qmlConsoleExtended())
259             message = QString::fromLatin1("%1 (%2:%3)").arg(message).arg(scriptName).arg(line);
260         qDebug("%s", qPrintable(message));
261     }
262
263     return v8::Undefined();
264 }
265
266 v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args)
267 {
268     if (args.Length() != 0)
269         V8THROW_ERROR("console.trace(): Invalid arguments");
270
271     printStack();
272     return v8::Undefined();
273 }
274
275 v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args)
276 {
277     return console(Warn, args);
278 }
279
280 v8::Handle<v8::Value> consoleAssert(const v8::Arguments &args)
281 {
282     if (args.Length() == 0)
283         V8THROW_ERROR("console.assert(): Missing argument");
284
285     if (!args[0]->ToBoolean()->Value()) {
286         QString message;
287         for (int i = 1; i < args.Length(); ++i) {
288             if (i != 1)
289                 message.append(QLatin1Char(' '));
290
291             v8::Local<v8::Value> value = args[i];
292             message.append(V8ENGINE()->toString(value->ToString()));
293         }
294
295         message = extendMessage(message);
296         qCritical("%s", qPrintable(message));
297         printStack();
298     }
299     return v8::Undefined();
300 }
301
302 v8::Handle<v8::Value> consoleException(const v8::Arguments &args)
303 {
304     if (args.Length() == 0)
305         V8THROW_ERROR("console.exception(): Missing argument");
306     console(Error, args);
307     printStack();
308
309     return v8::Undefined();
310 }
311
312 v8::Handle<v8::Value> stringArg(const v8::Arguments &args)
313 {
314     QString value = V8ENGINE()->toString(args.This()->ToString());
315     if (args.Length() != 1)
316         V8THROW_ERROR("String.arg(): Invalid arguments");
317
318     v8::Handle<v8::Value> arg = args[0];
319     if (arg->IsUint32())
320         return V8ENGINE()->toString(value.arg(arg->Uint32Value()));
321     else if (arg->IsInt32())
322         return V8ENGINE()->toString(value.arg(arg->Int32Value()));
323     else if (arg->IsNumber())
324         return V8ENGINE()->toString(value.arg(arg->NumberValue()));
325     else if (arg->IsBoolean())
326         return V8ENGINE()->toString(value.arg(arg->BooleanValue()));
327
328     return V8ENGINE()->toString(value.arg(V8ENGINE()->toString(arg)));
329 }
330
331 /*!
332 \qmlmethod bool Qt::isQtObject(object)
333 Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
334 */
335 v8::Handle<v8::Value> isQtObject(const v8::Arguments &args)
336 {
337     if (args.Length() == 0)
338         return v8::Boolean::New(false);
339
340     return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0]));
341 }
342
343 /*!
344 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
345
346 Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
347 All components should be in the range 0-1 inclusive.
348 */
349 v8::Handle<v8::Value> rgba(const v8::Arguments &args)
350 {
351     int argCount = args.Length();
352     if (argCount < 3 || argCount > 4)
353         V8THROW_ERROR("Qt.rgba(): Invalid arguments");
354
355     double r = args[0]->NumberValue();
356     double g = args[1]->NumberValue();
357     double b = args[2]->NumberValue();
358     double a = (argCount == 4) ? args[3]->NumberValue() : 1;
359
360     if (r < 0.0) r=0.0;
361     if (r > 1.0) r=1.0;
362     if (g < 0.0) g=0.0;
363     if (g > 1.0) g=1.0;
364     if (b < 0.0) b=0.0;
365     if (b > 1.0) b=1.0;
366     if (a < 0.0) a=0.0;
367     if (a > 1.0) a=1.0;
368
369     return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
370 }
371
372 /*!
373 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
374
375 Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
376 All components should be in the range 0-1 inclusive.
377 */
378 v8::Handle<v8::Value> hsla(const v8::Arguments &args)
379 {
380     int argCount = args.Length();
381     if (argCount < 3 || argCount > 4)
382         V8THROW_ERROR("Qt.hsla(): Invalid arguments");
383
384     double h = args[0]->NumberValue();
385     double s = args[1]->NumberValue();
386     double l = args[2]->NumberValue();
387     double a = (argCount == 4) ? args[3]->NumberValue() : 1;
388
389     if (h < 0.0) h=0.0;
390     if (h > 1.0) h=1.0;
391     if (s < 0.0) s=0.0;
392     if (s > 1.0) s=1.0;
393     if (l < 0.0) l=0.0;
394     if (l > 1.0) l=1.0;
395     if (a < 0.0) a=0.0;
396     if (a > 1.0) a=1.0;
397
398     return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
399 }
400
401 /*!
402 \qmlmethod rect Qt::rect(int x, int y, int width, int height)
403
404 Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
405
406 The returned object has \c x, \c y, \c width and \c height attributes with the given values.
407 */
408 v8::Handle<v8::Value> rect(const v8::Arguments &args)
409 {
410     if (args.Length() != 4)
411         V8THROW_ERROR("Qt.rect(): Invalid arguments");
412
413     double x = args[0]->NumberValue();
414     double y = args[1]->NumberValue();
415     double w = args[2]->NumberValue();
416     double h = args[3]->NumberValue();
417
418     return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
419 }
420
421 /*!
422 \qmlmethod point Qt::point(int x, int y)
423 Returns a Point with the specified \c x and \c y coordinates.
424 */
425 v8::Handle<v8::Value> point(const v8::Arguments &args)
426 {
427     if (args.Length() != 2)
428         V8THROW_ERROR("Qt.point(): Invalid arguments");
429
430     double x = args[0]->ToNumber()->Value();
431     double y = args[1]->ToNumber()->Value();
432
433     return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y)));
434 }
435
436 /*!
437 \qmlmethod Qt::size(int width, int height)
438 Returns a Size with the specified \c width and \c height.
439 */
440 v8::Handle<v8::Value> size(const v8::Arguments &args)
441 {
442     if (args.Length() != 2)
443         V8THROW_ERROR("Qt.size(): Invalid arguments");
444
445     double w = args[0]->ToNumber()->Value();
446     double h = args[1]->ToNumber()->Value();
447
448     return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
449 }
450
451 /*!
452 \qmlmethod Qt::vector3d(real x, real y, real z)
453 Returns a Vector3D with the specified \c x, \c y and \c z.
454 */
455 v8::Handle<v8::Value> vector3d(const v8::Arguments &args)
456 {
457     if (args.Length() != 3)
458         V8THROW_ERROR("Qt.vector(): Invalid arguments");
459
460     double x = args[0]->ToNumber()->Value();
461     double y = args[1]->ToNumber()->Value();
462     double z = args[2]->ToNumber()->Value();
463
464     return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z)));
465 }
466
467 /*!
468 \qmlmethod Qt::vector4d(real x, real y, real z, real w)
469 Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
470 */
471 v8::Handle<v8::Value> vector4d(const v8::Arguments &args)
472 {
473     if (args.Length() != 4)
474         V8THROW_ERROR("Qt.vector4d(): Invalid arguments");
475
476     double x = args[0]->NumberValue();
477     double y = args[1]->NumberValue();
478     double z = args[2]->NumberValue();
479     double w = args[3]->NumberValue();
480
481     return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w)));
482 }
483
484 /*!
485 \qmlmethod color Qt::lighter(color baseColor, real factor)
486 Returns a color lighter than \c baseColor by the \c factor provided.
487
488 If the factor is greater than 1.0, this functions returns a lighter color.
489 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
490 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
491 If the factor is 0 or negative, the return value is unspecified.
492
493 The function converts the current RGB color to HSV, multiplies the value (V) component
494 by factor and converts the color back to RGB.
495
496 If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
497 */
498 v8::Handle<v8::Value> lighter(const v8::Arguments &args)
499 {
500     if (args.Length() != 1 && args.Length() != 2)
501         V8THROW_ERROR("Qt.lighter(): Invalid arguments");
502
503     QColor color;
504     QVariant v = V8ENGINE()->toVariant(args[0], -1);
505     if (v.userType() == QVariant::Color) {
506         color = v.value<QColor>();
507     } else if (v.userType() == QVariant::String) {
508         bool ok = false;
509         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
510         if (!ok) {
511             return v8::Null();
512         }
513     } else {
514         return v8::Null();
515     }
516
517     qreal factor = 1.5;
518     if (args.Length() == 2)
519         factor = args[1]->ToNumber()->Value();
520
521     color = color.lighter(int(qRound(factor*100.)));
522     return V8ENGINE()->fromVariant(QVariant::fromValue(color));
523 }
524
525 /*!
526 \qmlmethod color Qt::darker(color baseColor, real factor)
527 Returns a color darker than \c baseColor by the \c factor provided.
528
529 If the factor is greater than 1.0, this function returns a darker color.
530 Setting factor to 3.0 returns a color that has one-third the brightness.
531 If the factor is less than 1.0, the return color is lighter, but we recommend using
532 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
533 value is unspecified.
534
535 The function converts the current RGB color to HSV, divides the value (V) component
536 by factor and converts the color back to RGB.
537
538 If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
539 */
540 v8::Handle<v8::Value> darker(const v8::Arguments &args)
541 {
542     if (args.Length() != 1 && args.Length() != 2)
543         V8THROW_ERROR("Qt.darker(): Invalid arguments");
544
545     QColor color;
546     QVariant v = V8ENGINE()->toVariant(args[0], -1);
547     if (v.userType() == QVariant::Color) {
548         color = v.value<QColor>();
549     } else if (v.userType() == QVariant::String) {
550         bool ok = false;
551         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
552         if (!ok) {
553             return v8::Null();
554         }
555     } else {
556         return v8::Null();
557     }
558
559     qreal factor = 2.0;
560     if (args.Length() == 2)
561         factor = args[1]->ToNumber()->Value();
562
563     color = color.darker(int(qRound(factor*100.)));
564     return V8ENGINE()->fromVariant(QVariant::fromValue(color));
565 }
566
567 /*!
568     \qmlmethod color Qt::tint(color baseColor, color tintColor)
569     This function allows tinting one color with another.
570
571     The tint color should usually be mostly transparent, or you will not be
572     able to see the underlying color. The below example provides a slight red
573     tint by having the tint color be pure red which is only 1/16th opaque.
574
575     \qml
576     Item {
577         Rectangle {
578             x: 0; width: 80; height: 80
579             color: "lightsteelblue"
580         }
581         Rectangle {
582             x: 100; width: 80; height: 80
583             color: Qt.tint("lightsteelblue", "#10FF0000")
584         }
585     }
586     \endqml
587     \image declarative-rect_tint.png
588
589     Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
590 */
591 v8::Handle<v8::Value> tint(const v8::Arguments &args)
592 {
593     if (args.Length() != 2)
594         V8THROW_ERROR("Qt.tint(): Invalid arguments");
595
596     // base color
597     QColor color;
598     QVariant v = V8ENGINE()->toVariant(args[0], -1);
599     if (v.userType() == QVariant::Color) {
600         color = v.value<QColor>();
601     } else if (v.userType() == QVariant::String) {
602         bool ok = false;
603         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
604         if (!ok) {
605             return v8::Null();
606         }
607     } else {
608         return v8::Null();
609     }
610
611     // tint color
612     QColor tintColor;
613     v = V8ENGINE()->toVariant(args[1], -1);
614     if (v.userType() == QVariant::Color) {
615         tintColor = v.value<QColor>();
616     } else if (v.userType() == QVariant::String) {
617         bool ok = false;
618         tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
619         if (!ok) {
620             return v8::Null();
621         }
622     } else {
623         return v8::Null();
624     }
625
626     // tint the base color and return the final color
627     QColor finalColor;
628     int a = tintColor.alpha();
629     if (a == 0xFF)
630         finalColor = tintColor;
631     else if (a == 0x00)
632         finalColor = color;
633     else {
634         qreal a = tintColor.alphaF();
635         qreal inv_a = 1.0 - a;
636
637         finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
638                            tintColor.greenF() * a + color.greenF() * inv_a,
639                            tintColor.blueF() * a + color.blueF() * inv_a,
640                            a + inv_a * color.alphaF());
641     }
642
643     return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor));
644 }
645
646 /*!
647 \qmlmethod string Qt::formatDate(datetime date, variant format)
648
649 Returns a string representation of \c date, optionally formatted according
650 to \c format.
651
652 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
653 property, a QDate, or QDateTime value. The \a format parameter may be any of
654 the possible format values as described for
655 \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
656
657 If \a format is not specified, \a date is formatted using
658 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
659
660 \sa Locale
661 */
662 v8::Handle<v8::Value> formatDate(const v8::Arguments &args)
663 {
664     if (args.Length() < 1 || args.Length() > 2)
665         V8THROW_ERROR("Qt.formatDate(): Invalid arguments");
666
667     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
668     QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date();
669     QString formattedDate;
670     if (args.Length() == 2) {
671         if (args[1]->IsString()) {
672             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
673             formattedDate = date.toString(format);
674         } else if (args[1]->IsNumber()) {
675             quint32 intFormat = args[1]->ToNumber()->Value();
676             Qt::DateFormat format = Qt::DateFormat(intFormat);
677             formattedDate = date.toString(format);
678         } else {
679             V8THROW_ERROR("Qt.formatDate(): Invalid date format");
680         }
681     } else {
682          formattedDate = date.toString(enumFormat);
683     }
684
685     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate));
686 }
687
688 /*!
689 \qmlmethod string Qt::formatTime(datetime time, variant format)
690
691 Returns a string representation of \c time, optionally formatted according to
692 \c format.
693
694 The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
695 value. The \a format parameter may be any of the possible format values as
696 described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
697
698 If \a format is not specified, \a time is formatted using
699 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
700
701 \sa Locale
702 */
703 v8::Handle<v8::Value> formatTime(const v8::Arguments &args)
704 {
705     if (args.Length() < 1 || args.Length() > 2)
706         V8THROW_ERROR("Qt.formatTime(): Invalid arguments");
707
708     QVariant argVariant = V8ENGINE()->toVariant(args[0], -1);
709     QTime time;
710     if (args[0]->IsDate() || (argVariant.type() == QVariant::String))
711         time = argVariant.toDateTime().time();
712     else // if (argVariant.type() == QVariant::Time), or invalid.
713         time = argVariant.toTime();
714
715     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
716     QString formattedTime;
717     if (args.Length() == 2) {
718         if (args[1]->IsString()) {
719             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
720             formattedTime = time.toString(format);
721         } else if (args[1]->IsNumber()) {
722             quint32 intFormat = args[1]->ToNumber()->Value();
723             Qt::DateFormat format = Qt::DateFormat(intFormat);
724             formattedTime = time.toString(format);
725         } else {
726             V8THROW_ERROR("Qt.formatTime(): Invalid time format");
727         }
728     } else {
729          formattedTime = time.toString(enumFormat);
730     }
731
732     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime));
733 }
734
735 /*!
736 \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
737
738 Returns a string representation of \c datetime, optionally formatted according to
739 \c format.
740
741 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
742 property, a QDate, QTime, or QDateTime value.
743
744 If \a format is not provided, \a dateTime is formatted using
745 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
746 \a format should be either:
747
748 \list
749 \o One of the Qt::DateFormat enumeration values, such as
750    \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
751 \o A string that specifies the format of the returned string, as detailed below.
752 \endlist
753
754 If \a format specifies a format string, it should use the following expressions
755 to specify the date:
756
757     \table
758     \header \i Expression \i Output
759     \row \i d \i the day as number without a leading zero (1 to 31)
760     \row \i dd \i the day as number with a leading zero (01 to 31)
761     \row \i ddd
762             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
763             Uses QDate::shortDayName().
764     \row \i dddd
765             \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
766             Uses QDate::longDayName().
767     \row \i M \i the month as number without a leading zero (1-12)
768     \row \i MM \i the month as number with a leading zero (01-12)
769     \row \i MMM
770             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
771             Uses QDate::shortMonthName().
772     \row \i MMMM
773             \i the long localized month name (e.g. 'January' to 'December').
774             Uses QDate::longMonthName().
775     \row \i yy \i the year as two digit number (00-99)
776     \row \i yyyy \i the year as four digit number
777     \endtable
778
779 In addition the following expressions can be used to specify the time:
780
781     \table
782     \header \i Expression \i Output
783     \row \i h
784          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
785     \row \i hh
786          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
787     \row \i m \i the minute without a leading zero (0 to 59)
788     \row \i mm \i the minute with a leading zero (00 to 59)
789     \row \i s \i the second without a leading zero (0 to 59)
790     \row \i ss \i the second with a leading zero (00 to 59)
791     \row \i z \i the milliseconds without leading zeroes (0 to 999)
792     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
793     \row \i AP
794             \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
795     \row \i ap
796             \i use am/pm display. \e ap will be replaced by either "am" or "pm".
797     \endtable
798
799     All other input characters will be ignored. Any sequence of characters that
800     are enclosed in single quotes will be treated as text and not be used as an
801     expression. Two consecutive single quotes ("''") are replaced by a single quote
802     in the output.
803
804 For example, if the following date/time value was specified:
805
806     \code
807     // 21 May 2001 14:13:09
808     var dateTime = new Date(2001, 5, 21, 14, 13, 09)
809     \endcode
810
811 This \a dateTime value could be passed to \c Qt.formatDateTime(),
812 \l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
813 with the \a format values below to produce the following results:
814
815     \table
816     \header \i Format \i Result
817     \row \i "dd.MM.yyyy"      \i 21.05.2001
818     \row \i "ddd MMMM d yy"   \i Tue May 21 01
819     \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
820     \row \i "h:m:s ap"        \i 2:13:9 pm
821     \endtable
822
823     \sa Locale
824 */
825 v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args)
826 {
827     if (args.Length() < 1 || args.Length() > 2)
828         V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
829
830     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
831     QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime();
832     QString formattedDt;
833     if (args.Length() == 2) {
834         if (args[1]->IsString()) {
835             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
836             formattedDt = dt.toString(format);
837         } else if (args[1]->IsNumber()) {
838             quint32 intFormat = args[1]->ToNumber()->Value();
839             Qt::DateFormat format = Qt::DateFormat(intFormat);
840             formattedDt = dt.toString(format);
841         } else {
842             V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
843         }
844     } else {
845          formattedDt = dt.toString(enumFormat);
846     }
847
848     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt));
849 }
850
851 /*!
852 \qmlmethod bool Qt::openUrlExternally(url target)
853 Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
854 */
855 v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args)
856 {
857     if (args.Length() != 1)
858         return V8ENGINE()->fromVariant(false);
859
860     bool ret = false;
861 #ifndef QT_NO_DESKTOPSERVICES
862     ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl());
863 #endif
864     return V8ENGINE()->fromVariant(ret);
865 }
866
867 /*!
868   \qmlmethod url Qt::resolvedUrl(url url)
869   Returns \a url resolved relative to the URL of the caller.
870 */
871 v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args)
872 {
873     QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl();
874     QDeclarativeEngine *e = V8ENGINE()->engine();
875     QDeclarativeEnginePrivate *p = 0;
876     if (e) p = QDeclarativeEnginePrivate::get(e);
877     if (p) {
878         QDeclarativeContextData *ctxt = V8ENGINE()->callingContext();
879         if (ctxt)
880             return V8ENGINE()->toString(ctxt->resolvedUrl(url).toString());
881         else
882             return V8ENGINE()->toString(url.toString());
883     }
884
885     return V8ENGINE()->toString(e->baseUrl().resolved(url).toString());
886 }
887
888 /*!
889 \qmlmethod list<string> Qt::fontFamilies()
890 Returns a list of the font families available to the application.
891 */
892 v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args)
893 {
894     if (args.Length() != 0)
895         V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
896
897     QFontDatabase database;
898     return V8ENGINE()->fromVariant(database.families());
899 }
900
901 /*!
902 \qmlmethod string Qt::md5(data)
903 Returns a hex string of the md5 hash of \c data.
904 */
905 v8::Handle<v8::Value> md5(const v8::Arguments &args)
906 {
907     if (args.Length() != 1)
908         V8THROW_ERROR("Qt.md5(): Invalid arguments");
909
910     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
911     QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
912     return V8ENGINE()->toString(QLatin1String(result.toHex()));
913 }
914
915 /*!
916 \qmlmethod string Qt::btoa(data)
917 Binary to ASCII - this function returns a base64 encoding of \c data.
918 */
919 v8::Handle<v8::Value> btoa(const v8::Arguments &args)
920 {
921     if (args.Length() != 1)
922         V8THROW_ERROR("Qt.btoa(): Invalid arguments");
923
924     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
925
926     return V8ENGINE()->toString(QLatin1String(data.toBase64()));
927 }
928
929 /*!
930 \qmlmethod string Qt::atob(data)
931 ASCII to binary - this function returns a base64 decoding of \c data.
932 */
933 v8::Handle<v8::Value> atob(const v8::Arguments &args)
934 {
935     if (args.Length() != 1)
936         V8THROW_ERROR("Qt.atob(): Invalid arguments");
937
938     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
939
940     return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data)));
941 }
942
943 /*!
944 \qmlmethod Qt::quit()
945 This function causes the QDeclarativeEngine::quit() signal to be emitted.
946 Within the \l {QML Viewer}, this causes the launcher application to exit;
947 to quit a C++ application when this method is called, connect the
948 QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
949 */
950 v8::Handle<v8::Value> quit(const v8::Arguments &args)
951 {
952     QDeclarativeEnginePrivate::get(V8ENGINE()->engine())->sendQuit();
953     return v8::Undefined();
954 }
955
956 /*!
957 \qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
958
959 Returns a new object created from the given \a string of QML which will have the specified \a parent,
960 or \c null if there was an error in creating the object.
961
962 If \a filepath is specified, it will be used for error reporting for the created object.
963
964 Example (where \c parentItem is the id of an existing QML item):
965
966 \snippet doc/src/snippets/declarative/createQmlObject.qml 0
967
968 In the case of an error, a QtScript Error object is thrown. This object has an additional property,
969 \c qmlErrors, which is an array of the errors encountered.
970 Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
971 For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
972 { "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
973
974 Note that this function returns immediately, and therefore may not work if
975 the \a qml string loads new components (that is, external QML files that have not yet been loaded).
976 If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
977
978 See \l {Dynamic Object Management in QML} for more information on using this function.
979 */
980 v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args)
981 {
982     if (args.Length() < 2 || args.Length() > 3)
983         V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
984
985     struct Error {
986         static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QDeclarativeError> &errors) {
987             QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
988
989             v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count());
990             for (int ii = 0; ii < errors.count(); ++ii) {
991                 const QDeclarativeError &error = errors.at(ii);
992                 errorstr += QLatin1String("\n    ") + error.toString();
993                 v8::Local<v8::Object> qmlerror = v8::Object::New();
994                 qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line()));
995                 qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.line()));
996                 qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString()));
997                 qmlerror->Set(v8::String::New("message"), engine->toString(error.description()));
998                 qmlerrors->Set(ii, qmlerror);
999             }
1000
1001             v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr));
1002             v8::Local<v8::Object> errorObject = error->ToObject();
1003             errorObject->Set(v8::String::New("qmlErrors"), qmlerrors);
1004             return error;
1005         }
1006     };
1007
1008     QV8Engine *v8engine = V8ENGINE();
1009     QDeclarativeEngine *engine = v8engine->engine();
1010
1011     QDeclarativeContextData *context = v8engine->callingContext();
1012     QDeclarativeContext *effectiveContext = 0;
1013     if (context->isPragmaLibraryContext)
1014         effectiveContext = engine->rootContext();
1015     else
1016         effectiveContext = context->asQDeclarativeContext();
1017     Q_ASSERT(context && effectiveContext);
1018
1019     QString qml = v8engine->toString(args[0]->ToString());
1020     if (qml.isEmpty())
1021         return v8::Null();
1022
1023     QUrl url;
1024     if (args.Length() > 2)
1025         url = QUrl(v8engine->toString(args[2]->ToString()));
1026     else
1027         url = QUrl(QLatin1String("inline"));
1028
1029     if (url.isValid() && url.isRelative())
1030         url = context->resolvedUrl(url);
1031
1032     QObject *parentArg = v8engine->toQObject(args[1]);
1033     if (!parentArg)
1034         V8THROW_ERROR("Qt.createQmlObject(): Missing parent object");
1035
1036     QDeclarativeComponent component(engine);
1037     component.setData(qml.toUtf8(), url);
1038
1039     if (component.isError()) {
1040         v8::ThrowException(Error::create(v8engine, component.errors()));
1041         return v8::Undefined();
1042     }
1043
1044     if (!component.isReady())
1045         V8THROW_ERROR("Qt.createQmlObject(): Component is not ready");
1046
1047     QObject *obj = component.beginCreate(effectiveContext);
1048     if (obj)
1049         QDeclarativeData::get(obj, true)->setImplicitDestructible();
1050     component.completeCreate();
1051
1052     if (component.isError()) {
1053         v8::ThrowException(Error::create(v8engine, component.errors()));
1054         return v8::Undefined();
1055     }
1056
1057     Q_ASSERT(obj);
1058
1059     obj->setParent(parentArg);
1060
1061     QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
1062     for (int ii = 0; ii < functions.count(); ++ii) {
1063         if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
1064             break;
1065     }
1066
1067     return v8engine->newQObject(obj);
1068 }
1069
1070 /*!
1071 \qmlmethod object Qt::createComponent(url)
1072
1073 Returns a \l Component object created using the QML file at the specified \a url,
1074 or \c null if an empty string was given.
1075
1076 The returned component's \l Component::status property indicates whether the
1077 component was successfully created. If the status is \c Component.Error,
1078 see \l Component::errorString() for an error description.
1079
1080 Call \l {Component::createObject()}{Component.createObject()} on the returned
1081 component to create an object instance of the component.
1082
1083 For example:
1084
1085 \snippet doc/src/snippets/declarative/createComponent-simple.qml 0
1086
1087 See \l {Dynamic Object Management in QML} for more information on using this function.
1088
1089 To create a QML object from an arbitrary string of QML (instead of a file),
1090 use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
1091 */
1092 v8::Handle<v8::Value> createComponent(const v8::Arguments &args)
1093 {
1094     if (args.Length() != 1)
1095         V8THROW_ERROR("Qt.createComponent(): Invalid arguments");
1096
1097     QV8Engine *v8engine = V8ENGINE();
1098     QDeclarativeEngine *engine = v8engine->engine();
1099
1100     QDeclarativeContextData *context = v8engine->callingContext();
1101     QDeclarativeContextData *effectiveContext = context;
1102     if (context->isPragmaLibraryContext)
1103         effectiveContext = 0;
1104     Q_ASSERT(context);
1105
1106     QString arg = v8engine->toString(args[0]->ToString());
1107     if (arg.isEmpty())
1108         return v8::Null();
1109
1110     QUrl url = context->resolvedUrl(QUrl(arg));
1111     QDeclarativeComponent *c = new QDeclarativeComponent(engine, url, engine);
1112     QDeclarativeComponentPrivate::get(c)->creationContext = effectiveContext;
1113     QDeclarativeData::get(c, true)->setImplicitDestructible();
1114     return v8engine->newQObject(c);
1115 }
1116
1117 v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args)
1118 {
1119     if (args.Length() < 2)
1120         V8THROW_ERROR("qsTranslate() requires at least two arguments");
1121     if (!args[0]->IsString())
1122         V8THROW_ERROR("qsTranslate(): first argument (context) must be a string");
1123     if (!args[1]->IsString())
1124         V8THROW_ERROR("qsTranslate(): second argument (text) must be a string");
1125     if ((args.Length() > 2) && !args[2]->IsString())
1126         V8THROW_ERROR("qsTranslate(): third argument (comment) must be a string");
1127     if ((args.Length() > 3) && !args[3]->IsString())
1128         V8THROW_ERROR("qsTranslate(): fourth argument (encoding) must be a string");
1129
1130     QV8Engine *v8engine = V8ENGINE();
1131     QString context = v8engine->toString(args[0]);
1132     QString text = v8engine->toString(args[1]);
1133     QString comment;
1134     if (args.Length() > 2) comment = v8engine->toString(args[2]);
1135
1136     QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8;
1137     if (args.Length() > 3) {
1138         QString encStr = v8engine->toString(args[3]);
1139         if (encStr == QLatin1String("CodecForTr")) {
1140             encoding = QCoreApplication::CodecForTr;
1141         } else if (encStr == QLatin1String("UnicodeUTF8")) {
1142             encoding = QCoreApplication::UnicodeUTF8;
1143         } else {
1144             QString msg = QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr);
1145             V8THROW_ERROR((uint16_t *)msg.constData());
1146         }
1147     }
1148
1149     int n = -1;
1150     if (args.Length() > 4)
1151         n = args[4]->Int32Value();
1152
1153     QString result = QCoreApplication::translate(context.toUtf8().constData(),
1154                                                  text.toUtf8().constData(),
1155                                                  comment.toUtf8().constData(),
1156                                                  encoding, n);
1157
1158     return v8engine->toString(result);
1159 }
1160
1161 v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args)
1162 {
1163     if (args.Length() < 2)
1164         return v8::Undefined();
1165     return args[1];
1166 }
1167
1168 v8::Handle<v8::Value> qsTr(const v8::Arguments &args)
1169 {
1170     if (args.Length() < 1)
1171         V8THROW_ERROR("qsTr() requires at least one argument");
1172     if (!args[0]->IsString())
1173         V8THROW_ERROR("qsTr(): first argument (text) must be a string");
1174     if ((args.Length() > 1) && !args[1]->IsString())
1175         V8THROW_ERROR("qsTr(): second argument (comment) must be a string");
1176     if ((args.Length() > 2) && !args[2]->IsNumber())
1177         V8THROW_ERROR("qsTr(): third argument (n) must be a number");
1178
1179     QV8Engine *v8engine = V8ENGINE();
1180     QDeclarativeContextData *ctxt = v8engine->callingContext();
1181
1182     QString path = ctxt->url.toString();
1183     int lastSlash = path.lastIndexOf(QLatin1Char('/'));
1184     QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString();
1185
1186     QString text = v8engine->toString(args[0]);
1187     QString comment;
1188     if (args.Length() > 1)
1189         comment = v8engine->toString(args[1]);
1190     int n = -1;
1191     if (args.Length() > 2)
1192         n = args[2]->Int32Value();
1193
1194     QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
1195                                                  comment.toUtf8().constData(), QCoreApplication::UnicodeUTF8, n);
1196
1197     return v8engine->toString(result);
1198 }
1199
1200 v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args)
1201 {
1202     if (args.Length() < 1)
1203         return v8::Undefined();
1204     return args[0];
1205 }
1206
1207 v8::Handle<v8::Value> qsTrId(const v8::Arguments &args)
1208 {
1209     if (args.Length() < 1)
1210         V8THROW_ERROR("qsTrId() requires at least one argument");
1211     if (!args[0]->IsString())
1212         V8THROW_TYPE("qsTrId(): first argument (id) must be a string");
1213     if (args.Length() > 1 && !args[1]->IsNumber())
1214         V8THROW_TYPE("qsTrId(): second argument (n) must be a number");
1215
1216     int n = -1;
1217     if (args.Length() > 1)
1218         n = args[1]->Int32Value();
1219
1220     QV8Engine *v8engine = V8ENGINE();
1221     return v8engine->toString(qtTrId(v8engine->toString(args[0]).toUtf8().constData(), n));
1222 }
1223
1224 v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args)
1225 {
1226     if (args.Length() < 1)
1227         return v8::Undefined();
1228     return args[0];
1229 }
1230
1231
1232 /*!
1233     \qmlmethod Qt::locale(name)
1234
1235     Returns a JS object representing the locale with the specified
1236     name, which has the format "language[_territory][.codeset][@modifier]"
1237     or "C", where:
1238
1239     \list
1240     \o language is a lowercase, two-letter, ISO 639 language code,
1241     \o territory is an uppercase, two-letter, ISO 3166 country code,
1242     \o and codeset and modifier are ignored.
1243     \endlist
1244
1245     If the string violates the locale format, or language is not a
1246     valid ISO 369 code, the "C" locale is used instead. If country
1247     is not present, or is not a valid ISO 3166 code, the most
1248     appropriate country is chosen for the specified language.
1249
1250     \sa QtQuick2::Locale
1251 */
1252 v8::Handle<v8::Value> locale(const v8::Arguments &args)
1253 {
1254     QString code;
1255     if (args.Length() > 1)
1256         V8THROW_ERROR("locale() requires 0 or 1 argument");
1257     if (args.Length() == 1 && !args[0]->IsString())
1258         V8THROW_TYPE("locale(): argument (locale code) must be a string");
1259
1260     QV8Engine *v8engine = V8ENGINE();
1261     if (args.Length() == 1)
1262         code = v8engine->toString(args[0]);
1263
1264     return QDeclarativeLocale::locale(v8engine, code);
1265 }
1266
1267 } // namespace QDeclarativeBuiltinFunctions
1268
1269 QT_END_NAMESPACE