1
/****************************************************************************
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
7
** This file is part of the QtScript module of the Qt Toolkit.
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file. Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights. These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
40
****************************************************************************/
43
#include "qscriptengine.h"
44
#include "qscriptsyntaxchecker_p.h"
47
#include "qscriptengine_p.h"
48
#include "qscriptengineagent_p.h"
49
#include "qscriptcontext_p.h"
50
#include "qscriptstring_p.h"
51
#include "qscriptvalue_p.h"
52
#include "qscriptvalueiterator.h"
53
#include "qscriptclass.h"
56
#include <QtCore/qstringlist.h>
57
#include <QtCore/qmetaobject.h>
62
#include "Interpreter.h"
63
#include "DateConstructor.h"
64
#include "RegExpConstructor.h"
66
#include "PrototypeFunction.h"
67
#include "InitializeThreading.h"
68
#include "ObjectPrototype.h"
69
#include "SourceCode.h"
70
#include "FunctionPrototype.h"
71
#include "TimeoutChecker.h"
72
#include "JSFunction.h"
74
#include "Operations.h"
76
#include "utils/qscriptdate_p.h"
77
#include "bridge/qscriptfunction_p.h"
78
#include "bridge/qscriptobject_p.h"
79
#include "bridge/qscriptclassobject_p.h"
80
#include "bridge/qscriptvariant_p.h"
81
#include "bridge/qscriptqobject_p.h"
82
#include "bridge/qscriptglobalobject_p.h"
83
#include "bridge/qscriptactivationobject_p.h"
86
#include <QtCore/qcoreapplication.h>
87
#include <QtCore/qdir.h>
88
#include <QtCore/qfile.h>
89
#include <QtCore/qfileinfo.h>
90
#include <QtCore/qpluginloader.h>
91
#include <QtCore/qset.h>
92
#include <QtCore/qtextstream.h>
93
#include "qscriptextensioninterface.h"
96
Q_DECLARE_METATYPE(QScriptValue)
98
Q_DECLARE_METATYPE(QObjectList)
100
Q_DECLARE_METATYPE(QList<int>)
109
\brief The QScriptEngine class provides an environment for evaluating Qt Script code.
114
See the \l{QtScript} documentation for information about the Qt Script language,
115
and how to get started with scripting your C++ application.
117
\section1 Evaluating Scripts
119
Use evaluate() to evaluate script code; this is the C++ equivalent
120
of the built-in script function \c{eval()}.
122
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0
124
evaluate() returns a QScriptValue that holds the result of the
125
evaluation. The QScriptValue class provides functions for converting
126
the result to various C++ types (e.g. QScriptValue::toString()
127
and QScriptValue::toNumber()).
129
The following code snippet shows how a script function can be
130
defined and then invoked from C++ using QScriptValue::call():
132
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1
134
As can be seen from the above snippets, a script is provided to the
135
engine in the form of a string. One common way of loading scripts is
136
by reading the contents of a file and passing it to evaluate():
138
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2
140
Here we pass the name of the file as the second argument to
141
evaluate(). This does not affect evaluation in any way; the second
142
argument is a general-purpose string that is used to identify the
143
script for debugging purposes (for example, our filename will now
144
show up in any uncaughtExceptionBacktrace() involving the script).
146
\section1 Engine Configuration
148
The globalObject() function returns the \bold {Global Object}
149
associated with the script engine. Properties of the Global Object
150
are accessible from any script code (i.e. they are global
151
variables). Typically, before evaluating "user" scripts, you will
152
want to configure a script engine by adding one or more properties
153
to the Global Object:
155
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3
157
Adding custom properties to the scripting environment is one of the
158
standard means of providing a scripting API that is specific to your
159
application. Usually these custom properties are objects created by
160
the newQObject() or newObject() functions, or constructor functions
161
created by newFunction().
163
\section1 Script Exceptions
165
evaluate() can throw a script exception (e.g. due to a syntax
166
error); in that case, the return value is the value that was thrown
167
(typically an \c{Error} object). You can check whether the
168
evaluation caused an exception by calling hasUncaughtException(). In
169
that case, you can call toString() on the error object to obtain an
170
error message. The current uncaught exception is also available
171
through uncaughtException(). You can obtain a human-readable
172
backtrace of the exception with uncaughtExceptionBacktrace().
173
Calling clearExceptions() will cause any uncaught exceptions to be
176
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
178
The checkSyntax() function can be used to determine whether code can be
179
usefully passed to evaluate().
181
\section1 Script Object Creation
183
Use newObject() to create a standard Qt Script object; this is the
184
C++ equivalent of the script statement \c{new Object()}. You can use
185
the object-specific functionality in QScriptValue to manipulate the
186
script object (e.g. QScriptValue::setProperty()). Similarly, use
187
newArray() to create a Qt Script array object. Use newDate() to
188
create a \c{Date} object, and newRegExp() to create a \c{RegExp}
191
\section1 QObject Integration
193
Use newQObject() to wrap a QObject (or subclass)
194
pointer. newQObject() returns a proxy script object; properties,
195
children, and signals and slots of the QObject are available as
196
properties of the proxy object. No binding code is needed because it
197
is done dynamically using the Qt meta object system.
199
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5
201
Use qScriptConnect() to connect a C++ signal to a script function;
202
this is the Qt Script equivalent of QObject::connect(). When a
203
script function is invoked in response to a C++ signal, it can cause
204
a script exception; you can connect to the signalHandlerException()
205
signal to catch such an exception.
207
Use newQMetaObject() to wrap a QMetaObject; this gives you a "script
208
representation" of a QObject-based class. newQMetaObject() returns a
209
proxy script object; enum values of the class are available as
210
properties of the proxy object. You can also specify a function that
211
will be used to construct objects of the class (e.g. when the
212
constructor is invoked from a script). For classes that have a
213
"standard" Qt constructor, Qt Script can provide a default script
214
constructor for you; see scriptValueFromQMetaObject().
216
See the \l{QtScript} documentation for more information on
217
the QObject integration.
219
\section1 Support for Custom C++ Types
221
Use newVariant() to wrap a QVariant. This can be used to store
222
values of custom (non-QObject) C++ types that have been registered
223
with the Qt meta-type system. To make such types scriptable, you
224
typically associate a prototype (delegate) object with the C++ type
225
by calling setDefaultPrototype(); the prototype object defines the
226
scripting API for the C++ type. Unlike the QObject integration,
227
there is no automatic binding possible here; i.e. you have to create
228
the scripting API yourself, for example by using the QScriptable
231
Use fromScriptValue() to cast from a QScriptValue to another type,
232
and toScriptValue() to create a QScriptValue from another value.
233
You can specify how the conversion of C++ types is to be performed
234
with qScriptRegisterMetaType() and qScriptRegisterSequenceMetaType().
235
By default, Qt Script will use QVariant to store values of custom
238
\section1 Importing Extensions
240
Use importExtension() to import plugin-based extensions into the
241
engine. Call availableExtensions() to obtain a list naming all the
242
available extensions, and importedExtensions() to obtain a list
243
naming only those extensions that have been imported.
245
Call pushContext() to open up a new variable scope, and popContext()
246
to close the current scope. This is useful if you are implementing
247
an extension that evaluates script code containing temporary
248
variable definitions (e.g. \c{var foo = 123;}) that are safe to
249
discard when evaluation has completed.
251
\section1 Native Functions
253
Use newFunction() to wrap native (C++) functions, including
254
constructors for your own custom types, so that these can be invoked
255
from script code. Such functions must have the signature
256
QScriptEngine::FunctionSignature. You may then pass the function as
257
argument to newFunction(). Here is an example of a function that
258
returns the sum of its first two arguments:
260
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6
262
To expose this function to script code, you can set it as a property
263
of the Global Object:
265
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7
267
Once this is done, script code can call your function in the exact
268
same manner as a "normal" script function:
270
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8
272
\section1 Long-running Scripts
274
If you need to evaluate possibly long-running scripts from the main
275
(GUI) thread, you should first call setProcessEventsInterval() to
276
make sure that the GUI stays responsive. You can abort a currently
277
running script by calling abortEvaluation(). You can determine
278
whether an engine is currently running a script by calling
281
\section1 Core Debugging/Tracing Facilities
283
Since Qt 4.4, you can be notified of events pertaining to script
284
execution (e.g. script function calls and statement execution)
285
through the QScriptEngineAgent interface; see the setAgent()
286
function. This can be used to implement debugging and profiling of a
289
\sa QScriptValue, QScriptContext, QScriptEngineAgent
294
\enum QScriptEngine::ValueOwnership
296
This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject().
298
\value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.)
299
\value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value).
300
\value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership).
304
\enum QScriptEngine::QObjectWrapOption
306
These flags specify options when wrapping a QObject pointer with newQObject().
308
\value ExcludeChildObjects The script object will not expose child objects as properties.
309
\value ExcludeSuperClassMethods The script object will not expose signals and slots inherited from the superclass.
310
\value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass.
311
\value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties
312
\value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot.
313
\value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object.
314
\value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object.
315
\value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties.
318
class QScriptSyntaxCheckResultPrivate
321
QScriptSyntaxCheckResultPrivate() { ref = 0; }
322
~QScriptSyntaxCheckResultPrivate() {}
324
QScriptSyntaxCheckResult::State state;
325
int errorColumnNumber;
327
QString errorMessage;
331
class QScriptTypeInfo
334
QScriptTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0)
337
QByteArray signature;
338
QScriptEngine::MarshalFunction marshal;
339
QScriptEngine::DemarshalFunction demarshal;
340
JSC::JSValue prototype;
346
struct GlobalClientData : public JSC::JSGlobalData::ClientData
348
GlobalClientData(QScriptEnginePrivate *e)
350
virtual ~GlobalClientData() {}
351
virtual void mark(JSC::MarkStack& markStack) { engine->mark(markStack); }
353
QScriptEnginePrivate *engine;
356
class TimeoutCheckerProxy : public JSC::TimeoutChecker
359
TimeoutCheckerProxy(const JSC::TimeoutChecker& originalChecker)
360
: JSC::TimeoutChecker(originalChecker)
361
, m_shouldProcessEvents(false)
362
, m_shouldAbortEvaluation(false)
365
void setShouldProcessEvents(bool shouldProcess) { m_shouldProcessEvents = shouldProcess; }
366
void setShouldAbort(bool shouldAbort) { m_shouldAbortEvaluation = shouldAbort; }
367
bool shouldAbort() { return m_shouldAbortEvaluation; }
369
virtual bool didTimeOut(JSC::ExecState* exec)
371
if (JSC::TimeoutChecker::didTimeOut(exec))
374
if (m_shouldProcessEvents)
375
QCoreApplication::processEvents();
377
return m_shouldAbortEvaluation;
381
bool m_shouldProcessEvents;
382
bool m_shouldAbortEvaluation;
385
static int toDigit(char c)
387
if ((c >= '0') && (c <= '9'))
389
else if ((c >= 'a') && (c <= 'z'))
391
else if ((c >= 'A') && (c <= 'Z'))
396
qsreal integerFromString(const char *buf, int size, int radix)
405
} else if (buf[0] == '-') {
410
if (((size-i) >= 2) && (buf[i] == '0')) {
411
if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
413
if ((radix != 0) && (radix != 16))
423
} else if (radix == 0) {
428
for ( ; i < size; ++i) {
429
int d = toDigit(buf[i]);
430
if ((d == -1) || (d >= radix))
435
if (!qstrcmp(buf, "Infinity"))
441
qsreal multiplier = 1;
442
for (--i ; i >= j; --i, multiplier *= radix)
443
result += toDigit(buf[i]) * multiplier;
449
qsreal integerFromString(const QString &str, int radix)
451
QByteArray ba = str.trimmed().toUtf8();
452
return integerFromString(ba.constData(), ba.size(), radix);
455
QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec)
457
return static_cast<GlobalClientData*>(exec->globalData().clientData)->engine;
460
bool isFunction(JSC::JSValue value)
462
if (!value || !value.isObject())
464
JSC::CallData callData;
465
return (JSC::asObject(value)->getCallData(callData) != JSC::CallTypeNone);
468
static JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
469
static JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
471
JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
473
#ifndef QT_NO_QOBJECT
474
if (args.size() == 0) {
475
return JSC::throwError(exec, JSC::GeneralError, "Function.prototype.disconnect: no arguments given");
478
if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
479
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: this object is not a signal");
482
QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
484
const QMetaObject *meta = qtSignal->metaObject();
486
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.discconnect: cannot disconnect from deleted QObject");
489
QMetaMethod sig = meta->method(qtSignal->initialIndex());
490
if (sig.methodType() != QMetaMethod::Signal) {
491
QString message = QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal")
492
.arg(QLatin1String(qtSignal->metaObject()->className()))
493
.arg(QLatin1String(sig.signature()));
494
return JSC::throwError(exec, JSC::TypeError, message);
497
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
499
JSC::JSValue receiver;
501
JSC::JSValue arg0 = args.at(0);
502
if (args.size() < 2) {
506
JSC::JSValue arg1 = args.at(1);
507
if (isFunction(arg1))
510
// ### don't go via QScriptValue
511
QScript::SaveFrameHelper saveFrame(engine, exec);
512
QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
513
QString propertyName(arg1.toString(exec));
514
slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
518
if (!isFunction(slot)) {
519
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: target is not a function");
522
bool ok = engine->scriptDisconnect(thisObject, receiver, slot);
524
QString message = QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1")
525
.arg(QLatin1String(qtSignal->metaObject()->className()))
526
.arg(QLatin1String(sig.signature()));
527
return JSC::throwError(exec, JSC::GeneralError, message);
529
return JSC::jsUndefined();
532
return context->throwError(QScriptContext::TypeError,
533
QLatin1String("Function.prototype.disconnect"));
534
#endif // QT_NO_QOBJECT
537
JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
539
#ifndef QT_NO_QOBJECT
540
if (args.size() == 0) {
541
return JSC::throwError(exec, JSC::GeneralError,"Function.prototype.connect: no arguments given");
544
if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
545
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: this object is not a signal");
548
QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
550
const QMetaObject *meta = qtSignal->metaObject();
552
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: cannot connect to deleted QObject");
555
QMetaMethod sig = meta->method(qtSignal->initialIndex());
556
if (sig.methodType() != QMetaMethod::Signal) {
557
QString message = QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal")
558
.arg(QLatin1String(qtSignal->metaObject()->className()))
559
.arg(QLatin1String(sig.signature()));
560
return JSC::throwError(exec, JSC::TypeError, message);
564
QList<int> overloads = qtSignal->overloadedIndexes();
565
if (!overloads.isEmpty()) {
566
overloads.append(qtSignal->initialIndex());
567
QByteArray signature = sig.signature();
568
QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n")
569
.arg(QLatin1String(qtSignal->metaObject()->className()))
570
.arg(QLatin1String(signature.left(signature.indexOf('('))));
571
for (int i = 0; i < overloads.size(); ++i) {
572
QMetaMethod mtd = meta->method(overloads.at(i));
573
message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature())));
575
message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload")
576
.arg(QLatin1String(signature)));
577
return JSC::throwError(exec, JSC::GeneralError, message);
581
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
583
JSC::JSValue receiver;
585
JSC::JSValue arg0 = args.at(0);
586
if (args.size() < 2) {
590
JSC::JSValue arg1 = args.at(1);
591
if (isFunction(arg1))
594
// ### don't go via QScriptValue
595
QScript::SaveFrameHelper saveFrame(engine, exec);
596
QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
597
QString propertyName = arg1.toString(exec);
598
slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
602
if (!isFunction(slot)) {
603
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: target is not a function");
606
bool ok = engine->scriptConnect(thisObject, receiver, slot, Qt::AutoConnection);
608
QString message = QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1")
609
.arg(QLatin1String(qtSignal->metaObject()->className()))
610
.arg(QLatin1String(sig.signature()));
611
return JSC::throwError(exec, JSC::GeneralError, message);
613
return JSC::jsUndefined();
617
return context->throwError(QScriptContext::TypeError,
618
QLatin1String("Function.prototype.connect"));
619
#endif // QT_NO_QOBJECT
622
static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
623
static JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
624
static JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
626
JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList& args)
629
for (unsigned i = 0; i < args.size(); ++i) {
631
result.append(QLatin1Char(' '));
632
QString s(args.at(i).toString(exec));
633
if (exec->hadException())
637
if (exec->hadException())
638
return exec->exception();
639
qDebug("%s", qPrintable(result));
640
return JSC::jsUndefined();
643
JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
645
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
646
engine->collectGarbage();
647
return JSC::jsUndefined();
650
JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
652
return JSC::JSValue(exec, 1);
655
static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
656
static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
657
static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
658
static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
660
JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
663
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
664
if (!args.at(0).isString())
665
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): first argument (context) must be a string");
666
if (!args.at(1).isString())
667
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): second argument (text) must be a string");
668
if ((args.size() > 2) && !args.at(2).isString())
669
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (comment) must be a string");
670
if ((args.size() > 3) && !args.at(3).isString())
671
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fourth argument (encoding) must be a string");
672
if ((args.size() > 4) && !args.at(4).isNumber())
673
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number");
674
#ifndef QT_NO_QOBJECT
675
QString context(args.at(0).toString(exec));
677
QString text(args.at(1).toString(exec));
678
#ifndef QT_NO_QOBJECT
681
comment = args.at(2).toString(exec);
682
QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr;
683
if (args.size() > 3) {
684
QString encStr(args.at(3).toString(exec));
685
if (encStr == QLatin1String("CodecForTr"))
686
encoding = QCoreApplication::CodecForTr;
687
else if (encStr == QLatin1String("UnicodeUTF8"))
688
encoding = QCoreApplication::UnicodeUTF8;
690
return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr));
694
n = args.at(4).toInt32(exec);
697
#ifndef QT_NO_QOBJECT
698
result = QCoreApplication::translate(context.toLatin1().constData(),
699
text.toLatin1().constData(),
700
comment.toLatin1().constData(),
705
return JSC::jsString(exec, result);
708
JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
711
return JSC::jsUndefined();
715
JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
718
return JSC::throwError(exec, JSC::GeneralError, "qsTr() requires at least one argument");
719
if (!args.at(0).isString())
720
return JSC::throwError(exec, JSC::GeneralError, "qsTr(): first argument (text) must be a string");
721
if ((args.size() > 1) && !args.at(1).isString())
722
return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string");
723
if ((args.size() > 2) && !args.at(2).isNumber())
724
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number");
725
#ifndef QT_NO_QOBJECT
727
// ### implement context resolution
728
// if (ctx->parentContext())
729
// context = QFileInfo(ctx->parentContext()->fileName()).baseName();
731
QString text(args.at(0).toString(exec));
732
#ifndef QT_NO_QOBJECT
735
comment = args.at(1).toString(exec);
738
n = args.at(2).toInt32(exec);
741
#ifndef QT_NO_QOBJECT
742
result = QCoreApplication::translate(context.toLatin1().constData(),
743
text.toLatin1().constData(),
744
comment.toLatin1().constData(),
745
QCoreApplication::CodecForTr, n);
749
return JSC::jsString(exec, result);
752
JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
755
return JSC::jsUndefined();
759
static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
761
JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
763
QString value(thisObject.toString(exec));
764
JSC::JSValue arg = (args.size() != 0) ? args.at(0) : JSC::jsUndefined();
767
result = value.arg(arg.toString(exec));
768
else if (arg.isNumber())
769
result = value.arg(arg.toNumber(exec));
770
return JSC::jsString(exec, result);
774
#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY)
775
static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng)
777
QString path = ctx->argument(0).toString();
778
QStringList components = path.split(QLatin1Char('.'));
779
QScriptValue o = eng->globalObject();
780
for (int i = 0; i < components.count(); ++i) {
781
QString name = components.at(i);
782
QScriptValue oo = o.property(name);
784
oo = eng->newObject();
785
o.setProperty(name, oo);
793
} // namespace QScript
795
QScriptEnginePrivate::QScriptEnginePrivate()
796
: registeredScriptValues(0), freeScriptValues(0),
797
registeredScriptStrings(0), inEval(false)
799
qMetaTypeId<QScriptValue>();
801
JSC::initializeThreading(); // ### hmmm
803
globalData = JSC::JSGlobalData::create().releaseRef();
804
globalData->clientData = new QScript::GlobalClientData(this);
805
JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
807
JSC::ExecState* exec = globalObject->globalExec();
809
scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
811
qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
812
qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
814
qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
815
qmetaobjectWrapperObjectStructure = QScript::QMetaObjectWrapperObject::createStructure(qmetaobjectPrototype);
817
variantPrototype = new (exec) QScript::QVariantPrototype(exec, QScript::QVariantPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
818
variantWrapperObjectStructure = QScriptObject::createStructure(variantPrototype);
820
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "print"), QScript::functionPrint));
821
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "gc"), QScript::functionGC));
822
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "version"), QScript::functionVersion));
824
// ### rather than extending Function.prototype, consider creating a QtSignal.prototype
825
globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "disconnect"), QScript::functionDisconnect));
826
globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "connect"), QScript::functionConnect));
828
JSC::TimeoutChecker* originalChecker = globalData->timeoutChecker;
829
globalData->timeoutChecker = new QScript::TimeoutCheckerProxy(*originalChecker);
830
delete originalChecker;
834
originalGlobalObjectProxy = 0;
836
agentLineNumber = -1;
837
processEventsInterval = -1;
840
QScriptEnginePrivate::~QScriptEnginePrivate()
842
//disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
843
QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
844
for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it)
845
it.value()->disconnectFromEngine();
847
while (!ownedAgents.isEmpty())
848
delete ownedAgents.takeFirst();
850
detachAllRegisteredScriptValues();
851
detachAllRegisteredScriptStrings();
852
qDeleteAll(m_qobjectData);
853
qDeleteAll(m_typeInfos);
854
JSC::JSLock lock(false);
855
globalData->heap.destroy();
857
while (freeScriptValues) {
858
QScriptValuePrivate *p = freeScriptValues;
859
freeScriptValues = p->next;
864
QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v)
867
QScriptValue result = q->create(v.userType(), v.data());
868
Q_ASSERT(result.isValid());
872
QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType)
874
QVariant v(targetType, (void *)0);
875
if (QScriptEnginePrivate::convert(value, targetType, v.data(), this))
877
if (uint(targetType) == QVariant::LastType)
878
return value.toVariant();
879
if (value.isVariant()) {
880
v = value.toVariant();
881
if (v.canConvert(QVariant::Type(targetType))) {
882
v.convert(QVariant::Type(targetType));
885
QByteArray typeName = v.typeName();
886
if (typeName.endsWith('*')
887
&& (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) {
888
return QVariant(targetType, *reinterpret_cast<void* *>(v.data()));
895
JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v)
897
// ### it's inefficient to convert to QScriptValue and then to JSValue
898
QScriptValue vv = scriptValueFromVariant(v);
899
QScriptValuePrivate *p = QScriptValuePrivate::get(vv);
901
case QScriptValuePrivate::JavaScriptCore:
903
case QScriptValuePrivate::Number:
904
return JSC::jsNumber(currentFrame, p->numberValue);
905
case QScriptValuePrivate::String: {
906
JSC::UString str = p->stringValue;
907
return JSC::jsString(currentFrame, str);
910
return JSC::JSValue();
913
QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType)
915
// ### it's inefficient to convert to QScriptValue and then to QVariant
916
return scriptValueToVariant(scriptValueFromJSCValue(value), targetType);
919
QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst)
922
QScriptValue arr = q->newArray(lst.size());
923
for (int i = 0; i < lst.size(); ++i)
924
arr.setProperty(i, QScriptValue(q, lst.at(i)));
928
QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr)
931
uint len = arr.property(QLatin1String("length")).toUInt32();
932
for (uint i = 0; i < len; ++i)
933
lst.append(arr.property(i).toString());
937
QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst)
940
QScriptValue arr = q->newArray(lst.size());
941
for (int i = 0; i < lst.size(); ++i)
942
arr.setProperty(i, scriptValueFromVariant(lst.at(i)));
946
QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr)
949
uint len = arr.property(QLatin1String("length")).toUInt32();
950
for (uint i = 0; i < len; ++i)
951
lst.append(arr.property(i).toVariant());
955
QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap)
958
QScriptValue obj = q->newObject();
959
QVariantMap::const_iterator it;
960
for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
961
obj.setProperty(it.key(), scriptValueFromVariant(it.value()));
965
QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj)
968
QScriptValueIterator it(obj);
969
while (it.hasNext()) {
971
vmap.insert(it.name(), it.value().toVariant());
976
JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
978
QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
980
return JSC::JSValue();
981
return info->prototype;
984
void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prototype)
986
QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
988
info = new QScriptTypeInfo();
989
m_typeInfos.insert(metaTypeId, info);
991
info->prototype = prototype;
994
QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame)
996
if (frame && frame->callerFrame()->hasHostCallFrameFlag() && !frame->callee()
997
&& frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) {
998
//skip the "fake" context created in Interpreter::execute.
999
frame = frame->callerFrame()->removeHostCallFrameFlag();
1001
return reinterpret_cast<QScriptContext *>(frame);
1004
JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context)
1006
return reinterpret_cast<JSC::ExecState*>(context);
1009
const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context)
1011
return reinterpret_cast<const JSC::ExecState*>(context);
1014
JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const
1016
return globalData->head;
1019
JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const
1021
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
1022
return glob->customGlobalObject;
1025
JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy()
1027
if (!originalGlobalObjectProxy) {
1028
JSC::ExecState* exec = currentFrame;
1029
originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
1031
return originalGlobalObjectProxy;
1034
JSC::JSObject *QScriptEnginePrivate::globalObject() const
1036
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
1037
if (glob->customGlobalObject)
1038
return glob->customGlobalObject;
1042
void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object)
1044
if (object == globalObject())
1046
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
1047
if (object == originalGlobalObjectProxy)
1048
glob->customGlobalObject = 0;
1050
Q_ASSERT(object != originalGlobalObject());
1051
glob->customGlobalObject = object;
1055
JSC::ExecState *QScriptEnginePrivate::globalExec() const
1057
return originalGlobalObject()->globalExec();
1063
If the given \a value is the original global object, returns the custom
1064
global object or a proxy to the original global object; otherwise returns \a
1067
JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value)
1069
if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject())
1071
Q_ASSERT(JSC::asObject(value) == originalGlobalObject());
1072
if (customGlobalObject())
1073
return customGlobalObject();
1074
if (!originalGlobalObjectProxy)
1075
originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
1076
return originalGlobalObjectProxy;
1080
Return the 'this' value for a given context
1082
JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame)
1084
if (frame->codeBlock() != 0) {
1085
return frame->thisValue();
1086
} else if(frame == frame->lexicalGlobalObject()->globalExec()) {
1087
return frame->globalThisValue();
1089
JSC::Register *thisRegister = thisRegisterForFrame(frame);
1090
return thisRegister->jsValue();
1094
JSC::Register* QScriptEnginePrivate::thisRegisterForFrame(JSC::ExecState *frame)
1096
Q_ASSERT(frame->codeBlock() == 0); // only for native calls
1097
return frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount();
1101
For native context, we use the ReturnValueRegister entry in the stackframe header to store flags.
1102
We can do that because this header is not used as the native function return their value thought C++
1104
when setting flags, NativeContext should always be set
1106
contextFlags returns 0 for non native context
1108
uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec)
1110
if (exec->codeBlock())
1111
return 0; //js function doesn't have flags
1113
return exec->returnValueRegister();
1116
void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags)
1118
Q_ASSERT(!exec->codeBlock());
1119
exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::Register::withInt(flags);
1123
void QScriptEnginePrivate::mark(JSC::MarkStack& markStack)
1125
markStack.append(originalGlobalObject());
1126
markStack.append(globalObject());
1127
if (originalGlobalObjectProxy)
1128
markStack.append(originalGlobalObjectProxy);
1130
if (qobjectPrototype)
1131
markStack.append(qobjectPrototype);
1132
if (qmetaobjectPrototype)
1133
markStack.append(qmetaobjectPrototype);
1134
if (variantPrototype)
1135
markStack.append(variantPrototype);
1138
QScriptValuePrivate *it;
1139
for (it = registeredScriptValues; it != 0; it = it->next) {
1141
markStack.append(it->jscValue);
1145
#ifndef QT_NO_QOBJECT
1147
QHash<QObject*, QScript::QObjectData*>::const_iterator it;
1148
for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) {
1149
QScript::QObjectData *qdata = it.value();
1150
qdata->mark(markStack);
1156
QHash<int, QScriptTypeInfo*>::const_iterator it;
1157
for (it = m_typeInfos.constBegin(); it != m_typeInfos.constEnd(); ++it) {
1158
if ((*it)->prototype)
1159
markStack.append((*it)->prototype);
1164
bool QScriptEnginePrivate::isCollecting() const
1166
return globalData->heap.isBusy();
1169
void QScriptEnginePrivate::collectGarbage()
1171
JSC::JSLock lock(false);
1172
globalData->heap.collect();
1175
QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const
1177
return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker);
1180
void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
1182
ownedAgents.removeOne(agent);
1183
if (activeAgent == agent) {
1184
QScriptEngineAgentPrivate::get(agent)->detach();
1189
#ifndef QT_NO_QOBJECT
1191
JSC::JSValue QScriptEnginePrivate::newQObject(
1192
QObject *object, QScriptEngine::ValueOwnership ownership,
1193
const QScriptEngine::QObjectWrapOptions &options)
1196
return JSC::jsNull();
1197
JSC::ExecState* exec = currentFrame;
1198
QScript::QObjectData *data = qobjectData(object);
1199
bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0;
1200
QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject;
1201
QScriptObject *result = 0;
1202
if (preferExisting) {
1203
result = data->findWrapper(ownership, opt);
1207
result = new (exec) QScriptObject(qobjectWrapperObjectStructure);
1209
data->registerWrapper(result, ownership, opt);
1210
result->setDelegate(new QScript::QObjectDelegate(object, ownership, options));
1211
/*if (setDefaultPrototype)*/ {
1212
const QMetaObject *meta = object->metaObject();
1214
QByteArray typeString = meta->className();
1215
typeString.append('*');
1216
int typeId = QMetaType::type(typeString);
1218
JSC::JSValue proto = defaultPrototype(typeId);
1220
result->setPrototype(proto);
1224
meta = meta->superClass();
1230
JSC::JSValue QScriptEnginePrivate::newQMetaObject(
1231
const QMetaObject *metaObject, JSC::JSValue ctor)
1234
return JSC::jsNull();
1235
JSC::ExecState* exec = currentFrame;
1236
QScript::QMetaObjectWrapperObject *result = new (exec) QScript::QMetaObjectWrapperObject(exec, metaObject, ctor, qmetaobjectWrapperObjectStructure);
1240
bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value,
1241
const QByteArray &targetType,
1244
if (!targetType.endsWith('*'))
1246
if (QObject *qobject = value.toQObject()) {
1247
int start = targetType.startsWith("const ") ? 6 : 0;
1248
QByteArray className = targetType.mid(start, targetType.size()-start-1);
1249
if (void *instance = qobject->qt_metacast(className)) {
1257
QScript::QObjectData *QScriptEnginePrivate::qobjectData(QObject *object)
1259
QHash<QObject*, QScript::QObjectData*>::const_iterator it;
1260
it = m_qobjectData.constFind(object);
1261
if (it != m_qobjectData.constEnd())
1264
QScript::QObjectData *data = new QScript::QObjectData(this);
1265
m_qobjectData.insert(object, data);
1266
QObject::connect(object, SIGNAL(destroyed(QObject*)),
1267
q_func(), SLOT(_q_objectDestroyed(QObject *)));
1271
void QScriptEnginePrivate::_q_objectDestroyed(QObject *object)
1273
QHash<QObject*, QScript::QObjectData*>::iterator it;
1274
it = m_qobjectData.find(object);
1275
Q_ASSERT(it != m_qobjectData.end());
1276
QScript::QObjectData *data = it.value();
1277
m_qobjectData.erase(it);
1281
void QScriptEnginePrivate::disposeQObject(QObject *object)
1284
/* if (isCollecting()) {
1285
// wait until we're done with GC before deleting it
1286
int index = m_qobjectsToBeDeleted.indexOf(object);
1288
m_qobjectsToBeDeleted.append(object);
1294
void QScriptEnginePrivate::emitSignalHandlerException()
1297
emit q->signalHandlerException(q->uncaughtException());
1300
bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal,
1301
JSC::JSValue receiver, JSC::JSValue function,
1302
Qt::ConnectionType type)
1306
const QMetaObject *meta = sender->metaObject();
1307
int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
1310
return scriptConnect(sender, index, receiver, function, /*wrapper=*/JSC::JSValue(), type);
1313
bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal,
1314
JSC::JSValue receiver, JSC::JSValue function)
1318
const QMetaObject *meta = sender->metaObject();
1319
int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
1322
return scriptDisconnect(sender, index, receiver, function);
1325
bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex,
1326
JSC::JSValue receiver, JSC::JSValue function,
1327
JSC::JSValue senderWrapper,
1328
Qt::ConnectionType type)
1330
QScript::QObjectData *data = qobjectData(sender);
1331
return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type);
1334
bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex,
1335
JSC::JSValue receiver, JSC::JSValue function)
1337
QScript::QObjectData *data = qobjectData(sender);
1340
return data->removeSignalHandler(sender, signalIndex, receiver, function);
1343
bool QScriptEnginePrivate::scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
1344
JSC::JSValue function, Qt::ConnectionType type)
1346
QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
1347
int index = fun->mostGeneralMethod();
1348
return scriptConnect(fun->qobject(), index, receiver, function, fun->wrapperObject(), type);
1351
bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
1352
JSC::JSValue function)
1354
QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
1355
int index = fun->mostGeneralMethod();
1356
return scriptDisconnect(fun->qobject(), index, receiver, function);
1361
void QScriptEnginePrivate::detachAllRegisteredScriptValues()
1363
QScriptValuePrivate *it;
1364
QScriptValuePrivate *next;
1365
for (it = registeredScriptValues; it != 0; it = next) {
1366
it->detachFromEngine();
1371
registeredScriptValues = 0;
1374
void QScriptEnginePrivate::detachAllRegisteredScriptStrings()
1376
QScriptStringPrivate *it;
1377
QScriptStringPrivate *next;
1378
for (it = registeredScriptStrings; it != 0; it = next) {
1379
it->detachFromEngine();
1384
registeredScriptStrings = 0;
1387
#ifdef QT_NO_QOBJECT
1389
QScriptEngine::QScriptEngine()
1390
: d_ptr(new QScriptEnginePrivate)
1392
d_ptr->q_ptr = this;
1397
QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
1400
d_ptr->q_ptr = this;
1405
Constructs a QScriptEngine object.
1407
The globalObject() is initialized to have properties as described in
1408
\l{ECMA-262}, Section 15.1.
1410
QScriptEngine::QScriptEngine()
1411
: QObject(*new QScriptEnginePrivate, 0)
1416
Constructs a QScriptEngine object with the given \a parent.
1418
The globalObject() is initialized to have properties as described in
1419
\l{ECMA-262}, Section 15.1.
1422
QScriptEngine::QScriptEngine(QObject *parent)
1423
: QObject(*new QScriptEnginePrivate, parent)
1429
QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
1430
: QObject(dd, parent)
1436
Destroys this QScriptEngine.
1438
QScriptEngine::~QScriptEngine()
1440
#ifdef QT_NO_QOBJECT
1447
Returns this engine's Global Object.
1449
By default, the Global Object contains the built-in objects that are
1450
part of \l{ECMA-262}, such as Math, Date and String. Additionally,
1451
you can set properties of the Global Object to make your own
1452
extensions available to all script code. Non-local variables in
1453
script code will be created as properties of the Global Object, as
1454
well as local variables in global code.
1456
QScriptValue QScriptEngine::globalObject() const
1458
Q_D(const QScriptEngine);
1459
JSC::JSObject *result = d->globalObject();
1460
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
1466
Sets this engine's Global Object to be the given \a object.
1467
If \a object is not a valid script object, this function does
1470
When setting a custom global object, you may want to use
1471
QScriptValueIterator to copy the properties of the standard Global
1472
Object; alternatively, you can set the internal prototype of your
1473
custom object to be the original Global Object.
1475
void QScriptEngine::setGlobalObject(const QScriptValue &object)
1478
if (!object.isObject())
1480
JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
1481
d->setGlobalObject(jscObject);
1485
Returns a QScriptValue of the primitive type Null.
1487
\sa undefinedValue()
1489
QScriptValue QScriptEngine::nullValue()
1492
return d->scriptValueFromJSCValue(JSC::jsNull());
1496
Returns a QScriptValue of the primitive type Undefined.
1500
QScriptValue QScriptEngine::undefinedValue()
1503
return d->scriptValueFromJSCValue(JSC::jsUndefined());
1507
Creates a constructor function from \a fun, with the given \a length.
1508
The \c{prototype} property of the resulting function is set to be the
1509
given \a prototype. The \c{constructor} property of \a prototype is
1510
set to be the resulting function.
1512
When a function is called as a constructor (e.g. \c{new Foo()}), the
1513
`this' object associated with the function call is the new object
1514
that the function is expected to initialize; the prototype of this
1515
default constructed object will be the function's public
1516
\c{prototype} property. If you always want the function to behave as
1517
a constructor (e.g. \c{Foo()} should also create a new object), or
1518
if you need to create your own object rather than using the default
1519
`this' object, you should make sure that the prototype of your
1520
object is set correctly; either by setting it manually, or, when
1521
wrapping a custom type, by having registered the defaultPrototype()
1522
of that type. Example:
1524
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
1526
To wrap a custom type and provide a constructor for it, you'd typically
1527
do something like this:
1529
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
1531
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
1532
const QScriptValue &prototype,
1536
JSC::ExecState* exec = d->currentFrame;
1537
JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
1538
QScriptValue result = d->scriptValueFromJSCValue(function);
1539
result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);
1540
const_cast<QScriptValue&>(prototype)
1541
.setProperty(QLatin1String("constructor"), result,
1542
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1546
#ifndef QT_NO_REGEXP
1548
extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
1551
Creates a QtScript object of class RegExp with the given
1554
\sa QScriptValue::toRegExp()
1556
QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp)
1559
JSC::ExecState* exec = d->currentFrame;
1560
JSC::JSValue buf[2];
1561
JSC::ArgList args(buf, sizeof(buf));
1563
//convert the pattern to a ECMAScript pattern
1564
QString pattern = qt_regexp_toCanonical(regexp.pattern(), regexp.patternSyntax());
1565
if (regexp.isMinimal()) {
1566
QString ecmaPattern;
1567
int len = pattern.length();
1568
ecmaPattern.reserve(len);
1570
const QChar *wc = pattern.unicode();
1571
bool inBracket = false;
1575
switch (c.unicode()) {
1581
ecmaPattern += QLatin1Char('?');
1585
ecmaPattern += wc[i++];
1597
pattern = ecmaPattern;
1600
JSC::UString jscPattern = pattern;
1602
if (regexp.caseSensitivity() == Qt::CaseInsensitive)
1603
flags.append(QLatin1Char('i'));
1604
JSC::UString jscFlags = flags;
1605
buf[0] = JSC::jsString(exec, jscPattern);
1606
buf[1] = JSC::jsString(exec, jscFlags);
1607
JSC::JSObject* result = JSC::constructRegExp(exec, args);
1608
return d->scriptValueFromJSCValue(result);
1611
#endif // QT_NO_REGEXP
1614
Creates a QtScript object holding the given variant \a value.
1616
If a default prototype has been registered with the meta type id of
1617
\a value, then the prototype of the created object will be that
1618
prototype; otherwise, the prototype will be the Object prototype
1621
\sa setDefaultPrototype(), QScriptValue::toVariant()
1623
QScriptValue QScriptEngine::newVariant(const QVariant &value)
1626
JSC::ExecState* exec = d->currentFrame;
1627
QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure);
1628
obj->setDelegate(new QScript::QVariantDelegate(value));
1629
QScriptValue result = d->scriptValueFromJSCValue(obj);
1630
QScriptValue proto = defaultPrototype(value.userType());
1631
if (proto.isValid())
1632
result.setPrototype(proto);
1640
Initializes the given Qt Script \a object to hold the given variant
1641
\a value, and returns the \a object.
1643
This function enables you to "promote" a plain Qt Script object
1644
(created by the newObject() function) to a variant, or to replace
1645
the variant contained inside an object previously created by the
1646
newVariant() function.
1648
The prototype() of the \a object will remain unchanged.
1650
If \a object is not an object, this function behaves like the normal
1651
newVariant(), i.e. it creates a new script object and returns it.
1653
This function is useful when you want to provide a script
1654
constructor for a C++ type. If your constructor is invoked in a
1655
\c{new} expression (QScriptContext::isCalledAsConstructor() returns
1656
true), you can pass QScriptContext::thisObject() (the default
1657
constructed script object) to this function to initialize the new
1660
QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
1661
const QVariant &value)
1663
if (!object.isObject())
1664
return newVariant(value);
1665
JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue);
1666
if (!jscObject->inherits(&QScriptObject::info)) {
1667
qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
1668
return QScriptValue();
1670
QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
1671
if (!object.isVariant()) {
1672
jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
1674
QScriptValuePrivate::get(object)->setVariantValue(value);
1679
#ifndef QT_NO_QOBJECT
1681
Creates a QtScript object that wraps the given QObject \a
1682
object, using the given \a ownership. The given \a options control
1683
various aspects of the interaction with the resulting script object.
1685
Signals and slots, properties and children of \a object are
1686
available as properties of the created QScriptValue. For more
1687
information, see the \l{QtScript} documentation.
1689
If \a object is a null pointer, this function returns nullValue().
1691
If a default prototype has been registered for the \a object's class
1692
(or its superclass, recursively), the prototype of the new script
1693
object will be set to be that default prototype.
1695
If the given \a object is deleted outside of QtScript's control, any
1696
attempt to access the deleted QObject's members through the QtScript
1697
wrapper object (either by script code or C++) will result in a
1700
\sa QScriptValue::toQObject()
1702
QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
1703
const QObjectWrapOptions &options)
1706
JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
1707
return d->scriptValueFromJSCValue(jscQObject);
1714
Initializes the given \a scriptObject to hold the given \a qtObject,
1715
and returns the \a scriptObject.
1717
This function enables you to "promote" a plain Qt Script object
1718
(created by the newObject() function) to a QObject proxy, or to
1719
replace the QObject contained inside an object previously created by
1720
the newQObject() function.
1722
The prototype() of the \a scriptObject will remain unchanged.
1724
If \a scriptObject is not an object, this function behaves like the
1725
normal newQObject(), i.e. it creates a new script object and returns
1728
This function is useful when you want to provide a script
1729
constructor for a QObject-based class. If your constructor is
1730
invoked in a \c{new} expression
1731
(QScriptContext::isCalledAsConstructor() returns true), you can pass
1732
QScriptContext::thisObject() (the default constructed script object)
1733
to this function to initialize the new object.
1735
QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
1737
ValueOwnership ownership,
1738
const QObjectWrapOptions &options)
1740
if (!scriptObject.isObject())
1741
return newQObject(qtObject, ownership, options);
1742
JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
1743
if (!jscObject->inherits(&QScriptObject::info)) {
1744
qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
1745
return QScriptValue();
1747
QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
1748
if (!scriptObject.isQObject()) {
1749
jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
1751
QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
1752
delegate->setValue(qtObject);
1753
delegate->setOwnership(ownership);
1754
delegate->setOptions(options);
1756
return scriptObject;
1759
#endif // QT_NO_QOBJECT
1762
Creates a QtScript object of class Object.
1764
The prototype of the created object will be the Object
1767
\sa newArray(), QScriptValue::setProperty()
1769
QScriptValue QScriptEngine::newObject()
1772
JSC::ExecState* exec = d->currentFrame;
1773
JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure);
1774
return d->scriptValueFromJSCValue(result);
1781
Creates a QtScript Object of the given class, \a scriptClass.
1783
The prototype of the created object will be the Object
1786
\a data, if specified, is set as the internal data of the
1787
new object (using QScriptValue::setData()).
1789
\sa QScriptValue::scriptClass()
1791
QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
1792
const QScriptValue &data)
1795
JSC::ExecState* exec = d->currentFrame;
1796
QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
1797
result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
1798
QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
1799
scriptObject.setData(data);
1800
QScriptValue proto = scriptClass->prototype();
1801
if (proto.isValid())
1802
scriptObject.setPrototype(proto);
1803
return scriptObject;
1809
QScriptValue QScriptEngine::newActivationObject()
1811
qWarning("QScriptEngine::newActivationObject() not implemented");
1812
// ### JSActivation or JSVariableObject?
1813
return QScriptValue();
1817
Creates a QScriptValue that wraps a native (C++) function. \a fun
1818
must be a C++ function with signature QScriptEngine::FunctionSignature. \a
1819
length is the number of arguments that \a fun expects; this becomes
1820
the \c{length} property of the created QScriptValue.
1822
Note that \a length only gives an indication of the number of
1823
arguments that the function expects; an actual invocation of a
1824
function can include any number of arguments. You can check the
1825
\l{QScriptContext::argumentCount()}{argumentCount()} of the
1826
QScriptContext associated with the invocation to determine the
1827
actual number of arguments passed.
1829
A \c{prototype} property is automatically created for the resulting
1830
function object, to provide for the possibility that the function
1831
will be used as a constructor.
1833
By combining newFunction() and the property flags
1834
QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
1835
can create script object properties that behave like normal
1836
properties in script code, but are in fact accessed through
1837
functions (analogous to how properties work in \l{Qt's Property
1840
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
1842
When the property \c{foo} of the script object is subsequently
1843
accessed in script code, \c{getSetFoo()} will be invoked to handle
1844
the access. In this particular case, we chose to store the "real"
1845
value of \c{foo} as a property of the accessor function itself; you
1846
are of course free to do whatever you like in this function.
1848
In the above example, a single native function was used to handle
1849
both reads and writes to the property; the argument count is used to
1850
determine if we are handling a read or write. You can also use two
1851
separate functions; just specify the relevant flag
1852
(QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
1853
setting the property, e.g.:
1855
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
1857
\sa QScriptValue::call()
1859
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
1862
JSC::ExecState* exec = d->currentFrame;
1863
JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
1864
QScriptValue result = d->scriptValueFromJSCValue(function);
1865
QScriptValue proto = newObject();
1866
result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
1867
proto.setProperty(QLatin1String("constructor"), result,
1868
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1876
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
1879
JSC::ExecState* exec = d->currentFrame;
1880
JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
1881
QScriptValue result = d->scriptValueFromJSCValue(function);
1882
QScriptValue proto = newObject();
1883
result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
1884
proto.setProperty(QLatin1String("constructor"), result,
1885
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1890
Creates a QtScript object of class Array with the given \a length.
1894
QScriptValue QScriptEngine::newArray(uint length)
1897
JSC::ExecState* exec = d->currentFrame;
1898
JSC::JSArray* result = JSC::constructEmptyArray(exec, length);
1899
return d->scriptValueFromJSCValue(result);
1903
Creates a QtScript object of class RegExp with the given
1904
\a pattern and \a flags.
1906
The legal flags are 'g' (global), 'i' (ignore case), and 'm'
1909
QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
1912
JSC::ExecState* exec = d->currentFrame;
1913
JSC::JSValue buf[2];
1914
JSC::ArgList args(buf, sizeof(buf));
1915
JSC::UString jscPattern = pattern;
1916
QString strippedFlags;
1917
if (flags.contains(QLatin1Char('i')))
1918
strippedFlags += QLatin1Char('i');
1919
if (flags.contains(QLatin1Char('m')))
1920
strippedFlags += QLatin1Char('m');
1921
if (flags.contains(QLatin1Char('g')))
1922
strippedFlags += QLatin1Char('g');
1923
JSC::UString jscFlags = strippedFlags;
1924
buf[0] = JSC::jsString(exec, jscPattern);
1925
buf[1] = JSC::jsString(exec, jscFlags);
1926
JSC::JSObject* result = JSC::constructRegExp(exec, args);
1927
return d->scriptValueFromJSCValue(result);
1931
Creates a QtScript object of class Date with the given
1932
\a value (the number of milliseconds since 01 January 1970,
1935
QScriptValue QScriptEngine::newDate(qsreal value)
1938
JSC::ExecState* exec = d->currentFrame;
1939
JSC::JSValue val = JSC::jsNumber(exec, value);
1940
JSC::ArgList args(&val, 1);
1941
JSC::JSObject *result = JSC::constructDate(exec, args);
1942
return d->scriptValueFromJSCValue(result);
1946
Creates a QtScript object of class Date from the given \a value.
1948
\sa QScriptValue::toDateTime()
1950
QScriptValue QScriptEngine::newDate(const QDateTime &value)
1952
return newDate(QScript::FromDateTime(value));
1955
#ifndef QT_NO_QOBJECT
1957
Creates a QtScript object that represents a QObject class, using the
1958
the given \a metaObject and constructor \a ctor.
1960
Enums of \a metaObject (declared with Q_ENUMS) are available as
1961
properties of the created QScriptValue. When the class is called as
1962
a function, \a ctor will be called to create a new instance of the
1967
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27
1969
\sa newQObject(), scriptValueFromQMetaObject()
1971
QScriptValue QScriptEngine::newQMetaObject(
1972
const QMetaObject *metaObject, const QScriptValue &ctor)
1975
JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor);
1976
JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor);
1977
return d->scriptValueFromJSCValue(jscQMetaObject);
1981
\fn QScriptValue QScriptEngine::scriptValueFromQMetaObject()
1983
Creates a QScriptValue that represents the Qt class \c{T}.
1985
This function is used in combination with one of the
1986
Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example:
1988
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13
1990
\warning This function is not available with MSVC 6. Use
1991
qScriptValueFromQMetaObject() instead if you need to support that version
1994
\sa QScriptEngine::newQMetaObject()
1998
\fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine)
2000
\relates QScriptEngine
2002
Uses \a engine to create a QScriptValue that represents the Qt class
2005
This function is equivalent to
2006
QScriptEngine::scriptValueFromQMetaObject(). It is provided as a
2007
work-around for MSVC 6, which doesn't support member template
2010
\sa QScriptEngine::newQMetaObject()
2012
#endif // QT_NO_QOBJECT
2017
Returns true if \a program can be evaluated; i.e. the code is
2018
sufficient to determine whether it appears to be a syntactically
2019
correct program, or contains a syntax error.
2021
This function returns false if \a program is incomplete; i.e. the
2022
input is syntactically correct up to the point where the input is
2025
Note that this function only does a static check of \a program;
2026
e.g. it does not check whether references to variables are
2029
A typical usage of canEvaluate() is to implement an interactive
2030
interpreter for QtScript. The user is repeatedly queried for
2031
individual lines of code; the lines are concatened internally, and
2032
only when canEvaluate() returns true for the resulting program is it
2033
passed to evaluate().
2035
The following are some examples to illustrate the behavior of
2036
canEvaluate(). (Note that all example inputs are assumed to have an
2037
explicit newline as their last character, since otherwise the
2038
QtScript parser would automatically insert a semi-colon character at
2039
the end of the input, and this could cause canEvaluate() to produce
2043
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14
2044
canEvaluate() will return true, since the program appears to be complete.
2047
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15
2048
canEvaluate() will return false, since the if-statement is not complete,
2049
but is syntactically correct so far.
2052
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16
2053
canEvaluate() will return true, but evaluate() will throw a
2054
SyntaxError given the same input.
2057
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17
2058
canEvaluate() will return true, even though the code is clearly not
2059
syntactically valid QtScript code. evaluate() will throw a
2060
SyntaxError when this code is evaluated.
2063
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18
2064
canEvaluate() will return true, but evaluate() will throw a
2065
ReferenceError if \c{foo} is not defined in the script
2068
\sa evaluate(), checkSyntax()
2070
bool QScriptEngine::canEvaluate(const QString &program) const
2072
return QScriptEnginePrivate::canEvaluate(program);
2076
bool QScriptEnginePrivate::canEvaluate(const QString &program)
2078
QScript::SyntaxChecker checker;
2079
QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
2080
return (result.state != QScript::SyntaxChecker::Intermediate);
2086
Checks the syntax of the given \a program. Returns a
2087
QScriptSyntaxCheckResult object that contains the result of the check.
2089
QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
2091
return QScriptEnginePrivate::checkSyntax(program);
2094
QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program)
2096
QScript::SyntaxChecker checker;
2097
QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
2098
QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate();
2099
switch (result.state) {
2100
case QScript::SyntaxChecker::Error:
2101
p->state = QScriptSyntaxCheckResult::Error;
2103
case QScript::SyntaxChecker::Intermediate:
2104
p->state = QScriptSyntaxCheckResult::Intermediate;
2106
case QScript::SyntaxChecker::Valid:
2107
p->state = QScriptSyntaxCheckResult::Valid;
2110
p->errorLineNumber = result.errorLineNumber;
2111
p->errorColumnNumber = result.errorColumnNumber;
2112
p->errorMessage = result.errorMessage;
2113
return QScriptSyntaxCheckResult(p);
2119
Evaluates \a program, using \a lineNumber as the base line number,
2120
and returns the result of the evaluation.
2122
The script code will be evaluated in the current context.
2124
The evaluation of \a program can cause an exception in the
2125
engine; in this case the return value will be the exception
2126
that was thrown (typically an \c{Error} object). You can call
2127
hasUncaughtException() to determine if an exception occurred in
2128
the last call to evaluate().
2130
\a lineNumber is used to specify a starting line number for \a
2131
program; line number information reported by the engine that pertain
2132
to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
2133
based on this argument. For example, if \a program consists of two
2134
lines of code, and the statement on the second line causes a script
2135
exception, uncaughtExceptionLineNumber() would return the given \a
2136
lineNumber plus one. When no starting line number is specified, line
2137
numbers will be 1-based.
2139
\a fileName is used for error reporting. For example in error objects
2140
the file name is accessible through the "fileName" property if it's
2141
provided with this function.
2143
\sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation()
2146
QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber)
2150
JSC::JSLock lock(false); // ### hmmm
2151
QBoolBlocker inEval(d->inEval, true);
2152
currentContext()->activationObject(); //force the creation of a context for native function;
2154
JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
2156
JSC::UString jscProgram = program;
2157
JSC::UString jscFileName = fileName;
2158
JSC::ExecState* exec = d->currentFrame;
2159
WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
2160
= QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d);
2161
intptr_t sourceId = provider->asID();
2162
JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null.
2165
debugger->evaluateStart(sourceId);
2167
exec->clearException();
2168
JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
2170
JSC::EvalExecutable executable(exec, source);
2171
JSC::JSObject* error = executable.compile(exec, exec->scopeChain());
2173
exec->setException(error);
2176
debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, error), sourceId, false);
2177
debugger->evaluateStop(error, sourceId);
2180
return d->scriptValueFromJSCValue(error);
2183
JSC::JSValue thisValue = d->thisForContext(exec);
2184
JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
2185
JSC::JSValue exceptionValue;
2186
d->timeoutChecker()->setShouldAbort(false);
2187
if (d->processEventsInterval > 0)
2188
d->timeoutChecker()->reset();
2189
JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
2191
if (d->timeoutChecker()->shouldAbort()) {
2192
if (d->abortResult.isError())
2193
exec->setException(d->scriptValueToJSCValue(d->abortResult));
2196
debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId);
2198
return d->abortResult;
2201
if (exceptionValue) {
2202
exec->setException(exceptionValue);
2205
debugger->evaluateStop(exceptionValue, sourceId);
2207
return d->scriptValueFromJSCValue(exceptionValue);
2211
debugger->evaluateStop(result, sourceId);
2213
Q_ASSERT(!exec->hadException());
2214
return d->scriptValueFromJSCValue(result);
2219
Returns the current context.
2221
The current context is typically accessed to retrieve the arguments
2222
and `this' object in native functions; for convenience, it is
2223
available as the first argument in QScriptEngine::FunctionSignature.
2225
QScriptContext *QScriptEngine::currentContext() const
2227
Q_D(const QScriptEngine);
2228
return const_cast<QScriptEnginePrivate*>(d)->contextForFrame(d->currentFrame);
2232
Enters a new execution context and returns the associated
2233
QScriptContext object.
2235
Once you are done with the context, you should call popContext() to
2236
restore the old context.
2238
By default, the `this' object of the new context is the Global Object.
2239
The context's \l{QScriptContext::callee()}{callee}() will be invalid.
2241
This function is useful when you want to evaluate script code
2242
as if it were the body of a function. You can use the context's
2243
\l{QScriptContext::activationObject()}{activationObject}() to initialize
2244
local variables that will be available to scripts. Example:
2246
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19
2248
In the above example, the new variable "tmp" defined in the script
2249
will be local to the context; in other words, the script doesn't
2250
have any effect on the global environment.
2252
Returns 0 in case of stack overflow
2256
QScriptContext *QScriptEngine::pushContext()
2260
JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
2261
JSC::ArgList(), /*callee = */0);
2264
agent()->contextPush();
2266
return d->contextForFrame(newFrame);
2270
push a context for a native function.
2271
JSC native function doesn't have different stackframe or context. so we need to create one.
2273
use popContext right after to go back to the previous context the context if no stack overflow has hapenned
2275
exec is the current top frame.
2277
return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
2279
JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
2280
const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor)
2282
JSC::JSValue thisObject = _thisObject;
2283
if (calledAsConstructor) {
2284
//JSC doesn't create default created object for native functions. so we do it
2285
JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype);
2286
JSC::Structure *structure = prototype.isObject() ? JSC::asObject(prototype)->inheritorID()
2287
: originalGlobalObject()->emptyObjectStructure();
2288
thisObject = new (exec) QScriptObject(structure);
2291
int flags = NativeContext;
2292
if (calledAsConstructor)
2293
flags |= CalledAsConstructorContext;
2296
JSC::CallFrame *newCallFrame = exec;
2297
if (callee == 0 //called from public QScriptEngine::pushContext
2298
|| exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
2299
|| (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us.
2300
//We need to check if the Interpreter might have already created a frame for function called from JS.
2301
JSC::Interpreter *interp = exec->interpreter();
2302
JSC::Register *oldEnd = interp->registerFile().end();
2303
int argc = args.size() + 1; //add "this"
2304
JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize;
2305
if (!interp->registerFile().grow(newEnd))
2306
return 0; //### Stack overflow
2307
newCallFrame = JSC::CallFrame::create(oldEnd);
2308
newCallFrame[0] = thisObject;
2310
JSC::ArgList::const_iterator it;
2311
for (it = args.begin(); it != args.end(); ++it)
2312
newCallFrame[++dst] = *it;
2313
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
2314
newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
2316
setContextFlags(newCallFrame, flags);
2318
exec->registers()[JSC::RegisterFile::Callee] = JSC::JSValue(callee); //JIT let the callee set the 'callee'
2320
if (calledAsConstructor) {
2321
//update the new created this
2322
JSC::Register* thisRegister = thisRegisterForFrame(newCallFrame);
2323
*thisRegister = thisObject;
2326
currentFrame = newCallFrame;
2327
return newCallFrame;
2332
Pops the current execution context and restores the previous one.
2333
This function must be used in conjunction with pushContext().
2337
void QScriptEngine::popContext()
2340
agent()->contextPop();
2342
if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
2343
|| !currentContext()->parentContext()) {
2344
qWarning("QScriptEngine::popContext() doesn't match with pushContext()");
2352
counter part of QScriptEnginePrivate::pushContext
2354
void QScriptEnginePrivate::popContext()
2356
uint flags = contextFlags(currentFrame);
2357
bool hasScope = flags & HasScopeContext;
2358
if (flags & ShouldRestoreCallFrame) { //normal case
2359
JSC::RegisterFile ®isterFile = currentFrame->interpreter()->registerFile();
2360
JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
2362
currentFrame->scopeChain()->pop()->deref();
2363
registerFile.shrink(newEnd);
2364
} else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it.
2365
currentFrame->setScopeChain(currentFrame->scopeChain()->pop());
2366
currentFrame->scopeChain()->deref();
2368
currentFrame = currentFrame->callerFrame();
2372
Returns true if the last script evaluation resulted in an uncaught
2373
exception; otherwise returns false.
2375
The exception state is cleared when evaluate() is called.
2377
\sa uncaughtException(), uncaughtExceptionLineNumber(),
2378
uncaughtExceptionBacktrace()
2380
bool QScriptEngine::hasUncaughtException() const
2382
Q_D(const QScriptEngine);
2383
JSC::ExecState* exec = d->globalExec();
2384
return exec->hadException();
2388
Returns the current uncaught exception, or an invalid QScriptValue
2389
if there is no uncaught exception.
2391
The exception value is typically an \c{Error} object; in that case,
2392
you can call toString() on the return value to obtain an error
2395
\sa hasUncaughtException(), uncaughtExceptionLineNumber(),
2396
uncaughtExceptionBacktrace()
2398
QScriptValue QScriptEngine::uncaughtException() const
2400
Q_D(const QScriptEngine);
2401
JSC::ExecState* exec = d->globalExec();
2402
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(exec->exception());
2406
Returns the line number where the last uncaught exception occurred.
2408
Line numbers are 1-based, unless a different base was specified as
2409
the second argument to evaluate().
2411
\sa hasUncaughtException(), uncaughtExceptionBacktrace()
2413
int QScriptEngine::uncaughtExceptionLineNumber() const
2415
if (!hasUncaughtException())
2417
return uncaughtException().property(QLatin1String("lineNumber")).toInt32();
2421
Returns a human-readable backtrace of the last uncaught exception.
2423
Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
2425
\sa uncaughtException()
2427
QStringList QScriptEngine::uncaughtExceptionBacktrace() const
2429
if (!hasUncaughtException())
2430
return QStringList();
2431
// ### currently no way to get a full backtrace from JSC without installing a
2432
// debugger that reimplements exception() and store the backtrace there.
2433
QScriptValue value = uncaughtException();
2434
if (!value.isError())
2435
return QStringList();
2437
result.append(QString::fromLatin1("<anonymous>()@%0:%1")
2438
.arg(value.property(QLatin1String("fileName")).toString())
2439
.arg(value.property(QLatin1String("lineNumber")).toInt32()));
2446
Clears any uncaught exceptions in this engine.
2448
\sa hasUncaughtException()
2450
void QScriptEngine::clearExceptions()
2453
JSC::ExecState* exec = d->currentFrame;
2454
exec->clearException();
2458
Returns the default prototype associated with the given \a metaTypeId,
2459
or an invalid QScriptValue if no default prototype has been set.
2461
\sa setDefaultPrototype()
2463
QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const
2465
Q_D(const QScriptEngine);
2466
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(d->defaultPrototype(metaTypeId));
2470
Sets the default prototype of the C++ type identified by the given
2471
\a metaTypeId to \a prototype.
2473
The default prototype provides a script interface for values of
2474
type \a metaTypeId when a value of that type is accessed from script
2475
code. Whenever the script engine (implicitly or explicitly) creates
2476
a QScriptValue from a value of type \a metaTypeId, the default
2477
prototype will be set as the QScriptValue's prototype.
2479
The \a prototype object itself may be constructed using one of two
2480
principal techniques; the simplest is to subclass QScriptable, which
2481
enables you to define the scripting API of the type through QObject
2482
properties and slots. Another possibility is to create a script
2483
object by calling newObject(), and populate the object with the
2484
desired properties (e.g. native functions wrapped with
2487
\sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example}
2489
void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype)
2492
d->setDefaultPrototype(metaTypeId, d->scriptValueToJSCValue(prototype));
2496
\typedef QScriptEngine::FunctionSignature
2497
\relates QScriptEngine
2499
The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
2501
A function with such a signature can be passed to
2502
QScriptEngine::newFunction() to wrap the function.
2506
\typedef QScriptEngine::FunctionWithArgSignature
2507
\relates QScriptEngine
2509
The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
2511
A function with such a signature can be passed to
2512
QScriptEngine::newFunction() to wrap the function.
2516
\typedef QScriptEngine::MarshalFunction
2521
\typedef QScriptEngine::DemarshalFunction
2528
QScriptValue QScriptEngine::create(int type, const void *ptr)
2531
return d->create(type, ptr);
2534
QScriptValue QScriptEnginePrivate::create(int type, const void *ptr)
2537
QScriptValue result;
2538
QScriptTypeInfo *info = m_typeInfos.value(type);
2539
if (info && info->marshal) {
2540
result = info->marshal(q_func(), ptr);
2542
// check if it's one of the types we know
2543
switch (QMetaType::Type(type)) {
2544
case QMetaType::Void:
2545
result = QScriptValue(QScriptValue::UndefinedValue);
2547
case QMetaType::Bool:
2548
result = QScriptValue(*reinterpret_cast<const bool*>(ptr));
2550
case QMetaType::Int:
2551
result = QScriptValue(*reinterpret_cast<const int*>(ptr));
2553
case QMetaType::UInt:
2554
result = QScriptValue(*reinterpret_cast<const uint*>(ptr));
2556
case QMetaType::LongLong:
2557
result = QScriptValue(qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
2559
case QMetaType::ULongLong:
2560
#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
2561
#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
2562
result = QScriptValue(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
2563
#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
2564
result = QScriptValue(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
2566
result = QScriptValue(qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
2569
case QMetaType::Double:
2570
result = QScriptValue(*reinterpret_cast<const double*>(ptr));
2572
case QMetaType::QString:
2573
result = QScriptValue(q_func(), *reinterpret_cast<const QString*>(ptr));
2575
case QMetaType::Float:
2576
result = QScriptValue(*reinterpret_cast<const float*>(ptr));
2578
case QMetaType::Short:
2579
result = QScriptValue(*reinterpret_cast<const short*>(ptr));
2581
case QMetaType::UShort:
2582
result = QScriptValue(*reinterpret_cast<const unsigned short*>(ptr));
2584
case QMetaType::Char:
2585
result = QScriptValue(*reinterpret_cast<const char*>(ptr));
2587
case QMetaType::UChar:
2588
result = QScriptValue(*reinterpret_cast<const unsigned char*>(ptr));
2590
case QMetaType::QChar:
2591
result = QScriptValue((*reinterpret_cast<const QChar*>(ptr)).unicode());
2593
case QMetaType::QStringList:
2594
result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr));
2596
case QMetaType::QVariantList:
2597
result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr));
2599
case QMetaType::QVariantMap:
2600
result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr));
2602
case QMetaType::QDateTime:
2603
result = q_func()->newDate(*reinterpret_cast<const QDateTime *>(ptr));
2605
case QMetaType::QDate:
2606
result = q_func()->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)));
2608
#ifndef QT_NO_REGEXP
2609
case QMetaType::QRegExp:
2610
result = q_func()->newRegExp(*reinterpret_cast<const QRegExp *>(ptr));
2613
#ifndef QT_NO_QOBJECT
2614
case QMetaType::QObjectStar:
2615
case QMetaType::QWidgetStar:
2616
result = q_func()->newQObject(*reinterpret_cast<QObject* const *>(ptr));
2620
if (type == qMetaTypeId<QScriptValue>()) {
2621
result = *reinterpret_cast<const QScriptValue*>(ptr);
2622
if (!result.isValid())
2623
result = QScriptValue(QScriptValue::UndefinedValue);
2626
#ifndef QT_NO_QOBJECT
2627
// lazy registration of some common list types
2628
else if (type == qMetaTypeId<QObjectList>()) {
2629
qScriptRegisterSequenceMetaType<QObjectList>(q_func());
2630
return create(type, ptr);
2633
else if (type == qMetaTypeId<QList<int> >()) {
2634
qScriptRegisterSequenceMetaType<QList<int> >(q_func());
2635
return create(type, ptr);
2639
QByteArray typeName = QMetaType::typeName(type);
2640
if (typeName == "QVariant")
2641
result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr));
2642
if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
2643
result = QScriptValue(QScriptValue::NullValue);
2645
result = q_func()->newVariant(QVariant(type, ptr));
2649
if (result.isObject() && info && info->prototype
2650
&& JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) {
2651
result.setPrototype(scriptValueFromJSCValue(info->prototype));
2656
bool QScriptEnginePrivate::convert(const QScriptValue &value,
2657
int type, void *ptr,
2658
QScriptEnginePrivate *eng)
2660
if (!eng && value.engine())
2661
eng = QScriptEnginePrivate::get(value.engine());
2663
QScriptTypeInfo *info = eng->m_typeInfos.value(type);
2664
if (info && info->demarshal) {
2665
info->demarshal(value, ptr);
2670
// check if it's one of the types we know
2671
switch (QMetaType::Type(type)) {
2672
case QMetaType::Bool:
2673
*reinterpret_cast<bool*>(ptr) = value.toBoolean();
2675
case QMetaType::Int:
2676
*reinterpret_cast<int*>(ptr) = value.toInt32();
2678
case QMetaType::UInt:
2679
*reinterpret_cast<uint*>(ptr) = value.toUInt32();
2681
case QMetaType::LongLong:
2682
*reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger());
2684
case QMetaType::ULongLong:
2685
*reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger());
2687
case QMetaType::Double:
2688
*reinterpret_cast<double*>(ptr) = value.toNumber();
2690
case QMetaType::QString:
2691
if (value.isUndefined() || value.isNull())
2692
*reinterpret_cast<QString*>(ptr) = QString();
2694
*reinterpret_cast<QString*>(ptr) = value.toString();
2696
case QMetaType::Float:
2697
*reinterpret_cast<float*>(ptr) = value.toNumber();
2699
case QMetaType::Short:
2700
*reinterpret_cast<short*>(ptr) = short(value.toInt32());
2702
case QMetaType::UShort:
2703
*reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();
2705
case QMetaType::Char:
2706
*reinterpret_cast<char*>(ptr) = char(value.toInt32());
2708
case QMetaType::UChar:
2709
*reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32());
2711
case QMetaType::QChar:
2712
if (value.isString()) {
2713
QString str = value.toString();
2714
*reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
2716
*reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16());
2719
case QMetaType::QDateTime:
2720
if (value.isDate()) {
2721
*reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();
2724
case QMetaType::QDate:
2725
if (value.isDate()) {
2726
*reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();
2729
#ifndef QT_NO_REGEXP
2730
case QMetaType::QRegExp:
2731
if (value.isRegExp()) {
2732
*reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();
2736
#ifndef QT_NO_QOBJECT
2737
case QMetaType::QObjectStar:
2738
if (value.isQObject() || value.isNull()) {
2739
*reinterpret_cast<QObject* *>(ptr) = value.toQObject();
2742
case QMetaType::QWidgetStar:
2743
if (value.isQObject() || value.isNull()) {
2744
QObject *qo = value.toQObject();
2745
if (!qo || qo->isWidgetType()) {
2746
*reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
2751
case QMetaType::QStringList:
2752
if (value.isArray()) {
2753
*reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value);
2756
case QMetaType::QVariantList:
2757
if (value.isArray()) {
2758
*reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value);
2761
case QMetaType::QVariantMap:
2762
if (value.isObject()) {
2763
*reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value);
2770
QByteArray name = QMetaType::typeName(type);
2771
#ifndef QT_NO_QOBJECT
2772
if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr)))
2775
if (value.isVariant() && name.endsWith('*')) {
2776
int valueType = QMetaType::type(name.left(name.size()-1));
2777
QVariant &var = QScriptValuePrivate::get(value)->variantValue();
2778
if (valueType == var.userType()) {
2779
*reinterpret_cast<void* *>(ptr) = var.data();
2782
// look in the prototype chain
2783
QScriptValue proto = value.prototype();
2784
while (proto.isObject()) {
2785
bool canCast = false;
2786
if (proto.isVariant()) {
2787
canCast = (type == proto.toVariant().userType())
2788
|| (valueType && (valueType == proto.toVariant().userType()));
2790
#ifndef QT_NO_QOBJECT
2791
else if (proto.isQObject()) {
2792
QByteArray className = name.left(name.size()-1);
2793
if (QObject *qobject = proto.toQObject())
2794
canCast = qobject->qt_metacast(className) != 0;
2798
QByteArray varTypeName = QMetaType::typeName(var.userType());
2799
if (varTypeName.endsWith('*'))
2800
*reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data());
2802
*reinterpret_cast<void* *>(ptr) = var.data();
2805
proto = proto.prototype();
2808
} else if (value.isNull() && name.endsWith('*')) {
2809
*reinterpret_cast<void* *>(ptr) = 0;
2811
} else if (type == qMetaTypeId<QScriptValue>()) {
2814
*reinterpret_cast<QScriptValue*>(ptr) = value;
2816
} else if (name == "QVariant") {
2817
*reinterpret_cast<QVariant*>(ptr) = value.toVariant();
2821
// lazy registration of some common list types
2822
#ifndef QT_NO_QOBJECT
2823
else if (type == qMetaTypeId<QObjectList>()) {
2826
qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
2827
return convert(value, type, ptr, eng);
2830
else if (type == qMetaTypeId<QList<int> >()) {
2833
qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
2834
return convert(value, type, ptr, eng);
2838
if (!name.isEmpty()) {
2839
qWarning("QScriptEngine::convert: unable to convert value to type `%s'",
2846
bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
2848
QScriptTypeInfo *info = m_typeInfos.value(type);
2849
return info && (info->demarshal != 0);
2855
bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr)
2858
return QScriptEnginePrivate::convert(value, type, ptr, d);
2864
bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
2866
return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0);
2872
void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
2873
DemarshalFunction df,
2874
const QScriptValue &prototype)
2877
QScriptTypeInfo *info = d->m_typeInfos.value(type);
2879
info = new QScriptTypeInfo();
2880
d->m_typeInfos.insert(type, info);
2883
info->demarshal = df;
2884
info->prototype = d->scriptValueToJSCValue(prototype);
2890
Installs translator functions on the given \a object, or on the Global
2891
Object if no object is specified.
2893
The relation between Qt Script translator functions and C++ translator
2894
functions is described in the following table:
2897
\header \o Script Function \o Corresponding C++ Function
2898
\row \o qsTr() \o QObject::tr()
2899
\row \o QT_TR_NOOP() \o QT_TR_NOOP()
2900
\row \o qsTranslate() \o QCoreApplication::translate()
2901
\row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
2904
\sa {Internationalization with Qt}
2906
void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
2909
JSC::ExecState* exec = d->currentFrame;
2910
JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
2911
JSC::JSGlobalObject *glob = d->originalGlobalObject();
2912
if (!jscObject || !jscObject.isObject())
2914
// unsigned attribs = JSC::DontEnum;
2915
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
2916
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
2917
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
2918
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
2920
glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
2924
Imports the given \a extension into this QScriptEngine. Returns
2925
undefinedValue() if the extension was successfully imported. You
2926
can call hasUncaughtException() to check if an error occurred; in
2927
that case, the return value is the value that was thrown by the
2928
exception (usually an \c{Error} object).
2930
QScriptEngine ensures that a particular extension is only imported
2931
once; subsequent calls to importExtension() with the same extension
2932
name will do nothing and return undefinedValue().
2934
\sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions}
2936
QScriptValue QScriptEngine::importExtension(const QString &extension)
2938
#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
2939
Q_UNUSED(extension);
2942
if (d->importedExtensions.contains(extension))
2943
return undefinedValue(); // already imported
2945
QScriptContext *context = currentContext();
2946
QCoreApplication *app = QCoreApplication::instance();
2948
return context->throwError(QLatin1String("No application object"));
2950
QObjectList staticPlugins = QPluginLoader::staticInstances();
2951
QStringList libraryPaths = app->libraryPaths();
2952
QString dot = QLatin1String(".");
2953
QStringList pathComponents = extension.split(dot);
2954
QString initDotJs = QLatin1String("__init__.js");
2957
for (int i = 0; i < pathComponents.count(); ++i) {
2960
ext.append(pathComponents.at(i));
2961
if (d->importedExtensions.contains(ext))
2962
continue; // already imported
2964
if (d->extensionsBeingImported.contains(ext)) {
2965
return context->throwError(QString::fromLatin1("recursive import of %0")
2968
d->extensionsBeingImported.insert(ext);
2970
QScriptExtensionInterface *iface = 0;
2971
QString initjsContents;
2972
QString initjsFileName;
2974
// look for the extension in static plugins
2975
for (int j = 0; j < staticPlugins.size(); ++j) {
2976
iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j));
2979
if (iface->keys().contains(ext))
2980
break; // use this one
2982
iface = 0; // keep looking
2986
// look for __init__.js resource
2987
QString path = QString::fromLatin1(":/qtscriptextension");
2988
for (int j = 0; j <= i; ++j) {
2989
path.append(QLatin1Char('/'));
2990
path.append(pathComponents.at(j));
2992
path.append(QLatin1Char('/'));
2993
path.append(initDotJs);
2995
if (file.open(QIODevice::ReadOnly)) {
2996
QTextStream ts(&file);
2997
initjsContents = ts.readAll();
2998
initjsFileName = path;
3003
if (!iface && initjsContents.isEmpty()) {
3004
// look for the extension in library paths
3005
for (int j = 0; j < libraryPaths.count(); ++j) {
3006
QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script");
3008
if (!dir.exists(dot))
3011
// look for C++ plugin
3012
QFileInfoList files = dir.entryInfoList(QDir::Files);
3013
for (int k = 0; k < files.count(); ++k) {
3014
QFileInfo entry = files.at(k);
3015
QString filePath = entry.canonicalFilePath();
3016
QPluginLoader loader(filePath);
3017
iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
3019
if (iface->keys().contains(ext))
3020
break; // use this one
3022
iface = 0; // keep looking
3026
// look for __init__.js in the corresponding dir
3027
QDir dirdir(libPath);
3028
bool dirExists = dirdir.exists();
3029
for (int k = 0; dirExists && (k <= i); ++k)
3030
dirExists = dirdir.cd(pathComponents.at(k));
3031
if (dirExists && dirdir.exists(initDotJs)) {
3032
QFile file(dirdir.canonicalPath()
3033
+ QDir::separator() + initDotJs);
3034
if (file.open(QIODevice::ReadOnly)) {
3035
QTextStream ts(&file);
3036
initjsContents = ts.readAll();
3037
initjsFileName = file.fileName();
3042
if (iface || !initjsContents.isEmpty())
3047
if (!iface && initjsContents.isEmpty()) {
3048
d->extensionsBeingImported.remove(ext);
3049
return context->throwError(
3050
QString::fromLatin1("Unable to import %0: no such extension")
3054
// initialize the extension in a new context
3055
QScriptContext *ctx = pushContext();
3056
ctx->setThisObject(globalObject());
3057
ctx->activationObject().setProperty(QLatin1String("__extension__"), ext,
3058
QScriptValue::ReadOnly | QScriptValue::Undeletable);
3059
ctx->activationObject().setProperty(QLatin1String("__setupPackage__"),
3060
newFunction(QScript::__setupPackage__));
3061
ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue));
3063
// the script is evaluated first
3064
if (!initjsContents.isEmpty()) {
3065
QScriptValue ret = evaluate(initjsContents, initjsFileName);
3066
if (hasUncaughtException()) {
3068
d->extensionsBeingImported.remove(ext);
3073
// next, the C++ plugin is called
3075
iface->initialize(ext, this);
3076
if (hasUncaughtException()) {
3077
QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
3079
d->extensionsBeingImported.remove(ext);
3084
// if the __postInit__ function has been set, we call it
3085
QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__"));
3086
if (postInit.isFunction()) {
3087
postInit.call(globalObject());
3088
if (hasUncaughtException()) {
3089
QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
3091
d->extensionsBeingImported.remove(ext);
3098
d->importedExtensions.insert(ext);
3099
d->extensionsBeingImported.remove(ext);
3101
#endif // QT_NO_QOBJECT
3102
return undefinedValue();
3108
Returns a list naming the available extensions that can be
3109
imported using the importExtension() function. This list includes
3110
extensions that have been imported.
3112
\sa importExtension(), importedExtensions()
3114
QStringList QScriptEngine::availableExtensions() const
3116
#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
3117
return QStringList();
3119
QCoreApplication *app = QCoreApplication::instance();
3121
return QStringList();
3123
QSet<QString> result;
3125
QObjectList staticPlugins = QPluginLoader::staticInstances();
3126
for (int i = 0; i < staticPlugins.size(); ++i) {
3127
QScriptExtensionInterface *iface;
3128
iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i));
3130
QStringList keys = iface->keys();
3131
for (int j = 0; j < keys.count(); ++j)
3132
result << keys.at(j);
3136
QStringList libraryPaths = app->libraryPaths();
3137
for (int i = 0; i < libraryPaths.count(); ++i) {
3138
QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script");
3143
// look for C++ plugins
3144
QFileInfoList files = dir.entryInfoList(QDir::Files);
3145
for (int j = 0; j < files.count(); ++j) {
3146
QFileInfo entry = files.at(j);
3147
QString filePath = entry.canonicalFilePath();
3148
QPluginLoader loader(filePath);
3149
QScriptExtensionInterface *iface;
3150
iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
3152
QStringList keys = iface->keys();
3153
for (int k = 0; k < keys.count(); ++k)
3154
result << keys.at(k);
3159
QString initDotJs = QLatin1String("__init__.js");
3160
QList<QFileInfo> stack;
3161
stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
3162
while (!stack.isEmpty()) {
3163
QFileInfo entry = stack.takeLast();
3164
QDir dd(entry.canonicalFilePath());
3165
if (dd.exists(initDotJs)) {
3166
QString rpath = dir.relativeFilePath(dd.canonicalPath());
3167
QStringList components = rpath.split(QLatin1Char('/'));
3168
result << components.join(QLatin1String("."));
3169
stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
3174
QStringList lst = result.toList();
3183
Returns a list naming the extensions that have been imported
3184
using the importExtension() function.
3186
\sa availableExtensions()
3188
QStringList QScriptEngine::importedExtensions() const
3190
Q_D(const QScriptEngine);
3191
QStringList lst = d->importedExtensions.toList();
3196
/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value)
3198
Creates a QScriptValue with the given \a value.
3200
Note that the template type \c{T} must be known to QMetaType.
3202
See \l{Conversion Between QtScript and C++ Types} for a
3203
description of the built-in type conversion provided by
3204
QtScript. By default, the types that are not specially handled by
3205
QtScript are represented as QVariants (e.g. the \a value is passed
3206
to newVariant()); you can change this behavior by installing your
3207
own type conversion functions with qScriptRegisterMetaType().
3209
\warning This function is not available with MSVC 6. Use
3210
qScriptValueFromValue() instead if you need to support that
3211
version of the compiler.
3213
\sa fromScriptValue(), qScriptRegisterMetaType()
3216
/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value)
3218
Returns the given \a value converted to the template type \c{T}.
3220
Note that \c{T} must be known to QMetaType.
3222
See \l{Conversion Between QtScript and C++ Types} for a
3223
description of the built-in type conversion provided by
3226
\warning This function is not available with MSVC 6. Use
3227
qScriptValueToValue() or qscriptvalue_cast() instead if you need
3228
to support that version of the compiler.
3230
\sa toScriptValue(), qScriptRegisterMetaType()
3234
\fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value)
3236
\relates QScriptEngine
3238
Creates a QScriptValue using the given \a engine with the given \a
3239
value of template type \c{T}.
3241
This function is equivalent to QScriptEngine::toScriptValue().
3242
It is provided as a work-around for MSVC 6, which doesn't support
3243
member template functions.
3245
\sa qScriptValueToValue()
3249
\fn T qScriptValueToValue(const QScriptValue &value)
3251
\relates QScriptEngine
3253
Returns the given \a value converted to the template type \c{T}.
3255
This function is equivalent to QScriptEngine::fromScriptValue().
3256
It is provided as a work-around for MSVC 6, which doesn't
3257
support member template functions.
3259
\sa qScriptValueFromValue()
3263
\fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container)
3265
\relates QScriptEngine
3267
Creates an array in the form of a QScriptValue using the given \a engine
3268
with the given \a container of template type \c{Container}.
3270
The \c Container type must provide a \c const_iterator class to enable the
3271
contents of the container to be copied into the array.
3273
Additionally, the type of each element in the sequence should be
3274
suitable for conversion to a QScriptValue. See
3275
\l{Conversion Between QtScript and C++ Types} for more information
3276
about the restrictions on types that can be used with QScriptValue.
3278
\sa qScriptValueFromValue()
3282
\fn void qScriptValueToSequence(const QScriptValue &value, Container &container)
3284
\relates QScriptEngine
3286
Copies the elements in the sequence specified by \a value to the given
3287
\a container of template type \c{Container}.
3289
The \a value used is typically an array, but any container can be copied
3290
as long as it provides a \c length property describing how many elements
3293
Additionally, the type of each element in the sequence must be
3294
suitable for conversion to a C++ type from a QScriptValue. See
3295
\l{Conversion Between QtScript and C++ Types} for more information
3296
about the restrictions on types that can be used with
3299
\sa qscriptvalue_cast()
3303
\fn T qscriptvalue_cast(const QScriptValue &value)
3305
\relates QScriptValue
3307
Returns the given \a value converted to the template type \c{T}.
3309
\sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue()
3312
/*! \fn int qScriptRegisterMetaType(
3313
QScriptEngine *engine,
3314
QScriptValue (*toScriptValue)(QScriptEngine *, const T &t),
3315
void (*fromScriptValue)(const QScriptValue &, T &t),
3316
const QScriptValue &prototype = QScriptValue())
3317
\relates QScriptEngine
3319
Registers the type \c{T} in the given \a engine. \a toScriptValue must
3320
be a function that will convert from a value of type \c{T} to a
3321
QScriptValue, and \a fromScriptValue a function that does the
3322
opposite. \a prototype, if valid, is the prototype that's set on
3323
QScriptValues returned by \a toScriptValue.
3325
Returns the internal ID used by QMetaType.
3327
You only need to call this function if you want to provide custom
3328
conversion of values of type \c{T}, i.e. if the default
3329
QVariant-based representation and conversion is not
3330
appropriate. (Note that custom QObject-derived types also fall in
3331
this category; e.g. for a QObject-derived class called MyObject,
3332
you probably want to define conversion functions for MyObject*
3333
that utilize QScriptEngine::newQObject() and
3334
QScriptValue::toQObject().)
3336
If you only want to define a common script interface for values of
3337
type \c{T}, and don't care how those values are represented
3338
(i.e. storing them in QVariants is fine), use
3339
\l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}()
3340
instead; this will minimize conversion costs.
3342
You need to declare the custom type first with
3343
Q_DECLARE_METATYPE().
3345
After a type has been registered, you can convert from a
3346
QScriptValue to that type using
3347
\l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and
3348
create a QScriptValue from a value of that type using
3349
\l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine
3350
will take care of calling the proper conversion function when
3351
calling C++ slots, and when getting or setting a C++ property;
3352
i.e. the custom type may be used seamlessly on both the C++ side
3353
and the script side.
3355
The following is an example of how to use this function. We will
3356
specify custom conversion of our type \c{MyStruct}. Here's the C++
3359
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20
3361
We must declare it so that the type will be known to QMetaType:
3363
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21
3365
Next, the \c{MyStruct} conversion functions. We represent the
3366
\c{MyStruct} value as a script object and just copy the properties:
3368
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22
3370
Now we can register \c{MyStruct} with the engine:
3371
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23
3373
Working with \c{MyStruct} values is now easy:
3374
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24
3376
If you want to be able to construct values of your custom type
3377
from script code, you have to register a constructor function for
3378
the type. For example:
3380
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25
3382
\sa qScriptRegisterSequenceMetaType(), qRegisterMetaType()
3386
\macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType)
3388
\relates QScriptEngine
3390
Declares the given \a QMetaObject. Used in combination with
3391
QScriptEngine::scriptValueFromQMetaObject() to make enums and
3392
instantiation of \a QMetaObject available to script code. The
3393
constructor generated by this macro takes a single argument of
3394
type \a ArgType; typically the argument is the parent type of the
3395
new instance, in which case \a ArgType is \c{QWidget*} or
3396
\c{QObject*}. Objects created by the constructor will have
3397
QScriptEngine::AutoOwnership ownership.
3400
/*! \fn int qScriptRegisterSequenceMetaType(
3401
QScriptEngine *engine,
3402
const QScriptValue &prototype = QScriptValue())
3403
\relates QScriptEngine
3405
Registers the sequence type \c{T} in the given \a engine. This
3406
function provides conversion functions that convert between \c{T}
3407
and Qt Script \c{Array} objects. \c{T} must provide a
3408
const_iterator class and begin(), end() and push_back()
3409
functions. If \a prototype is valid, it will be set as the
3410
prototype of \c{Array} objects due to conversion from \c{T};
3411
otherwise, the standard \c{Array} prototype will be used.
3413
Returns the internal ID used by QMetaType.
3415
You need to declare the container type first with
3416
Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++
3417
type, it must be declared using Q_DECLARE_METATYPE() as well.
3420
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26
3422
\sa qScriptRegisterMetaType()
3426
Runs the garbage collector.
3428
The garbage collector will attempt to reclaim memory by locating and
3429
disposing of objects that are no longer reachable in the script
3432
Normally you don't need to call this function; the garbage collector
3433
will automatically be invoked when the QScriptEngine decides that
3434
it's wise to do so (i.e. when a certain number of new objects have
3435
been created). However, you can call this function to explicitly
3436
request that garbage collection should be performed as soon as
3439
void QScriptEngine::collectGarbage()
3442
d->collectGarbage();
3447
Sets the interval between calls to QCoreApplication::processEvents
3448
to \a interval milliseconds.
3450
While the interpreter is running, all event processing is by default
3451
blocked. This means for instance that the gui will not be updated
3452
and timers will not be fired. To allow event processing during
3453
interpreter execution one can specify the processing interval to be
3454
a positive value, indicating the number of milliseconds between each
3455
time QCoreApplication::processEvents() is called.
3457
The default value is -1, which disables event processing during
3458
interpreter execution.
3460
You can use QCoreApplication::postEvent() to post an event that
3461
performs custom processing at the next interval. For example, you
3462
could keep track of the total running time of the script and call
3463
abortEvaluation() when you detect that the script has been running
3464
for a long time without completing.
3466
\sa processEventsInterval()
3468
void QScriptEngine::setProcessEventsInterval(int interval)
3471
d->processEventsInterval = interval;
3474
d->globalData->timeoutChecker->setCheckInterval(interval);
3476
d->timeoutChecker()->setShouldProcessEvents(interval > 0);
3481
Returns the interval in milliseconds between calls to
3482
QCoreApplication::processEvents() while the interpreter is running.
3484
\sa setProcessEventsInterval()
3486
int QScriptEngine::processEventsInterval() const
3488
Q_D(const QScriptEngine);
3489
return d->processEventsInterval;
3495
Returns true if this engine is currently evaluating a script,
3496
otherwise returns false.
3498
\sa evaluate(), abortEvaluation()
3500
bool QScriptEngine::isEvaluating() const
3502
Q_D(const QScriptEngine);
3503
return (d->currentFrame != d->globalExec()) || d->inEval;
3509
Aborts any script evaluation currently taking place in this engine.
3510
The given \a result is passed back as the result of the evaluation
3511
(i.e. it is returned from the call to evaluate() being aborted).
3513
If the engine isn't evaluating a script (i.e. isEvaluating() returns
3514
false), this function does nothing.
3516
Call this function if you need to abort a running script for some
3517
reason, e.g. when you have detected that the script has been
3518
running for several seconds without completing.
3520
\sa evaluate(), isEvaluating(), setProcessEventsInterval()
3522
void QScriptEngine::abortEvaluation(const QScriptValue &result)
3526
d->timeoutChecker()->setShouldAbort(true);
3527
d->abortResult = result;
3530
#ifndef QT_NO_QOBJECT
3534
\relates QScriptEngine
3536
Creates a connection from the \a signal in the \a sender to the
3537
given \a function. If \a receiver is an object, it will act as the
3538
`this' object when the signal handler function is invoked. Returns
3539
true if the connection succeeds; otherwise returns false.
3541
\sa qScriptDisconnect(), QScriptEngine::signalHandlerException()
3543
bool qScriptConnect(QObject *sender, const char *signal,
3544
const QScriptValue &receiver, const QScriptValue &function)
3546
if (!sender || !signal)
3548
if (!function.isFunction())
3550
if (receiver.isObject() && (receiver.engine() != function.engine()))
3552
QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
3553
JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
3554
JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
3555
return engine->scriptConnect(sender, signal, jscReceiver, jscFunction,
3556
Qt::AutoConnection);
3561
\relates QScriptEngine
3563
Disconnects the \a signal in the \a sender from the given (\a
3564
receiver, \a function) pair. Returns true if the connection is
3565
successfully broken; otherwise returns false.
3567
\sa qScriptConnect()
3569
bool qScriptDisconnect(QObject *sender, const char *signal,
3570
const QScriptValue &receiver, const QScriptValue &function)
3572
if (!sender || !signal)
3574
if (!function.isFunction())
3576
if (receiver.isObject() && (receiver.engine() != function.engine()))
3578
QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
3579
JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
3580
JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
3581
return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction);
3586
\fn void QScriptEngine::signalHandlerException(const QScriptValue &exception)
3588
This signal is emitted when a script function connected to a signal causes
3591
\sa qScriptConnect()
3594
QT_BEGIN_INCLUDE_NAMESPACE
3595
#include "moc_qscriptengine.cpp"
3596
QT_END_INCLUDE_NAMESPACE
3598
#endif // QT_NO_QOBJECT
3603
Installs the given \a agent on this engine. The agent will be
3604
notified of various events pertaining to script execution. This is
3605
useful when you want to find out exactly what the engine is doing,
3606
e.g. when evaluate() is called. The agent interface is the basis of
3607
tools like debuggers and profilers.
3609
The engine maintains ownership of the \a agent.
3611
Calling this function will replace the existing agent, if any.
3615
void QScriptEngine::setAgent(QScriptEngineAgent *agent)
3618
if (agent && (agent->engine() != this)) {
3619
qWarning("QScriptEngine::setAgent(): "
3620
"cannot set agent belonging to different engine");
3624
QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
3625
d->activeAgent = agent;
3627
QScriptEngineAgentPrivate::get(agent)->attach();
3634
Returns the agent currently installed on this engine, or 0 if no
3639
QScriptEngineAgent *QScriptEngine::agent() const
3641
Q_D(const QScriptEngine);
3642
return d->activeAgent;
3648
Returns a handle that represents the given string, \a str.
3650
QScriptString can be used to quickly look up properties, and
3651
compare property names, of script objects.
3653
\sa QScriptValue::property()
3655
QScriptString QScriptEngine::toStringHandle(const QString &str)
3658
QScriptString result;
3659
QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated);
3660
QScriptStringPrivate::init(result, p);
3661
d->registerScriptString(p);
3668
Converts the given \a value to an object, if such a conversion is
3669
possible; otherwise returns an invalid QScriptValue. The conversion
3670
is performed according to the following table:
3673
\header \o Input Type \o Result
3674
\row \o Undefined \o An invalid QScriptValue.
3675
\row \o Null \o An invalid QScriptValue.
3676
\row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
3677
\row \o Number \o A new Number object whose internal value is set to the value of the number.
3678
\row \o String \o A new String object whose internal value is set to the value of the string.
3679
\row \o Object \o The result is the object itself (no conversion).
3684
QScriptValue QScriptEngine::toObject(const QScriptValue &value)
3687
JSC::JSValue jscValue = d->scriptValueToJSCValue(value);
3688
if (!jscValue || jscValue.isUndefined() || jscValue.isNull())
3689
return QScriptValue();
3690
JSC::ExecState* exec = d->currentFrame;
3691
JSC::JSValue result = jscValue.toObject(exec);
3692
return d->scriptValueFromJSCValue(result);
3698
Returns the object with the given \a id, or an invalid
3699
QScriptValue if there is no object with that id.
3701
\sa QScriptValue::objectId()
3703
QScriptValue QScriptEngine::objectById(qint64 id) const
3705
Q_D(const QScriptEngine);
3706
// Assumes that the cell was not been garbage collected
3707
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
3712
\class QScriptSyntaxCheckResult
3714
\brief The QScriptSyntaxCheckResult class provides the result of a script syntax check.
3719
QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to
3720
provide information about the syntactical (in)correctness of a script.
3724
\enum QScriptSyntaxCheckResult::State
3726
This enum specifies the state of a syntax check.
3728
\value Error The program contains a syntax error.
3729
\value Intermediate The program is incomplete.
3730
\value Valid The program is a syntactically correct Qt Script program.
3734
Constructs a new QScriptSyntaxCheckResult from the \a other result.
3736
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other)
3737
: d_ptr(other.d_ptr)
3744
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d)
3752
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult()
3758
Destroys this QScriptSyntaxCheckResult.
3760
QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult()
3765
Returns the state of this QScriptSyntaxCheckResult.
3767
QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const
3769
Q_D(const QScriptSyntaxCheckResult);
3776
Returns the error line number of this QScriptSyntaxCheckResult, or -1 if
3779
\sa state(), errorMessage()
3781
int QScriptSyntaxCheckResult::errorLineNumber() const
3783
Q_D(const QScriptSyntaxCheckResult);
3786
return d->errorLineNumber;
3790
Returns the error column number of this QScriptSyntaxCheckResult, or -1 if
3793
\sa state(), errorLineNumber()
3795
int QScriptSyntaxCheckResult::errorColumnNumber() const
3797
Q_D(const QScriptSyntaxCheckResult);
3800
return d->errorColumnNumber;
3804
Returns the error message of this QScriptSyntaxCheckResult, or an empty
3805
string if there is no error.
3807
\sa state(), errorLineNumber()
3809
QString QScriptSyntaxCheckResult::errorMessage() const
3811
Q_D(const QScriptSyntaxCheckResult);
3814
return d->errorMessage;
3818
Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a
3819
reference to this QScriptSyntaxCheckResult.
3821
QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other)
3823
d_ptr = other.d_ptr;
3827
#ifdef QT_BUILD_INTERNAL
3828
Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()