0
+ − 1
/****************************************************************************
+ − 2
**
+ − 3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ − 4
** All rights reserved.
+ − 5
** Contact: Nokia Corporation (qt-info@nokia.com)
+ − 6
**
+ − 7
** This file is part of the QtScript module of the Qt Toolkit.
+ − 8
**
+ − 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
+ − 14
** this package.
+ − 15
**
+ − 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.
+ − 23
**
+ − 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.
+ − 27
**
+ − 28
** If you have questions regarding the use of this file, please contact
+ − 29
** Nokia at qt-info@nokia.com.
+ − 30
**
+ − 31
**
+ − 32
**
+ − 33
**
+ − 34
**
+ − 35
**
+ − 36
**
+ − 37
**
+ − 38
** $QT_END_LICENSE$
+ − 39
**
+ − 40
****************************************************************************/
+ − 41
+ − 42
#include "config.h"
+ − 43
#include "qscriptengine.h"
+ − 44
#include "qscriptsyntaxchecker_p.h"
+ − 45
#include "qnumeric.h"
+ − 46
+ − 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"
+ − 54
#include "qdebug.h"
+ − 55
+ − 56
#include <QtCore/qstringlist.h>
+ − 57
#include <QtCore/qmetaobject.h>
+ − 58
+ − 59
#include "Error.h"
+ − 60
#include "JSArray.h"
+ − 61
#include "JSLock.h"
+ − 62
#include "Interpreter.h"
+ − 63
#include "DateConstructor.h"
+ − 64
#include "RegExpConstructor.h"
+ − 65
+ − 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"
+ − 73
#include "Parser.h"
+ − 74
#include "Operations.h"
+ − 75
+ − 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"
+ − 84
+ − 85
#ifndef QT_NO_QOBJECT
+ − 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"
+ − 94
#endif
+ − 95
+ − 96
Q_DECLARE_METATYPE(QScriptValue)
+ − 97
#ifndef QT_NO_QOBJECT
+ − 98
Q_DECLARE_METATYPE(QObjectList)
+ − 99
#endif
+ − 100
Q_DECLARE_METATYPE(QList<int>)
+ − 101
+ − 102
QT_BEGIN_NAMESPACE
+ − 103
+ − 104
/*!
+ − 105
\since 4.3
+ − 106
\class QScriptEngine
+ − 107
\reentrant
+ − 108
+ − 109
\brief The QScriptEngine class provides an environment for evaluating Qt Script code.
+ − 110
+ − 111
\ingroup script
+ − 112
\mainclass
+ − 113
+ − 114
See the \l{QtScript} documentation for information about the Qt Script language,
+ − 115
and how to get started with scripting your C++ application.
+ − 116
+ − 117
\section1 Evaluating Scripts
+ − 118
+ − 119
Use evaluate() to evaluate script code; this is the C++ equivalent
+ − 120
of the built-in script function \c{eval()}.
+ − 121
+ − 122
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0
+ − 123
+ − 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()).
+ − 128
+ − 129
The following code snippet shows how a script function can be
+ − 130
defined and then invoked from C++ using QScriptValue::call():
+ − 131
+ − 132
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1
+ − 133
+ − 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():
+ − 137
+ − 138
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2
+ − 139
+ − 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).
+ − 145
+ − 146
\section1 Engine Configuration
+ − 147
+ − 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:
+ − 154
+ − 155
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3
+ − 156
+ − 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().
+ − 162
+ − 163
\section1 Script Exceptions
+ − 164
+ − 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
+ − 174
cleared.
+ − 175
+ − 176
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
+ − 177
+ − 178
The checkSyntax() function can be used to determine whether code can be
+ − 179
usefully passed to evaluate().
+ − 180
+ − 181
\section1 Script Object Creation
+ − 182
+ − 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}
+ − 189
object.
+ − 190
+ − 191
\section1 QObject Integration
+ − 192
+ − 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.
+ − 198
+ − 199
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5
+ − 200
+ − 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.
+ − 206
+ − 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().
+ − 215
+ − 216
See the \l{QtScript} documentation for more information on
+ − 217
the QObject integration.
+ − 218
+ − 219
\section1 Support for Custom C++ Types
+ − 220
+ − 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
+ − 229
class.
+ − 230
+ − 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
+ − 236
types.
+ − 237
+ − 238
\section1 Importing Extensions
+ − 239
+ − 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.
+ − 244
+ − 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.
+ − 250
+ − 251
\section1 Native Functions
+ − 252
+ − 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:
+ − 259
+ − 260
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6
+ − 261
+ − 262
To expose this function to script code, you can set it as a property
+ − 263
of the Global Object:
+ − 264
+ − 265
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7
+ − 266
+ − 267
Once this is done, script code can call your function in the exact
+ − 268
same manner as a "normal" script function:
+ − 269
+ − 270
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8
+ − 271
+ − 272
\section1 Long-running Scripts
+ − 273
+ − 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
+ − 279
isEvaluating().
+ − 280
+ − 281
\section1 Core Debugging/Tracing Facilities
+ − 282
+ − 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
+ − 287
QScriptEngine.
+ − 288
+ − 289
\sa QScriptValue, QScriptContext, QScriptEngineAgent
+ − 290
+ − 291
*/
+ − 292
+ − 293
/*!
+ − 294
\enum QScriptEngine::ValueOwnership
+ − 295
+ − 296
This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject().
+ − 297
+ − 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).
+ − 301
*/
+ − 302
+ − 303
/*!
+ − 304
\enum QScriptEngine::QObjectWrapOption
+ − 305
+ − 306
These flags specify options when wrapping a QObject pointer with newQObject().
+ − 307
+ − 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.
+ − 316
*/
+ − 317
+ − 318
class QScriptSyntaxCheckResultPrivate
+ − 319
{
+ − 320
public:
+ − 321
QScriptSyntaxCheckResultPrivate() { ref = 0; }
+ − 322
~QScriptSyntaxCheckResultPrivate() {}
+ − 323
+ − 324
QScriptSyntaxCheckResult::State state;
+ − 325
int errorColumnNumber;
+ − 326
int errorLineNumber;
+ − 327
QString errorMessage;
+ − 328
QBasicAtomicInt ref;
+ − 329
};
+ − 330
+ − 331
class QScriptTypeInfo
+ − 332
{
+ − 333
public:
+ − 334
QScriptTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0)
+ − 335
{ }
+ − 336
+ − 337
QByteArray signature;
+ − 338
QScriptEngine::MarshalFunction marshal;
+ − 339
QScriptEngine::DemarshalFunction demarshal;
+ − 340
JSC::JSValue prototype;
+ − 341
};
+ − 342
+ − 343
namespace QScript
+ − 344
{
+ − 345
+ − 346
void GlobalClientData::mark(JSC::MarkStack& markStack)
+ − 347
{
+ − 348
engine->mark(markStack);
+ − 349
}
+ − 350
+ − 351
class TimeoutCheckerProxy : public JSC::TimeoutChecker
+ − 352
{
+ − 353
public:
+ − 354
TimeoutCheckerProxy(const JSC::TimeoutChecker& originalChecker)
+ − 355
: JSC::TimeoutChecker(originalChecker)
+ − 356
, m_shouldProcessEvents(false)
+ − 357
, m_shouldAbortEvaluation(false)
+ − 358
{}
+ − 359
+ − 360
void setShouldProcessEvents(bool shouldProcess) { m_shouldProcessEvents = shouldProcess; }
+ − 361
void setShouldAbort(bool shouldAbort) { m_shouldAbortEvaluation = shouldAbort; }
+ − 362
bool shouldAbort() { return m_shouldAbortEvaluation; }
+ − 363
+ − 364
virtual bool didTimeOut(JSC::ExecState* exec)
+ − 365
{
+ − 366
if (JSC::TimeoutChecker::didTimeOut(exec))
+ − 367
return true;
+ − 368
+ − 369
if (m_shouldProcessEvents)
+ − 370
QCoreApplication::processEvents();
+ − 371
+ − 372
return m_shouldAbortEvaluation;
+ − 373
}
+ − 374
+ − 375
private:
+ − 376
bool m_shouldProcessEvents;
+ − 377
bool m_shouldAbortEvaluation;
+ − 378
};
+ − 379
+ − 380
static int toDigit(char c)
+ − 381
{
+ − 382
if ((c >= '0') && (c <= '9'))
+ − 383
return c - '0';
+ − 384
else if ((c >= 'a') && (c <= 'z'))
+ − 385
return 10 + c - 'a';
+ − 386
else if ((c >= 'A') && (c <= 'Z'))
+ − 387
return 10 + c - 'A';
+ − 388
return -1;
+ − 389
}
+ − 390
+ − 391
qsreal integerFromString(const char *buf, int size, int radix)
+ − 392
{
+ − 393
if (size == 0)
+ − 394
return qSNaN();
+ − 395
+ − 396
qsreal sign = 1.0;
+ − 397
int i = 0;
+ − 398
if (buf[0] == '+') {
+ − 399
++i;
+ − 400
} else if (buf[0] == '-') {
+ − 401
sign = -1.0;
+ − 402
++i;
+ − 403
}
+ − 404
+ − 405
if (((size-i) >= 2) && (buf[i] == '0')) {
+ − 406
if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ − 407
&& (radix < 34)) {
+ − 408
if ((radix != 0) && (radix != 16))
+ − 409
return 0;
+ − 410
radix = 16;
+ − 411
i += 2;
+ − 412
} else {
+ − 413
if (radix == 0) {
+ − 414
radix = 8;
+ − 415
++i;
+ − 416
}
+ − 417
}
+ − 418
} else if (radix == 0) {
+ − 419
radix = 10;
+ − 420
}
+ − 421
+ − 422
int j = i;
+ − 423
for ( ; i < size; ++i) {
+ − 424
int d = toDigit(buf[i]);
+ − 425
if ((d == -1) || (d >= radix))
+ − 426
break;
+ − 427
}
+ − 428
qsreal result;
+ − 429
if (j == i) {
+ − 430
if (!qstrcmp(buf, "Infinity"))
+ − 431
result = qInf();
+ − 432
else
+ − 433
result = qSNaN();
+ − 434
} else {
+ − 435
result = 0;
+ − 436
qsreal multiplier = 1;
+ − 437
for (--i ; i >= j; --i, multiplier *= radix)
+ − 438
result += toDigit(buf[i]) * multiplier;
+ − 439
}
+ − 440
result *= sign;
+ − 441
return result;
+ − 442
}
+ − 443
+ − 444
qsreal integerFromString(const QString &str, int radix)
+ − 445
{
+ − 446
QByteArray ba = str.trimmed().toUtf8();
+ − 447
return integerFromString(ba.constData(), ba.size(), radix);
+ − 448
}
+ − 449
+ − 450
bool isFunction(JSC::JSValue value)
+ − 451
{
+ − 452
if (!value || !value.isObject())
+ − 453
return false;
+ − 454
JSC::CallData callData;
+ − 455
return (JSC::asObject(value)->getCallData(callData) != JSC::CallTypeNone);
+ − 456
}
+ − 457
+ − 458
static JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 459
static JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 460
+ − 461
JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
+ − 462
{
+ − 463
#ifndef QT_NO_QOBJECT
+ − 464
if (args.size() == 0) {
+ − 465
return JSC::throwError(exec, JSC::GeneralError, "Function.prototype.disconnect: no arguments given");
+ − 466
}
+ − 467
+ − 468
if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
+ − 469
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: this object is not a signal");
+ − 470
}
+ − 471
+ − 472
QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
+ − 473
+ − 474
const QMetaObject *meta = qtSignal->metaObject();
+ − 475
if (!meta) {
+ − 476
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.discconnect: cannot disconnect from deleted QObject");
+ − 477
}
+ − 478
+ − 479
QMetaMethod sig = meta->method(qtSignal->initialIndex());
+ − 480
if (sig.methodType() != QMetaMethod::Signal) {
+ − 481
QString message = QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal")
+ − 482
.arg(QLatin1String(qtSignal->metaObject()->className()))
+ − 483
.arg(QLatin1String(sig.signature()));
+ − 484
return JSC::throwError(exec, JSC::TypeError, message);
+ − 485
}
+ − 486
+ − 487
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ − 488
+ − 489
JSC::JSValue receiver;
+ − 490
JSC::JSValue slot;
+ − 491
JSC::JSValue arg0 = args.at(0);
+ − 492
if (args.size() < 2) {
+ − 493
slot = arg0;
+ − 494
} else {
+ − 495
receiver = arg0;
+ − 496
JSC::JSValue arg1 = args.at(1);
+ − 497
if (isFunction(arg1))
+ − 498
slot = arg1;
+ − 499
else {
+ − 500
// ### don't go via QScriptValue
+ − 501
QScript::SaveFrameHelper saveFrame(engine, exec);
+ − 502
QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
+ − 503
QString propertyName(arg1.toString(exec));
+ − 504
slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
+ − 505
}
+ − 506
}
+ − 507
+ − 508
if (!isFunction(slot)) {
+ − 509
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: target is not a function");
+ − 510
}
+ − 511
+ − 512
bool ok = engine->scriptDisconnect(thisObject, receiver, slot);
+ − 513
if (!ok) {
+ − 514
QString message = QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1")
+ − 515
.arg(QLatin1String(qtSignal->metaObject()->className()))
+ − 516
.arg(QLatin1String(sig.signature()));
+ − 517
return JSC::throwError(exec, JSC::GeneralError, message);
+ − 518
}
+ − 519
return JSC::jsUndefined();
+ − 520
#else
+ − 521
Q_UNUSED(eng);
+ − 522
return context->throwError(QScriptContext::TypeError,
+ − 523
QLatin1String("Function.prototype.disconnect"));
+ − 524
#endif // QT_NO_QOBJECT
+ − 525
}
+ − 526
+ − 527
JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
+ − 528
{
+ − 529
#ifndef QT_NO_QOBJECT
+ − 530
if (args.size() == 0) {
+ − 531
return JSC::throwError(exec, JSC::GeneralError,"Function.prototype.connect: no arguments given");
+ − 532
}
+ − 533
+ − 534
if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
+ − 535
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: this object is not a signal");
+ − 536
}
+ − 537
+ − 538
QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
+ − 539
+ − 540
const QMetaObject *meta = qtSignal->metaObject();
+ − 541
if (!meta) {
+ − 542
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: cannot connect to deleted QObject");
+ − 543
}
+ − 544
+ − 545
QMetaMethod sig = meta->method(qtSignal->initialIndex());
+ − 546
if (sig.methodType() != QMetaMethod::Signal) {
+ − 547
QString message = QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal")
+ − 548
.arg(QLatin1String(qtSignal->metaObject()->className()))
+ − 549
.arg(QLatin1String(sig.signature()));
+ − 550
return JSC::throwError(exec, JSC::TypeError, message);
+ − 551
}
+ − 552
+ − 553
{
+ − 554
QList<int> overloads = qtSignal->overloadedIndexes();
+ − 555
if (!overloads.isEmpty()) {
+ − 556
overloads.append(qtSignal->initialIndex());
+ − 557
QByteArray signature = sig.signature();
+ − 558
QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n")
+ − 559
.arg(QLatin1String(qtSignal->metaObject()->className()))
+ − 560
.arg(QLatin1String(signature.left(signature.indexOf('('))));
+ − 561
for (int i = 0; i < overloads.size(); ++i) {
+ − 562
QMetaMethod mtd = meta->method(overloads.at(i));
+ − 563
message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature())));
+ − 564
}
+ − 565
message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload")
+ − 566
.arg(QLatin1String(signature)));
+ − 567
return JSC::throwError(exec, JSC::GeneralError, message);
+ − 568
}
+ − 569
}
+ − 570
+ − 571
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ − 572
+ − 573
JSC::JSValue receiver;
+ − 574
JSC::JSValue slot;
+ − 575
JSC::JSValue arg0 = args.at(0);
+ − 576
if (args.size() < 2) {
+ − 577
slot = arg0;
+ − 578
} else {
+ − 579
receiver = arg0;
+ − 580
JSC::JSValue arg1 = args.at(1);
+ − 581
if (isFunction(arg1))
+ − 582
slot = arg1;
+ − 583
else {
+ − 584
// ### don't go via QScriptValue
+ − 585
QScript::SaveFrameHelper saveFrame(engine, exec);
+ − 586
QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
+ − 587
QString propertyName = arg1.toString(exec);
+ − 588
slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
+ − 589
}
+ − 590
}
+ − 591
+ − 592
if (!isFunction(slot)) {
+ − 593
return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: target is not a function");
+ − 594
}
+ − 595
+ − 596
bool ok = engine->scriptConnect(thisObject, receiver, slot, Qt::AutoConnection);
+ − 597
if (!ok) {
+ − 598
QString message = QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1")
+ − 599
.arg(QLatin1String(qtSignal->metaObject()->className()))
+ − 600
.arg(QLatin1String(sig.signature()));
+ − 601
return JSC::throwError(exec, JSC::GeneralError, message);
+ − 602
}
+ − 603
return JSC::jsUndefined();
+ − 604
#else
+ − 605
Q_UNUSED(eng);
+ − 606
Q_UNUSED(classInfo);
+ − 607
return context->throwError(QScriptContext::TypeError,
+ − 608
QLatin1String("Function.prototype.connect"));
+ − 609
#endif // QT_NO_QOBJECT
+ − 610
}
+ − 611
+ − 612
static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 613
static JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 614
static JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 615
+ − 616
JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList& args)
+ − 617
{
+ − 618
QString result;
+ − 619
for (unsigned i = 0; i < args.size(); ++i) {
+ − 620
if (i != 0)
+ − 621
result.append(QLatin1Char(' '));
+ − 622
QString s(args.at(i).toString(exec));
+ − 623
if (exec->hadException())
+ − 624
break;
+ − 625
result.append(s);
+ − 626
}
+ − 627
if (exec->hadException())
+ − 628
return exec->exception();
+ − 629
qDebug("%s", qPrintable(result));
+ − 630
return JSC::jsUndefined();
+ − 631
}
+ − 632
+ − 633
JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
+ − 634
{
+ − 635
QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ − 636
engine->collectGarbage();
+ − 637
return JSC::jsUndefined();
+ − 638
}
+ − 639
+ − 640
JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
+ − 641
{
+ − 642
return JSC::JSValue(exec, 1);
+ − 643
}
+ − 644
+ − 645
static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 646
static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 647
static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 648
static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 649
+ − 650
JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+ − 651
{
+ − 652
if (args.size() < 2)
+ − 653
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
+ − 654
if (!args.at(0).isString())
+ − 655
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): first argument (context) must be a string");
+ − 656
if (!args.at(1).isString())
+ − 657
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): second argument (text) must be a string");
+ − 658
if ((args.size() > 2) && !args.at(2).isString())
+ − 659
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (comment) must be a string");
+ − 660
if ((args.size() > 3) && !args.at(3).isString())
+ − 661
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fourth argument (encoding) must be a string");
+ − 662
if ((args.size() > 4) && !args.at(4).isNumber())
+ − 663
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number");
+ − 664
#ifndef QT_NO_QOBJECT
+ − 665
QString context(args.at(0).toString(exec));
+ − 666
#endif
+ − 667
QString text(args.at(1).toString(exec));
+ − 668
#ifndef QT_NO_QOBJECT
+ − 669
QString comment;
+ − 670
if (args.size() > 2)
+ − 671
comment = args.at(2).toString(exec);
+ − 672
QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr;
+ − 673
if (args.size() > 3) {
+ − 674
QString encStr(args.at(3).toString(exec));
+ − 675
if (encStr == QLatin1String("CodecForTr"))
+ − 676
encoding = QCoreApplication::CodecForTr;
+ − 677
else if (encStr == QLatin1String("UnicodeUTF8"))
+ − 678
encoding = QCoreApplication::UnicodeUTF8;
+ − 679
else
+ − 680
return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr));
+ − 681
}
+ − 682
int n = -1;
+ − 683
if (args.size() > 4)
+ − 684
n = args.at(4).toInt32(exec);
+ − 685
#endif
+ − 686
QString result;
+ − 687
#ifndef QT_NO_QOBJECT
+ − 688
result = QCoreApplication::translate(context.toLatin1().constData(),
+ − 689
text.toLatin1().constData(),
+ − 690
comment.toLatin1().constData(),
+ − 691
encoding, n);
+ − 692
#else
+ − 693
result = text;
+ − 694
#endif
+ − 695
return JSC::jsString(exec, result);
+ − 696
}
+ − 697
+ − 698
JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+ − 699
{
+ − 700
if (args.size() < 2)
+ − 701
return JSC::jsUndefined();
+ − 702
return args.at(1);
+ − 703
}
+ − 704
+ − 705
JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+ − 706
{
+ − 707
if (args.size() < 1)
+ − 708
return JSC::throwError(exec, JSC::GeneralError, "qsTr() requires at least one argument");
+ − 709
if (!args.at(0).isString())
+ − 710
return JSC::throwError(exec, JSC::GeneralError, "qsTr(): first argument (text) must be a string");
+ − 711
if ((args.size() > 1) && !args.at(1).isString())
+ − 712
return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string");
+ − 713
if ((args.size() > 2) && !args.at(2).isNumber())
+ − 714
return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number");
+ − 715
#ifndef QT_NO_QOBJECT
+ − 716
QString context;
+ − 717
// ### implement context resolution
+ − 718
// if (ctx->parentContext())
+ − 719
// context = QFileInfo(ctx->parentContext()->fileName()).baseName();
+ − 720
#endif
+ − 721
QString text(args.at(0).toString(exec));
+ − 722
#ifndef QT_NO_QOBJECT
+ − 723
QString comment;
+ − 724
if (args.size() > 1)
+ − 725
comment = args.at(1).toString(exec);
+ − 726
int n = -1;
+ − 727
if (args.size() > 2)
+ − 728
n = args.at(2).toInt32(exec);
+ − 729
#endif
+ − 730
QString result;
+ − 731
#ifndef QT_NO_QOBJECT
+ − 732
result = QCoreApplication::translate(context.toLatin1().constData(),
+ − 733
text.toLatin1().constData(),
+ − 734
comment.toLatin1().constData(),
+ − 735
QCoreApplication::CodecForTr, n);
+ − 736
#else
+ − 737
result = text;
+ − 738
#endif
+ − 739
return JSC::jsString(exec, result);
+ − 740
}
+ − 741
+ − 742
JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+ − 743
{
+ − 744
if (args.size() < 1)
+ − 745
return JSC::jsUndefined();
+ − 746
return args.at(0);
+ − 747
}
+ − 748
+ − 749
static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+ − 750
+ − 751
JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
+ − 752
{
+ − 753
QString value(thisObject.toString(exec));
+ − 754
JSC::JSValue arg = (args.size() != 0) ? args.at(0) : JSC::jsUndefined();
+ − 755
QString result;
+ − 756
if (arg.isString())
+ − 757
result = value.arg(arg.toString(exec));
+ − 758
else if (arg.isNumber())
+ − 759
result = value.arg(arg.toNumber(exec));
+ − 760
return JSC::jsString(exec, result);
+ − 761
}
+ − 762
+ − 763
+ − 764
#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY)
+ − 765
static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng)
+ − 766
{
+ − 767
QString path = ctx->argument(0).toString();
+ − 768
QStringList components = path.split(QLatin1Char('.'));
+ − 769
QScriptValue o = eng->globalObject();
+ − 770
for (int i = 0; i < components.count(); ++i) {
+ − 771
QString name = components.at(i);
+ − 772
QScriptValue oo = o.property(name);
+ − 773
if (!oo.isValid()) {
+ − 774
oo = eng->newObject();
+ − 775
o.setProperty(name, oo);
+ − 776
}
+ − 777
o = oo;
+ − 778
}
+ − 779
return o;
+ − 780
}
+ − 781
#endif
+ − 782
+ − 783
} // namespace QScript
+ − 784
+ − 785
QScriptEnginePrivate::QScriptEnginePrivate()
+ − 786
: registeredScriptValues(0), freeScriptValues(0),
+ − 787
registeredScriptStrings(0), inEval(false)
+ − 788
{
+ − 789
qMetaTypeId<QScriptValue>();
+ − 790
qMetaTypeId<QList<int> >();
+ − 791
#ifndef QT_NO_QOBJECT
+ − 792
qMetaTypeId<QObjectList>();
+ − 793
#endif
+ − 794
+ − 795
JSC::initializeThreading(); // ### hmmm
+ − 796
+ − 797
globalData = JSC::JSGlobalData::create().releaseRef();
+ − 798
globalData->clientData = new QScript::GlobalClientData(this);
+ − 799
JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
+ − 800
+ − 801
JSC::ExecState* exec = globalObject->globalExec();
+ − 802
+ − 803
scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
+ − 804
+ − 805
qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ − 806
qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
+ − 807
+ − 808
qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ − 809
qmetaobjectWrapperObjectStructure = QScript::QMetaObjectWrapperObject::createStructure(qmetaobjectPrototype);
+ − 810
+ − 811
variantPrototype = new (exec) QScript::QVariantPrototype(exec, QScript::QVariantPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ − 812
variantWrapperObjectStructure = QScriptObject::createStructure(variantPrototype);
+ − 813
+ − 814
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "print"), QScript::functionPrint));
+ − 815
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "gc"), QScript::functionGC));
+ − 816
globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "version"), QScript::functionVersion));
+ − 817
+ − 818
// ### rather than extending Function.prototype, consider creating a QtSignal.prototype
+ − 819
globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "disconnect"), QScript::functionDisconnect));
+ − 820
globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "connect"), QScript::functionConnect));
+ − 821
+ − 822
JSC::TimeoutChecker* originalChecker = globalData->timeoutChecker;
+ − 823
globalData->timeoutChecker = new QScript::TimeoutCheckerProxy(*originalChecker);
+ − 824
delete originalChecker;
+ − 825
+ − 826
currentFrame = exec;
+ − 827
+ − 828
originalGlobalObjectProxy = 0;
+ − 829
activeAgent = 0;
+ − 830
agentLineNumber = -1;
+ − 831
processEventsInterval = -1;
+ − 832
}
+ − 833
+ − 834
QScriptEnginePrivate::~QScriptEnginePrivate()
+ − 835
{
+ − 836
//disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
+ − 837
QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
+ − 838
for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it)
+ − 839
it.value()->disconnectFromEngine();
+ − 840
+ − 841
while (!ownedAgents.isEmpty())
+ − 842
delete ownedAgents.takeFirst();
+ − 843
+ − 844
detachAllRegisteredScriptValues();
+ − 845
detachAllRegisteredScriptStrings();
+ − 846
qDeleteAll(m_qobjectData);
+ − 847
qDeleteAll(m_typeInfos);
+ − 848
JSC::JSLock lock(false);
+ − 849
globalData->heap.destroy();
+ − 850
globalData->deref();
+ − 851
while (freeScriptValues) {
+ − 852
QScriptValuePrivate *p = freeScriptValues;
+ − 853
freeScriptValues = p->next;
+ − 854
qFree(p);
+ − 855
}
+ − 856
}
+ − 857
+ − 858
QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v)
+ − 859
{
+ − 860
Q_Q(QScriptEngine);
+ − 861
QScriptValue result = q->create(v.userType(), v.data());
+ − 862
Q_ASSERT(result.isValid());
+ − 863
return result;
+ − 864
}
+ − 865
+ − 866
QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType)
+ − 867
{
+ − 868
QVariant v(targetType, (void *)0);
+ − 869
if (QScriptEnginePrivate::convert(value, targetType, v.data(), this))
+ − 870
return v;
+ − 871
if (uint(targetType) == QVariant::LastType)
+ − 872
return value.toVariant();
+ − 873
if (value.isVariant()) {
+ − 874
v = value.toVariant();
+ − 875
if (v.canConvert(QVariant::Type(targetType))) {
+ − 876
v.convert(QVariant::Type(targetType));
+ − 877
return v;
+ − 878
}
+ − 879
QByteArray typeName = v.typeName();
+ − 880
if (typeName.endsWith('*')
+ − 881
&& (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) {
+ − 882
return QVariant(targetType, *reinterpret_cast<void* *>(v.data()));
+ − 883
}
+ − 884
}
+ − 885
+ − 886
return QVariant();
+ − 887
}
+ − 888
+ − 889
JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v)
+ − 890
{
+ − 891
// ### it's inefficient to convert to QScriptValue and then to JSValue
+ − 892
QScriptValue vv = scriptValueFromVariant(v);
+ − 893
QScriptValuePrivate *p = QScriptValuePrivate::get(vv);
+ − 894
switch (p->type) {
+ − 895
case QScriptValuePrivate::JavaScriptCore:
+ − 896
return p->jscValue;
+ − 897
case QScriptValuePrivate::Number:
+ − 898
return JSC::jsNumber(currentFrame, p->numberValue);
+ − 899
case QScriptValuePrivate::String: {
+ − 900
JSC::UString str = p->stringValue;
+ − 901
return JSC::jsString(currentFrame, str);
+ − 902
}
+ − 903
}
+ − 904
return JSC::JSValue();
+ − 905
}
+ − 906
+ − 907
QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType)
+ − 908
{
+ − 909
// ### it's inefficient to convert to QScriptValue and then to QVariant
+ − 910
return scriptValueToVariant(scriptValueFromJSCValue(value), targetType);
+ − 911
}
+ − 912
+ − 913
QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst)
+ − 914
{
+ − 915
Q_Q(QScriptEngine);
+ − 916
QScriptValue arr = q->newArray(lst.size());
+ − 917
for (int i = 0; i < lst.size(); ++i)
+ − 918
arr.setProperty(i, QScriptValue(q, lst.at(i)));
+ − 919
return arr;
+ − 920
}
+ − 921
+ − 922
QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr)
+ − 923
{
+ − 924
QStringList lst;
+ − 925
uint len = arr.property(QLatin1String("length")).toUInt32();
+ − 926
for (uint i = 0; i < len; ++i)
+ − 927
lst.append(arr.property(i).toString());
+ − 928
return lst;
+ − 929
}
+ − 930
+ − 931
QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst)
+ − 932
{
+ − 933
Q_Q(QScriptEngine);
+ − 934
QScriptValue arr = q->newArray(lst.size());
+ − 935
for (int i = 0; i < lst.size(); ++i)
+ − 936
arr.setProperty(i, scriptValueFromVariant(lst.at(i)));
+ − 937
return arr;
+ − 938
}
+ − 939
+ − 940
QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr)
+ − 941
{
+ − 942
QVariantList lst;
+ − 943
uint len = arr.property(QLatin1String("length")).toUInt32();
+ − 944
for (uint i = 0; i < len; ++i)
+ − 945
lst.append(arr.property(i).toVariant());
+ − 946
return lst;
+ − 947
}
+ − 948
+ − 949
QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap)
+ − 950
{
+ − 951
Q_Q(QScriptEngine);
+ − 952
QScriptValue obj = q->newObject();
+ − 953
QVariantMap::const_iterator it;
+ − 954
for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
+ − 955
obj.setProperty(it.key(), scriptValueFromVariant(it.value()));
+ − 956
return obj;
+ − 957
}
+ − 958
+ − 959
QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj)
+ − 960
{
+ − 961
QVariantMap vmap;
+ − 962
QScriptValueIterator it(obj);
+ − 963
while (it.hasNext()) {
+ − 964
it.next();
+ − 965
vmap.insert(it.name(), it.value().toVariant());
+ − 966
}
+ − 967
return vmap;
+ − 968
}
+ − 969
+ − 970
JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
+ − 971
{
+ − 972
QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
+ − 973
if (!info)
+ − 974
return JSC::JSValue();
+ − 975
return info->prototype;
+ − 976
}
+ − 977
+ − 978
void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prototype)
+ − 979
{
+ − 980
QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
+ − 981
if (!info) {
+ − 982
info = new QScriptTypeInfo();
+ − 983
m_typeInfos.insert(metaTypeId, info);
+ − 984
}
+ − 985
info->prototype = prototype;
+ − 986
}
+ − 987
+ − 988
JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const
+ − 989
{
+ − 990
return globalData->head;
+ − 991
}
+ − 992
+ − 993
JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const
+ − 994
{
+ − 995
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ − 996
return glob->customGlobalObject;
+ − 997
}
+ − 998
+ − 999
JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy()
+ − 1000
{
+ − 1001
if (!originalGlobalObjectProxy) {
+ − 1002
JSC::ExecState* exec = currentFrame;
+ − 1003
originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ − 1004
}
+ − 1005
return originalGlobalObjectProxy;
+ − 1006
}
+ − 1007
+ − 1008
JSC::JSObject *QScriptEnginePrivate::globalObject() const
+ − 1009
{
+ − 1010
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ − 1011
if (glob->customGlobalObject)
+ − 1012
return glob->customGlobalObject;
+ − 1013
return glob;
+ − 1014
}
+ − 1015
+ − 1016
void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object)
+ − 1017
{
+ − 1018
if (object == globalObject())
+ − 1019
return;
+ − 1020
QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ − 1021
if (object == originalGlobalObjectProxy)
+ − 1022
glob->customGlobalObject = 0;
+ − 1023
else {
+ − 1024
Q_ASSERT(object != originalGlobalObject());
+ − 1025
glob->customGlobalObject = object;
+ − 1026
}
+ − 1027
}
+ − 1028
+ − 1029
/*!
+ − 1030
\internal
+ − 1031
+ − 1032
If the given \a value is the original global object, returns the custom
+ − 1033
global object or a proxy to the original global object; otherwise returns \a
+ − 1034
value.
+ − 1035
*/
+ − 1036
JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value)
+ − 1037
{
+ − 1038
if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject())
+ − 1039
return value;
+ − 1040
Q_ASSERT(JSC::asObject(value) == originalGlobalObject());
+ − 1041
if (customGlobalObject())
+ − 1042
return customGlobalObject();
+ − 1043
if (!originalGlobalObjectProxy)
+ − 1044
originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ − 1045
return originalGlobalObjectProxy;
+ − 1046
}
+ − 1047
/*!
+ − 1048
\internal
+ − 1049
Return the 'this' value for a given context
+ − 1050
*/
+ − 1051
JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame)
+ − 1052
{
+ − 1053
if (frame->codeBlock() != 0) {
+ − 1054
return frame->thisValue();
+ − 1055
} else if(frame == frame->lexicalGlobalObject()->globalExec()) {
+ − 1056
return frame->globalThisValue();
+ − 1057
} else {
+ − 1058
JSC::Register *thisRegister = thisRegisterForFrame(frame);
+ − 1059
return thisRegister->jsValue();
+ − 1060
}
+ − 1061
}
+ − 1062
+ − 1063
JSC::Register* QScriptEnginePrivate::thisRegisterForFrame(JSC::ExecState *frame)
+ − 1064
{
+ − 1065
Q_ASSERT(frame->codeBlock() == 0); // only for native calls
+ − 1066
return frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount();
+ − 1067
}
+ − 1068
+ − 1069
/*! \internal
+ − 1070
For native context, we use the ReturnValueRegister entry in the stackframe header to store flags.
+ − 1071
We can do that because this header is not used as the native function return their value thought C++
+ − 1072
+ − 1073
when setting flags, NativeContext should always be set
+ − 1074
+ − 1075
contextFlags returns 0 for non native context
+ − 1076
*/
+ − 1077
uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec)
+ − 1078
{
+ − 1079
if (exec->codeBlock())
+ − 1080
return 0; //js function doesn't have flags
+ − 1081
+ − 1082
return exec->returnValueRegister();
+ − 1083
}
+ − 1084
+ − 1085
void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags)
+ − 1086
{
+ − 1087
Q_ASSERT(!exec->codeBlock());
+ − 1088
exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::Register::withInt(flags);
+ − 1089
}
+ − 1090
+ − 1091
+ − 1092
void QScriptEnginePrivate::mark(JSC::MarkStack& markStack)
+ − 1093
{
+ − 1094
markStack.append(originalGlobalObject());
+ − 1095
markStack.append(globalObject());
+ − 1096
if (originalGlobalObjectProxy)
+ − 1097
markStack.append(originalGlobalObjectProxy);
+ − 1098
+ − 1099
if (qobjectPrototype)
+ − 1100
markStack.append(qobjectPrototype);
+ − 1101
if (qmetaobjectPrototype)
+ − 1102
markStack.append(qmetaobjectPrototype);
+ − 1103
if (variantPrototype)
+ − 1104
markStack.append(variantPrototype);
+ − 1105
+ − 1106
{
+ − 1107
QScriptValuePrivate *it;
+ − 1108
for (it = registeredScriptValues; it != 0; it = it->next) {
+ − 1109
if (it->isJSC())
+ − 1110
markStack.append(it->jscValue);
+ − 1111
}
+ − 1112
}
+ − 1113
+ − 1114
#ifndef QT_NO_QOBJECT
+ − 1115
{
+ − 1116
QHash<QObject*, QScript::QObjectData*>::const_iterator it;
+ − 1117
for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) {
+ − 1118
QScript::QObjectData *qdata = it.value();
+ − 1119
qdata->mark(markStack);
+ − 1120
}
+ − 1121
}
+ − 1122
#endif
+ − 1123
+ − 1124
{
+ − 1125
QHash<int, QScriptTypeInfo*>::const_iterator it;
+ − 1126
for (it = m_typeInfos.constBegin(); it != m_typeInfos.constEnd(); ++it) {
+ − 1127
if ((*it)->prototype)
+ − 1128
markStack.append((*it)->prototype);
+ − 1129
}
+ − 1130
}
+ − 1131
}
+ − 1132
+ − 1133
bool QScriptEnginePrivate::isCollecting() const
+ − 1134
{
+ − 1135
return globalData->heap.isBusy();
+ − 1136
}
+ − 1137
+ − 1138
void QScriptEnginePrivate::collectGarbage()
+ − 1139
{
+ − 1140
JSC::JSLock lock(false);
+ − 1141
globalData->heap.collect();
+ − 1142
}
+ − 1143
+ − 1144
QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const
+ − 1145
{
+ − 1146
return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker);
+ − 1147
}
+ − 1148
+ − 1149
void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
+ − 1150
{
+ − 1151
ownedAgents.removeOne(agent);
+ − 1152
if (activeAgent == agent) {
+ − 1153
QScriptEngineAgentPrivate::get(agent)->detach();
+ − 1154
activeAgent = 0;
+ − 1155
}
+ − 1156
}
+ − 1157
+ − 1158
#ifndef QT_NO_QOBJECT
+ − 1159
+ − 1160
JSC::JSValue QScriptEnginePrivate::newQObject(
+ − 1161
QObject *object, QScriptEngine::ValueOwnership ownership,
+ − 1162
const QScriptEngine::QObjectWrapOptions &options)
+ − 1163
{
+ − 1164
if (!object)
+ − 1165
return JSC::jsNull();
+ − 1166
JSC::ExecState* exec = currentFrame;
+ − 1167
QScript::QObjectData *data = qobjectData(object);
+ − 1168
bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0;
+ − 1169
QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject;
+ − 1170
QScriptObject *result = 0;
+ − 1171
if (preferExisting) {
+ − 1172
result = data->findWrapper(ownership, opt);
+ − 1173
if (result)
+ − 1174
return result;
+ − 1175
}
+ − 1176
result = new (exec) QScriptObject(qobjectWrapperObjectStructure);
+ − 1177
if (preferExisting)
+ − 1178
data->registerWrapper(result, ownership, opt);
+ − 1179
result->setDelegate(new QScript::QObjectDelegate(object, ownership, options));
+ − 1180
/*if (setDefaultPrototype)*/ {
+ − 1181
const QMetaObject *meta = object->metaObject();
+ − 1182
while (meta) {
+ − 1183
QByteArray typeString = meta->className();
+ − 1184
typeString.append('*');
+ − 1185
int typeId = QMetaType::type(typeString);
+ − 1186
if (typeId != 0) {
+ − 1187
JSC::JSValue proto = defaultPrototype(typeId);
+ − 1188
if (proto) {
+ − 1189
result->setPrototype(proto);
+ − 1190
break;
+ − 1191
}
+ − 1192
}
+ − 1193
meta = meta->superClass();
+ − 1194
}
+ − 1195
}
+ − 1196
return result;
+ − 1197
}
+ − 1198
+ − 1199
JSC::JSValue QScriptEnginePrivate::newQMetaObject(
+ − 1200
const QMetaObject *metaObject, JSC::JSValue ctor)
+ − 1201
{
+ − 1202
if (!metaObject)
+ − 1203
return JSC::jsNull();
+ − 1204
JSC::ExecState* exec = currentFrame;
+ − 1205
QScript::QMetaObjectWrapperObject *result = new (exec) QScript::QMetaObjectWrapperObject(exec, metaObject, ctor, qmetaobjectWrapperObjectStructure);
+ − 1206
return result;
+ − 1207
}
+ − 1208
+ − 1209
bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value,
+ − 1210
const QByteArray &targetType,
+ − 1211
void **result)
+ − 1212
{
+ − 1213
if (!targetType.endsWith('*'))
+ − 1214
return false;
+ − 1215
if (QObject *qobject = value.toQObject()) {
+ − 1216
int start = targetType.startsWith("const ") ? 6 : 0;
+ − 1217
QByteArray className = targetType.mid(start, targetType.size()-start-1);
+ − 1218
if (void *instance = qobject->qt_metacast(className)) {
+ − 1219
*result = instance;
+ − 1220
return true;
+ − 1221
}
+ − 1222
}
+ − 1223
return false;
+ − 1224
}
+ − 1225
+ − 1226
QScript::QObjectData *QScriptEnginePrivate::qobjectData(QObject *object)
+ − 1227
{
+ − 1228
QHash<QObject*, QScript::QObjectData*>::const_iterator it;
+ − 1229
it = m_qobjectData.constFind(object);
+ − 1230
if (it != m_qobjectData.constEnd())
+ − 1231
return it.value();
+ − 1232
+ − 1233
QScript::QObjectData *data = new QScript::QObjectData(this);
+ − 1234
m_qobjectData.insert(object, data);
+ − 1235
QObject::connect(object, SIGNAL(destroyed(QObject*)),
+ − 1236
q_func(), SLOT(_q_objectDestroyed(QObject *)));
+ − 1237
return data;
+ − 1238
}
+ − 1239
+ − 1240
void QScriptEnginePrivate::_q_objectDestroyed(QObject *object)
+ − 1241
{
+ − 1242
QHash<QObject*, QScript::QObjectData*>::iterator it;
+ − 1243
it = m_qobjectData.find(object);
+ − 1244
Q_ASSERT(it != m_qobjectData.end());
+ − 1245
QScript::QObjectData *data = it.value();
+ − 1246
m_qobjectData.erase(it);
+ − 1247
delete data;
+ − 1248
}
+ − 1249
+ − 1250
void QScriptEnginePrivate::disposeQObject(QObject *object)
+ − 1251
{
+ − 1252
// TODO
+ − 1253
/* if (isCollecting()) {
+ − 1254
// wait until we're done with GC before deleting it
+ − 1255
int index = m_qobjectsToBeDeleted.indexOf(object);
+ − 1256
if (index == -1)
+ − 1257
m_qobjectsToBeDeleted.append(object);
+ − 1258
} else*/ {
+ − 1259
delete object;
+ − 1260
}
+ − 1261
}
+ − 1262
+ − 1263
void QScriptEnginePrivate::emitSignalHandlerException()
+ − 1264
{
+ − 1265
Q_Q(QScriptEngine);
+ − 1266
emit q->signalHandlerException(q->uncaughtException());
+ − 1267
}
+ − 1268
+ − 1269
bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal,
+ − 1270
JSC::JSValue receiver, JSC::JSValue function,
+ − 1271
Qt::ConnectionType type)
+ − 1272
{
+ − 1273
Q_ASSERT(sender);
+ − 1274
Q_ASSERT(signal);
+ − 1275
const QMetaObject *meta = sender->metaObject();
+ − 1276
int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
+ − 1277
if (index == -1)
+ − 1278
return false;
+ − 1279
return scriptConnect(sender, index, receiver, function, /*wrapper=*/JSC::JSValue(), type);
+ − 1280
}
+ − 1281
+ − 1282
bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal,
+ − 1283
JSC::JSValue receiver, JSC::JSValue function)
+ − 1284
{
+ − 1285
Q_ASSERT(sender);
+ − 1286
Q_ASSERT(signal);
+ − 1287
const QMetaObject *meta = sender->metaObject();
+ − 1288
int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
+ − 1289
if (index == -1)
+ − 1290
return false;
+ − 1291
return scriptDisconnect(sender, index, receiver, function);
+ − 1292
}
+ − 1293
+ − 1294
bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex,
+ − 1295
JSC::JSValue receiver, JSC::JSValue function,
+ − 1296
JSC::JSValue senderWrapper,
+ − 1297
Qt::ConnectionType type)
+ − 1298
{
+ − 1299
QScript::QObjectData *data = qobjectData(sender);
+ − 1300
return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type);
+ − 1301
}
+ − 1302
+ − 1303
bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex,
+ − 1304
JSC::JSValue receiver, JSC::JSValue function)
+ − 1305
{
+ − 1306
QScript::QObjectData *data = qobjectData(sender);
+ − 1307
if (!data)
+ − 1308
return false;
+ − 1309
return data->removeSignalHandler(sender, signalIndex, receiver, function);
+ − 1310
}
+ − 1311
+ − 1312
bool QScriptEnginePrivate::scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
+ − 1313
JSC::JSValue function, Qt::ConnectionType type)
+ − 1314
{
+ − 1315
QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
+ − 1316
int index = fun->mostGeneralMethod();
+ − 1317
return scriptConnect(fun->qobject(), index, receiver, function, fun->wrapperObject(), type);
+ − 1318
}
+ − 1319
+ − 1320
bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
+ − 1321
JSC::JSValue function)
+ − 1322
{
+ − 1323
QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
+ − 1324
int index = fun->mostGeneralMethod();
+ − 1325
return scriptDisconnect(fun->qobject(), index, receiver, function);
+ − 1326
}
+ − 1327
+ − 1328
#endif
+ − 1329
+ − 1330
void QScriptEnginePrivate::detachAllRegisteredScriptValues()
+ − 1331
{
+ − 1332
QScriptValuePrivate *it;
+ − 1333
QScriptValuePrivate *next;
+ − 1334
for (it = registeredScriptValues; it != 0; it = next) {
+ − 1335
it->detachFromEngine();
+ − 1336
next = it->next;
+ − 1337
it->prev = 0;
+ − 1338
it->next = 0;
+ − 1339
}
+ − 1340
registeredScriptValues = 0;
+ − 1341
}
+ − 1342
+ − 1343
void QScriptEnginePrivate::detachAllRegisteredScriptStrings()
+ − 1344
{
+ − 1345
QScriptStringPrivate *it;
+ − 1346
QScriptStringPrivate *next;
+ − 1347
for (it = registeredScriptStrings; it != 0; it = next) {
+ − 1348
it->detachFromEngine();
+ − 1349
next = it->next;
+ − 1350
it->prev = 0;
+ − 1351
it->next = 0;
+ − 1352
}
+ − 1353
registeredScriptStrings = 0;
+ − 1354
}
+ − 1355
+ − 1356
#ifdef QT_NO_QOBJECT
+ − 1357
+ − 1358
QScriptEngine::QScriptEngine()
+ − 1359
: d_ptr(new QScriptEnginePrivate)
+ − 1360
{
+ − 1361
d_ptr->q_ptr = this;
+ − 1362
}
+ − 1363
+ − 1364
/*! \internal
+ − 1365
*/
+ − 1366
QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
+ − 1367
: d_ptr(&dd)
+ − 1368
{
+ − 1369
d_ptr->q_ptr = this;
+ − 1370
}
+ − 1371
#else
+ − 1372
+ − 1373
/*!
+ − 1374
Constructs a QScriptEngine object.
+ − 1375
+ − 1376
The globalObject() is initialized to have properties as described in
+ − 1377
\l{ECMA-262}, Section 15.1.
+ − 1378
*/
+ − 1379
QScriptEngine::QScriptEngine()
+ − 1380
: QObject(*new QScriptEnginePrivate, 0)
+ − 1381
{
+ − 1382
}
+ − 1383
+ − 1384
/*!
+ − 1385
Constructs a QScriptEngine object with the given \a parent.
+ − 1386
+ − 1387
The globalObject() is initialized to have properties as described in
+ − 1388
\l{ECMA-262}, Section 15.1.
+ − 1389
*/
+ − 1390
+ − 1391
QScriptEngine::QScriptEngine(QObject *parent)
+ − 1392
: QObject(*new QScriptEnginePrivate, parent)
+ − 1393
{
+ − 1394
}
+ − 1395
+ − 1396
/*! \internal
+ − 1397
*/
+ − 1398
QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
+ − 1399
: QObject(dd, parent)
+ − 1400
{
+ − 1401
}
+ − 1402
#endif
+ − 1403
+ − 1404
/*!
+ − 1405
Destroys this QScriptEngine.
+ − 1406
*/
+ − 1407
QScriptEngine::~QScriptEngine()
+ − 1408
{
+ − 1409
#ifdef QT_NO_QOBJECT
+ − 1410
delete d_ptr;
+ − 1411
d_ptr = 0;
+ − 1412
#endif
+ − 1413
}
+ − 1414
+ − 1415
/*!
+ − 1416
Returns this engine's Global Object.
+ − 1417
+ − 1418
By default, the Global Object contains the built-in objects that are
+ − 1419
part of \l{ECMA-262}, such as Math, Date and String. Additionally,
+ − 1420
you can set properties of the Global Object to make your own
+ − 1421
extensions available to all script code. Non-local variables in
+ − 1422
script code will be created as properties of the Global Object, as
+ − 1423
well as local variables in global code.
+ − 1424
*/
+ − 1425
QScriptValue QScriptEngine::globalObject() const
+ − 1426
{
+ − 1427
Q_D(const QScriptEngine);
+ − 1428
JSC::JSObject *result = d->globalObject();
+ − 1429
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
+ − 1430
}
+ − 1431
+ − 1432
/*!
+ − 1433
\since 4.5
+ − 1434
+ − 1435
Sets this engine's Global Object to be the given \a object.
+ − 1436
If \a object is not a valid script object, this function does
+ − 1437
nothing.
+ − 1438
+ − 1439
When setting a custom global object, you may want to use
+ − 1440
QScriptValueIterator to copy the properties of the standard Global
+ − 1441
Object; alternatively, you can set the internal prototype of your
+ − 1442
custom object to be the original Global Object.
+ − 1443
*/
+ − 1444
void QScriptEngine::setGlobalObject(const QScriptValue &object)
+ − 1445
{
+ − 1446
Q_D(QScriptEngine);
+ − 1447
if (!object.isObject())
+ − 1448
return;
+ − 1449
JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
+ − 1450
d->setGlobalObject(jscObject);
+ − 1451
}
+ − 1452
+ − 1453
/*!
+ − 1454
Returns a QScriptValue of the primitive type Null.
+ − 1455
+ − 1456
\sa undefinedValue()
+ − 1457
*/
+ − 1458
QScriptValue QScriptEngine::nullValue()
+ − 1459
{
+ − 1460
Q_D(QScriptEngine);
+ − 1461
return d->scriptValueFromJSCValue(JSC::jsNull());
+ − 1462
}
+ − 1463
+ − 1464
/*!
+ − 1465
Returns a QScriptValue of the primitive type Undefined.
+ − 1466
+ − 1467
\sa nullValue()
+ − 1468
*/
+ − 1469
QScriptValue QScriptEngine::undefinedValue()
+ − 1470
{
+ − 1471
Q_D(QScriptEngine);
+ − 1472
return d->scriptValueFromJSCValue(JSC::jsUndefined());
+ − 1473
}
+ − 1474
+ − 1475
/*!
+ − 1476
Creates a constructor function from \a fun, with the given \a length.
+ − 1477
The \c{prototype} property of the resulting function is set to be the
+ − 1478
given \a prototype. The \c{constructor} property of \a prototype is
+ − 1479
set to be the resulting function.
+ − 1480
+ − 1481
When a function is called as a constructor (e.g. \c{new Foo()}), the
+ − 1482
`this' object associated with the function call is the new object
+ − 1483
that the function is expected to initialize; the prototype of this
+ − 1484
default constructed object will be the function's public
+ − 1485
\c{prototype} property. If you always want the function to behave as
+ − 1486
a constructor (e.g. \c{Foo()} should also create a new object), or
+ − 1487
if you need to create your own object rather than using the default
+ − 1488
`this' object, you should make sure that the prototype of your
+ − 1489
object is set correctly; either by setting it manually, or, when
+ − 1490
wrapping a custom type, by having registered the defaultPrototype()
+ − 1491
of that type. Example:
+ − 1492
+ − 1493
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
+ − 1494
+ − 1495
To wrap a custom type and provide a constructor for it, you'd typically
+ − 1496
do something like this:
+ − 1497
+ − 1498
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
+ − 1499
*/
+ − 1500
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
+ − 1501
const QScriptValue &prototype,
+ − 1502
int length)
+ − 1503
{
+ − 1504
Q_D(QScriptEngine);
+ − 1505
JSC::ExecState* exec = d->currentFrame;
+ − 1506
JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
+ − 1507
QScriptValue result = d->scriptValueFromJSCValue(function);
+ − 1508
result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);
+ − 1509
const_cast<QScriptValue&>(prototype)
+ − 1510
.setProperty(QLatin1String("constructor"), result,
+ − 1511
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 1512
return result;
+ − 1513
}
+ − 1514
+ − 1515
#ifndef QT_NO_REGEXP
+ − 1516
+ − 1517
extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+ − 1518
+ − 1519
/*!
+ − 1520
Creates a QtScript object of class RegExp with the given
+ − 1521
\a regexp.
+ − 1522
+ − 1523
\sa QScriptValue::toRegExp()
+ − 1524
*/
+ − 1525
QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp)
+ − 1526
{
+ − 1527
Q_D(QScriptEngine);
+ − 1528
JSC::ExecState* exec = d->currentFrame;
+ − 1529
JSC::JSValue buf[2];
+ − 1530
JSC::ArgList args(buf, sizeof(buf));
+ − 1531
+ − 1532
//convert the pattern to a ECMAScript pattern
+ − 1533
QString pattern = qt_regexp_toCanonical(regexp.pattern(), regexp.patternSyntax());
+ − 1534
if (regexp.isMinimal()) {
+ − 1535
QString ecmaPattern;
+ − 1536
int len = pattern.length();
+ − 1537
ecmaPattern.reserve(len);
+ − 1538
int i = 0;
+ − 1539
const QChar *wc = pattern.unicode();
+ − 1540
bool inBracket = false;
+ − 1541
while (i < len) {
+ − 1542
QChar c = wc[i++];
+ − 1543
ecmaPattern += c;
+ − 1544
switch (c.unicode()) {
+ − 1545
case '?':
+ − 1546
case '+':
+ − 1547
case '*':
+ − 1548
case '}':
+ − 1549
if (!inBracket)
+ − 1550
ecmaPattern += QLatin1Char('?');
+ − 1551
break;
+ − 1552
case '\\':
+ − 1553
if (i < len)
+ − 1554
ecmaPattern += wc[i++];
+ − 1555
break;
+ − 1556
case '[':
+ − 1557
inBracket = true;
+ − 1558
break;
+ − 1559
case ']':
+ − 1560
inBracket = false;
+ − 1561
break;
+ − 1562
default:
+ − 1563
break;
+ − 1564
}
+ − 1565
}
+ − 1566
pattern = ecmaPattern;
+ − 1567
}
+ − 1568
+ − 1569
JSC::UString jscPattern = pattern;
+ − 1570
QString flags;
+ − 1571
if (regexp.caseSensitivity() == Qt::CaseInsensitive)
+ − 1572
flags.append(QLatin1Char('i'));
+ − 1573
JSC::UString jscFlags = flags;
+ − 1574
buf[0] = JSC::jsString(exec, jscPattern);
+ − 1575
buf[1] = JSC::jsString(exec, jscFlags);
+ − 1576
JSC::JSObject* result = JSC::constructRegExp(exec, args);
+ − 1577
return d->scriptValueFromJSCValue(result);
+ − 1578
}
+ − 1579
+ − 1580
#endif // QT_NO_REGEXP
+ − 1581
+ − 1582
/*!
+ − 1583
Creates a QtScript object holding the given variant \a value.
+ − 1584
+ − 1585
If a default prototype has been registered with the meta type id of
+ − 1586
\a value, then the prototype of the created object will be that
+ − 1587
prototype; otherwise, the prototype will be the Object prototype
+ − 1588
object.
+ − 1589
+ − 1590
\sa setDefaultPrototype(), QScriptValue::toVariant()
+ − 1591
*/
+ − 1592
QScriptValue QScriptEngine::newVariant(const QVariant &value)
+ − 1593
{
+ − 1594
Q_D(QScriptEngine);
+ − 1595
JSC::ExecState* exec = d->currentFrame;
+ − 1596
QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure);
+ − 1597
obj->setDelegate(new QScript::QVariantDelegate(value));
+ − 1598
QScriptValue result = d->scriptValueFromJSCValue(obj);
+ − 1599
QScriptValue proto = defaultPrototype(value.userType());
+ − 1600
if (proto.isValid())
+ − 1601
result.setPrototype(proto);
+ − 1602
return result;
+ − 1603
}
+ − 1604
+ − 1605
/*!
+ − 1606
\since 4.4
+ − 1607
\overload
+ − 1608
+ − 1609
Initializes the given Qt Script \a object to hold the given variant
+ − 1610
\a value, and returns the \a object.
+ − 1611
+ − 1612
This function enables you to "promote" a plain Qt Script object
+ − 1613
(created by the newObject() function) to a variant, or to replace
+ − 1614
the variant contained inside an object previously created by the
+ − 1615
newVariant() function.
+ − 1616
+ − 1617
The prototype() of the \a object will remain unchanged.
+ − 1618
+ − 1619
If \a object is not an object, this function behaves like the normal
+ − 1620
newVariant(), i.e. it creates a new script object and returns it.
+ − 1621
+ − 1622
This function is useful when you want to provide a script
+ − 1623
constructor for a C++ type. If your constructor is invoked in a
+ − 1624
\c{new} expression (QScriptContext::isCalledAsConstructor() returns
+ − 1625
true), you can pass QScriptContext::thisObject() (the default
+ − 1626
constructed script object) to this function to initialize the new
+ − 1627
object.
+ − 1628
*/
+ − 1629
QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
+ − 1630
const QVariant &value)
+ − 1631
{
+ − 1632
if (!object.isObject())
+ − 1633
return newVariant(value);
+ − 1634
JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue);
+ − 1635
if (!jscObject->inherits(&QScriptObject::info)) {
+ − 1636
qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
+ − 1637
return QScriptValue();
+ − 1638
}
+ − 1639
QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
+ − 1640
if (!object.isVariant()) {
+ − 1641
jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
+ − 1642
} else {
+ − 1643
QScriptValuePrivate::get(object)->setVariantValue(value);
+ − 1644
}
+ − 1645
return object;
+ − 1646
}
+ − 1647
+ − 1648
#ifndef QT_NO_QOBJECT
+ − 1649
/*!
+ − 1650
Creates a QtScript object that wraps the given QObject \a
+ − 1651
object, using the given \a ownership. The given \a options control
+ − 1652
various aspects of the interaction with the resulting script object.
+ − 1653
+ − 1654
Signals and slots, properties and children of \a object are
+ − 1655
available as properties of the created QScriptValue. For more
+ − 1656
information, see the \l{QtScript} documentation.
+ − 1657
+ − 1658
If \a object is a null pointer, this function returns nullValue().
+ − 1659
+ − 1660
If a default prototype has been registered for the \a object's class
+ − 1661
(or its superclass, recursively), the prototype of the new script
+ − 1662
object will be set to be that default prototype.
+ − 1663
+ − 1664
If the given \a object is deleted outside of QtScript's control, any
+ − 1665
attempt to access the deleted QObject's members through the QtScript
+ − 1666
wrapper object (either by script code or C++) will result in a
+ − 1667
script exception.
+ − 1668
+ − 1669
\sa QScriptValue::toQObject()
+ − 1670
*/
+ − 1671
QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
+ − 1672
const QObjectWrapOptions &options)
+ − 1673
{
+ − 1674
Q_D(QScriptEngine);
+ − 1675
JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
+ − 1676
return d->scriptValueFromJSCValue(jscQObject);
+ − 1677
}
+ − 1678
+ − 1679
/*!
+ − 1680
\since 4.4
+ − 1681
\overload
+ − 1682
+ − 1683
Initializes the given \a scriptObject to hold the given \a qtObject,
+ − 1684
and returns the \a scriptObject.
+ − 1685
+ − 1686
This function enables you to "promote" a plain Qt Script object
+ − 1687
(created by the newObject() function) to a QObject proxy, or to
+ − 1688
replace the QObject contained inside an object previously created by
+ − 1689
the newQObject() function.
+ − 1690
+ − 1691
The prototype() of the \a scriptObject will remain unchanged.
+ − 1692
+ − 1693
If \a scriptObject is not an object, this function behaves like the
+ − 1694
normal newQObject(), i.e. it creates a new script object and returns
+ − 1695
it.
+ − 1696
+ − 1697
This function is useful when you want to provide a script
+ − 1698
constructor for a QObject-based class. If your constructor is
+ − 1699
invoked in a \c{new} expression
+ − 1700
(QScriptContext::isCalledAsConstructor() returns true), you can pass
+ − 1701
QScriptContext::thisObject() (the default constructed script object)
+ − 1702
to this function to initialize the new object.
+ − 1703
*/
+ − 1704
QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
+ − 1705
QObject *qtObject,
+ − 1706
ValueOwnership ownership,
+ − 1707
const QObjectWrapOptions &options)
+ − 1708
{
+ − 1709
if (!scriptObject.isObject())
+ − 1710
return newQObject(qtObject, ownership, options);
+ − 1711
JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
+ − 1712
if (!jscObject->inherits(&QScriptObject::info)) {
+ − 1713
qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
+ − 1714
return QScriptValue();
+ − 1715
}
+ − 1716
QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
+ − 1717
if (!scriptObject.isQObject()) {
+ − 1718
jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
+ − 1719
} else {
+ − 1720
QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
+ − 1721
delegate->setValue(qtObject);
+ − 1722
delegate->setOwnership(ownership);
+ − 1723
delegate->setOptions(options);
+ − 1724
}
+ − 1725
return scriptObject;
+ − 1726
}
+ − 1727
+ − 1728
#endif // QT_NO_QOBJECT
+ − 1729
+ − 1730
/*!
+ − 1731
Creates a QtScript object of class Object.
+ − 1732
+ − 1733
The prototype of the created object will be the Object
+ − 1734
prototype object.
+ − 1735
+ − 1736
\sa newArray(), QScriptValue::setProperty()
+ − 1737
*/
+ − 1738
QScriptValue QScriptEngine::newObject()
+ − 1739
{
+ − 1740
Q_D(QScriptEngine);
+ − 1741
JSC::ExecState* exec = d->currentFrame;
+ − 1742
JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure);
+ − 1743
return d->scriptValueFromJSCValue(result);
+ − 1744
}
+ − 1745
+ − 1746
/*!
+ − 1747
\since 4.4
+ − 1748
\overload
+ − 1749
+ − 1750
Creates a QtScript Object of the given class, \a scriptClass.
+ − 1751
+ − 1752
The prototype of the created object will be the Object
+ − 1753
prototype object.
+ − 1754
+ − 1755
\a data, if specified, is set as the internal data of the
+ − 1756
new object (using QScriptValue::setData()).
+ − 1757
+ − 1758
\sa QScriptValue::scriptClass()
+ − 1759
*/
+ − 1760
QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
+ − 1761
const QScriptValue &data)
+ − 1762
{
+ − 1763
Q_D(QScriptEngine);
+ − 1764
JSC::ExecState* exec = d->currentFrame;
+ − 1765
QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
+ − 1766
result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
+ − 1767
QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
+ − 1768
scriptObject.setData(data);
+ − 1769
QScriptValue proto = scriptClass->prototype();
+ − 1770
if (proto.isValid())
+ − 1771
scriptObject.setPrototype(proto);
+ − 1772
return scriptObject;
+ − 1773
}
+ − 1774
+ − 1775
/*!
+ − 1776
\internal
+ − 1777
*/
+ − 1778
QScriptValue QScriptEngine::newActivationObject()
+ − 1779
{
+ − 1780
qWarning("QScriptEngine::newActivationObject() not implemented");
+ − 1781
// ### JSActivation or JSVariableObject?
+ − 1782
return QScriptValue();
+ − 1783
}
+ − 1784
+ − 1785
/*!
+ − 1786
Creates a QScriptValue that wraps a native (C++) function. \a fun
+ − 1787
must be a C++ function with signature QScriptEngine::FunctionSignature. \a
+ − 1788
length is the number of arguments that \a fun expects; this becomes
+ − 1789
the \c{length} property of the created QScriptValue.
+ − 1790
+ − 1791
Note that \a length only gives an indication of the number of
+ − 1792
arguments that the function expects; an actual invocation of a
+ − 1793
function can include any number of arguments. You can check the
+ − 1794
\l{QScriptContext::argumentCount()}{argumentCount()} of the
+ − 1795
QScriptContext associated with the invocation to determine the
+ − 1796
actual number of arguments passed.
+ − 1797
+ − 1798
A \c{prototype} property is automatically created for the resulting
+ − 1799
function object, to provide for the possibility that the function
+ − 1800
will be used as a constructor.
+ − 1801
+ − 1802
By combining newFunction() and the property flags
+ − 1803
QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
+ − 1804
can create script object properties that behave like normal
+ − 1805
properties in script code, but are in fact accessed through
+ − 1806
functions (analogous to how properties work in \l{Qt's Property
+ − 1807
System}). Example:
+ − 1808
+ − 1809
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
+ − 1810
+ − 1811
When the property \c{foo} of the script object is subsequently
+ − 1812
accessed in script code, \c{getSetFoo()} will be invoked to handle
+ − 1813
the access. In this particular case, we chose to store the "real"
+ − 1814
value of \c{foo} as a property of the accessor function itself; you
+ − 1815
are of course free to do whatever you like in this function.
+ − 1816
+ − 1817
In the above example, a single native function was used to handle
+ − 1818
both reads and writes to the property; the argument count is used to
+ − 1819
determine if we are handling a read or write. You can also use two
+ − 1820
separate functions; just specify the relevant flag
+ − 1821
(QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
+ − 1822
setting the property, e.g.:
+ − 1823
+ − 1824
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
+ − 1825
+ − 1826
\sa QScriptValue::call()
+ − 1827
*/
+ − 1828
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
+ − 1829
{
+ − 1830
Q_D(QScriptEngine);
+ − 1831
JSC::ExecState* exec = d->currentFrame;
+ − 1832
JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
+ − 1833
QScriptValue result = d->scriptValueFromJSCValue(function);
+ − 1834
QScriptValue proto = newObject();
+ − 1835
result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
+ − 1836
proto.setProperty(QLatin1String("constructor"), result,
+ − 1837
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 1838
return result;
+ − 1839
}
+ − 1840
+ − 1841
/*!
+ − 1842
\internal
+ − 1843
\since 4.4
+ − 1844
*/
+ − 1845
QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
+ − 1846
{
+ − 1847
Q_D(QScriptEngine);
+ − 1848
JSC::ExecState* exec = d->currentFrame;
+ − 1849
JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
+ − 1850
QScriptValue result = d->scriptValueFromJSCValue(function);
+ − 1851
QScriptValue proto = newObject();
+ − 1852
result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
+ − 1853
proto.setProperty(QLatin1String("constructor"), result,
+ − 1854
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 1855
return result;
+ − 1856
}
+ − 1857
+ − 1858
/*!
+ − 1859
Creates a QtScript object of class Array with the given \a length.
+ − 1860
+ − 1861
\sa newObject()
+ − 1862
*/
+ − 1863
QScriptValue QScriptEngine::newArray(uint length)
+ − 1864
{
+ − 1865
Q_D(QScriptEngine);
+ − 1866
JSC::ExecState* exec = d->currentFrame;
+ − 1867
JSC::JSArray* result = JSC::constructEmptyArray(exec, length);
+ − 1868
return d->scriptValueFromJSCValue(result);
+ − 1869
}
+ − 1870
+ − 1871
/*!
+ − 1872
Creates a QtScript object of class RegExp with the given
+ − 1873
\a pattern and \a flags.
+ − 1874
+ − 1875
The legal flags are 'g' (global), 'i' (ignore case), and 'm'
+ − 1876
(multiline).
+ − 1877
*/
+ − 1878
QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
+ − 1879
{
+ − 1880
Q_D(QScriptEngine);
+ − 1881
JSC::ExecState* exec = d->currentFrame;
+ − 1882
JSC::JSValue buf[2];
+ − 1883
JSC::ArgList args(buf, sizeof(buf));
+ − 1884
JSC::UString jscPattern = pattern;
+ − 1885
QString strippedFlags;
+ − 1886
if (flags.contains(QLatin1Char('i')))
+ − 1887
strippedFlags += QLatin1Char('i');
+ − 1888
if (flags.contains(QLatin1Char('m')))
+ − 1889
strippedFlags += QLatin1Char('m');
+ − 1890
if (flags.contains(QLatin1Char('g')))
+ − 1891
strippedFlags += QLatin1Char('g');
+ − 1892
JSC::UString jscFlags = strippedFlags;
+ − 1893
buf[0] = JSC::jsString(exec, jscPattern);
+ − 1894
buf[1] = JSC::jsString(exec, jscFlags);
+ − 1895
JSC::JSObject* result = JSC::constructRegExp(exec, args);
+ − 1896
return d->scriptValueFromJSCValue(result);
+ − 1897
}
+ − 1898
+ − 1899
/*!
+ − 1900
Creates a QtScript object of class Date with the given
+ − 1901
\a value (the number of milliseconds since 01 January 1970,
+ − 1902
UTC).
+ − 1903
*/
+ − 1904
QScriptValue QScriptEngine::newDate(qsreal value)
+ − 1905
{
+ − 1906
Q_D(QScriptEngine);
+ − 1907
JSC::ExecState* exec = d->currentFrame;
+ − 1908
JSC::JSValue val = JSC::jsNumber(exec, value);
+ − 1909
JSC::ArgList args(&val, 1);
+ − 1910
JSC::JSObject *result = JSC::constructDate(exec, args);
+ − 1911
return d->scriptValueFromJSCValue(result);
+ − 1912
}
+ − 1913
+ − 1914
/*!
+ − 1915
Creates a QtScript object of class Date from the given \a value.
+ − 1916
+ − 1917
\sa QScriptValue::toDateTime()
+ − 1918
*/
+ − 1919
QScriptValue QScriptEngine::newDate(const QDateTime &value)
+ − 1920
{
+ − 1921
return newDate(QScript::FromDateTime(value));
+ − 1922
}
+ − 1923
+ − 1924
#ifndef QT_NO_QOBJECT
+ − 1925
/*!
+ − 1926
Creates a QtScript object that represents a QObject class, using the
+ − 1927
the given \a metaObject and constructor \a ctor.
+ − 1928
+ − 1929
Enums of \a metaObject (declared with Q_ENUMS) are available as
+ − 1930
properties of the created QScriptValue. When the class is called as
+ − 1931
a function, \a ctor will be called to create a new instance of the
+ − 1932
class.
+ − 1933
+ − 1934
Example:
+ − 1935
+ − 1936
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27
+ − 1937
+ − 1938
\sa newQObject(), scriptValueFromQMetaObject()
+ − 1939
*/
+ − 1940
QScriptValue QScriptEngine::newQMetaObject(
+ − 1941
const QMetaObject *metaObject, const QScriptValue &ctor)
+ − 1942
{
+ − 1943
Q_D(QScriptEngine);
+ − 1944
JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor);
+ − 1945
JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor);
+ − 1946
return d->scriptValueFromJSCValue(jscQMetaObject);
+ − 1947
}
+ − 1948
+ − 1949
/*!
+ − 1950
\fn QScriptValue QScriptEngine::scriptValueFromQMetaObject()
+ − 1951
+ − 1952
Creates a QScriptValue that represents the Qt class \c{T}.
+ − 1953
+ − 1954
This function is used in combination with one of the
+ − 1955
Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example:
+ − 1956
+ − 1957
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13
+ − 1958
+ − 1959
\warning This function is not available with MSVC 6. Use
+ − 1960
qScriptValueFromQMetaObject() instead if you need to support that version
+ − 1961
of the compiler.
+ − 1962
+ − 1963
\sa QScriptEngine::newQMetaObject()
+ − 1964
*/
+ − 1965
+ − 1966
/*!
+ − 1967
\fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine)
+ − 1968
\since 4.3
+ − 1969
\relates QScriptEngine
+ − 1970
+ − 1971
Uses \a engine to create a QScriptValue that represents the Qt class
+ − 1972
\c{T}.
+ − 1973
+ − 1974
This function is equivalent to
+ − 1975
QScriptEngine::scriptValueFromQMetaObject(). It is provided as a
+ − 1976
work-around for MSVC 6, which doesn't support member template
+ − 1977
functions.
+ − 1978
+ − 1979
\sa QScriptEngine::newQMetaObject()
+ − 1980
*/
+ − 1981
#endif // QT_NO_QOBJECT
+ − 1982
+ − 1983
/*!
+ − 1984
\obsolete
+ − 1985
+ − 1986
Returns true if \a program can be evaluated; i.e. the code is
+ − 1987
sufficient to determine whether it appears to be a syntactically
+ − 1988
correct program, or contains a syntax error.
+ − 1989
+ − 1990
This function returns false if \a program is incomplete; i.e. the
+ − 1991
input is syntactically correct up to the point where the input is
+ − 1992
terminated.
+ − 1993
+ − 1994
Note that this function only does a static check of \a program;
+ − 1995
e.g. it does not check whether references to variables are
+ − 1996
valid, and so on.
+ − 1997
+ − 1998
A typical usage of canEvaluate() is to implement an interactive
+ − 1999
interpreter for QtScript. The user is repeatedly queried for
+ − 2000
individual lines of code; the lines are concatened internally, and
+ − 2001
only when canEvaluate() returns true for the resulting program is it
+ − 2002
passed to evaluate().
+ − 2003
+ − 2004
The following are some examples to illustrate the behavior of
+ − 2005
canEvaluate(). (Note that all example inputs are assumed to have an
+ − 2006
explicit newline as their last character, since otherwise the
+ − 2007
QtScript parser would automatically insert a semi-colon character at
+ − 2008
the end of the input, and this could cause canEvaluate() to produce
+ − 2009
different results.)
+ − 2010
+ − 2011
Given the input
+ − 2012
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14
+ − 2013
canEvaluate() will return true, since the program appears to be complete.
+ − 2014
+ − 2015
Given the input
+ − 2016
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15
+ − 2017
canEvaluate() will return false, since the if-statement is not complete,
+ − 2018
but is syntactically correct so far.
+ − 2019
+ − 2020
Given the input
+ − 2021
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16
+ − 2022
canEvaluate() will return true, but evaluate() will throw a
+ − 2023
SyntaxError given the same input.
+ − 2024
+ − 2025
Given the input
+ − 2026
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17
+ − 2027
canEvaluate() will return true, even though the code is clearly not
+ − 2028
syntactically valid QtScript code. evaluate() will throw a
+ − 2029
SyntaxError when this code is evaluated.
+ − 2030
+ − 2031
Given the input
+ − 2032
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18
+ − 2033
canEvaluate() will return true, but evaluate() will throw a
+ − 2034
ReferenceError if \c{foo} is not defined in the script
+ − 2035
environment.
+ − 2036
+ − 2037
\sa evaluate(), checkSyntax()
+ − 2038
*/
+ − 2039
bool QScriptEngine::canEvaluate(const QString &program) const
+ − 2040
{
+ − 2041
return QScriptEnginePrivate::canEvaluate(program);
+ − 2042
}
+ − 2043
+ − 2044
+ − 2045
bool QScriptEnginePrivate::canEvaluate(const QString &program)
+ − 2046
{
+ − 2047
QScript::SyntaxChecker checker;
+ − 2048
QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
+ − 2049
return (result.state != QScript::SyntaxChecker::Intermediate);
+ − 2050
}
+ − 2051
+ − 2052
/*!
+ − 2053
\since 4.5
+ − 2054
+ − 2055
Checks the syntax of the given \a program. Returns a
+ − 2056
QScriptSyntaxCheckResult object that contains the result of the check.
+ − 2057
*/
+ − 2058
QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
+ − 2059
{
+ − 2060
return QScriptEnginePrivate::checkSyntax(program);
+ − 2061
}
+ − 2062
+ − 2063
QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program)
+ − 2064
{
+ − 2065
QScript::SyntaxChecker checker;
+ − 2066
QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
+ − 2067
QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate();
+ − 2068
switch (result.state) {
+ − 2069
case QScript::SyntaxChecker::Error:
+ − 2070
p->state = QScriptSyntaxCheckResult::Error;
+ − 2071
break;
+ − 2072
case QScript::SyntaxChecker::Intermediate:
+ − 2073
p->state = QScriptSyntaxCheckResult::Intermediate;
+ − 2074
break;
+ − 2075
case QScript::SyntaxChecker::Valid:
+ − 2076
p->state = QScriptSyntaxCheckResult::Valid;
+ − 2077
break;
+ − 2078
}
+ − 2079
p->errorLineNumber = result.errorLineNumber;
+ − 2080
p->errorColumnNumber = result.errorColumnNumber;
+ − 2081
p->errorMessage = result.errorMessage;
+ − 2082
return QScriptSyntaxCheckResult(p);
+ − 2083
}
+ − 2084
+ − 2085
+ − 2086
+ − 2087
/*!
+ − 2088
Evaluates \a program, using \a lineNumber as the base line number,
+ − 2089
and returns the result of the evaluation.
+ − 2090
+ − 2091
The script code will be evaluated in the current context.
+ − 2092
+ − 2093
The evaluation of \a program can cause an exception in the
+ − 2094
engine; in this case the return value will be the exception
+ − 2095
that was thrown (typically an \c{Error} object). You can call
+ − 2096
hasUncaughtException() to determine if an exception occurred in
+ − 2097
the last call to evaluate().
+ − 2098
+ − 2099
\a lineNumber is used to specify a starting line number for \a
+ − 2100
program; line number information reported by the engine that pertain
+ − 2101
to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
+ − 2102
based on this argument. For example, if \a program consists of two
+ − 2103
lines of code, and the statement on the second line causes a script
+ − 2104
exception, uncaughtExceptionLineNumber() would return the given \a
+ − 2105
lineNumber plus one. When no starting line number is specified, line
+ − 2106
numbers will be 1-based.
+ − 2107
+ − 2108
\a fileName is used for error reporting. For example in error objects
+ − 2109
the file name is accessible through the "fileName" property if it's
+ − 2110
provided with this function.
+ − 2111
+ − 2112
\sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation()
+ − 2113
*/
+ − 2114
+ − 2115
QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber)
+ − 2116
{
+ − 2117
Q_D(QScriptEngine);
+ − 2118
+ − 2119
JSC::JSLock lock(false); // ### hmmm
+ − 2120
QBoolBlocker inEval(d->inEval, true);
+ − 2121
currentContext()->activationObject(); //force the creation of a context for native function;
+ − 2122
+ − 2123
JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
+ − 2124
+ − 2125
JSC::UString jscProgram = program;
+ − 2126
JSC::UString jscFileName = fileName;
+ − 2127
JSC::ExecState* exec = d->currentFrame;
+ − 2128
WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
+ − 2129
= QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d);
+ − 2130
intptr_t sourceId = provider->asID();
+ − 2131
JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null.
+ − 2132
+ − 2133
if (debugger)
+ − 2134
debugger->evaluateStart(sourceId);
+ − 2135
+ − 2136
clearExceptions();
+ − 2137
JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
+ − 2138
+ − 2139
JSC::EvalExecutable executable(exec, source);
+ − 2140
JSC::JSObject* error = executable.compile(exec, exec->scopeChain());
+ − 2141
if (error) {
+ − 2142
exec->setException(error);
+ − 2143
+ − 2144
if (debugger) {
+ − 2145
debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, error), sourceId, false);
+ − 2146
debugger->evaluateStop(error, sourceId);
+ − 2147
}
+ − 2148
+ − 2149
return d->scriptValueFromJSCValue(error);
+ − 2150
}
+ − 2151
+ − 2152
JSC::JSValue thisValue = d->thisForContext(exec);
+ − 2153
JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
+ − 2154
JSC::JSValue exceptionValue;
+ − 2155
d->timeoutChecker()->setShouldAbort(false);
+ − 2156
if (d->processEventsInterval > 0)
+ − 2157
d->timeoutChecker()->reset();
+ − 2158
JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
+ − 2159
+ − 2160
if (d->timeoutChecker()->shouldAbort()) {
+ − 2161
if (d->abortResult.isError())
+ − 2162
exec->setException(d->scriptValueToJSCValue(d->abortResult));
+ − 2163
+ − 2164
if (debugger)
+ − 2165
debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId);
+ − 2166
+ − 2167
return d->abortResult;
+ − 2168
}
+ − 2169
+ − 2170
if (exceptionValue) {
+ − 2171
exec->setException(exceptionValue);
+ − 2172
+ − 2173
if (debugger)
+ − 2174
debugger->evaluateStop(exceptionValue, sourceId);
+ − 2175
+ − 2176
return d->scriptValueFromJSCValue(exceptionValue);
+ − 2177
}
+ − 2178
+ − 2179
if (debugger)
+ − 2180
debugger->evaluateStop(result, sourceId);
+ − 2181
+ − 2182
Q_ASSERT(!exec->hadException());
+ − 2183
return d->scriptValueFromJSCValue(result);
+ − 2184
}
+ − 2185
+ − 2186
+ − 2187
/*!
+ − 2188
Returns the current context.
+ − 2189
+ − 2190
The current context is typically accessed to retrieve the arguments
+ − 2191
and `this' object in native functions; for convenience, it is
+ − 2192
available as the first argument in QScriptEngine::FunctionSignature.
+ − 2193
*/
+ − 2194
QScriptContext *QScriptEngine::currentContext() const
+ − 2195
{
+ − 2196
Q_D(const QScriptEngine);
+ − 2197
return const_cast<QScriptEnginePrivate*>(d)->contextForFrame(d->currentFrame);
+ − 2198
}
+ − 2199
+ − 2200
/*!
+ − 2201
Enters a new execution context and returns the associated
+ − 2202
QScriptContext object.
+ − 2203
+ − 2204
Once you are done with the context, you should call popContext() to
+ − 2205
restore the old context.
+ − 2206
+ − 2207
By default, the `this' object of the new context is the Global Object.
+ − 2208
The context's \l{QScriptContext::callee()}{callee}() will be invalid.
+ − 2209
+ − 2210
This function is useful when you want to evaluate script code
+ − 2211
as if it were the body of a function. You can use the context's
+ − 2212
\l{QScriptContext::activationObject()}{activationObject}() to initialize
+ − 2213
local variables that will be available to scripts. Example:
+ − 2214
+ − 2215
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19
+ − 2216
+ − 2217
In the above example, the new variable "tmp" defined in the script
+ − 2218
will be local to the context; in other words, the script doesn't
+ − 2219
have any effect on the global environment.
+ − 2220
+ − 2221
Returns 0 in case of stack overflow
+ − 2222
+ − 2223
\sa popContext()
+ − 2224
*/
+ − 2225
QScriptContext *QScriptEngine::pushContext()
+ − 2226
{
+ − 2227
Q_D(QScriptEngine);
+ − 2228
+ − 2229
JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
+ − 2230
JSC::ArgList(), /*callee = */0);
+ − 2231
+ − 2232
if (agent())
+ − 2233
agent()->contextPush();
+ − 2234
+ − 2235
return d->contextForFrame(newFrame);
+ − 2236
}
+ − 2237
+ − 2238
/*! \internal
+ − 2239
push a context for a native function.
+ − 2240
JSC native function doesn't have different stackframe or context. so we need to create one.
+ − 2241
+ − 2242
use popContext right after to go back to the previous context the context if no stack overflow has hapenned
+ − 2243
+ − 2244
exec is the current top frame.
+ − 2245
+ − 2246
return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
+ − 2247
*/
+ − 2248
JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
+ − 2249
const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor)
+ − 2250
{
+ − 2251
JSC::JSValue thisObject = _thisObject;
+ − 2252
if (calledAsConstructor) {
+ − 2253
//JSC doesn't create default created object for native functions. so we do it
+ − 2254
JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype);
+ − 2255
JSC::Structure *structure = prototype.isObject() ? JSC::asObject(prototype)->inheritorID()
+ − 2256
: originalGlobalObject()->emptyObjectStructure();
+ − 2257
thisObject = new (exec) QScriptObject(structure);
+ − 2258
}
+ − 2259
+ − 2260
int flags = NativeContext;
+ − 2261
if (calledAsConstructor)
+ − 2262
flags |= CalledAsConstructorContext;
+ − 2263
+ − 2264
//build a frame
+ − 2265
JSC::CallFrame *newCallFrame = exec;
+ − 2266
if (callee == 0 //called from public QScriptEngine::pushContext
+ − 2267
|| exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
+ − 2268
|| (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us.
+ − 2269
//We need to check if the Interpreter might have already created a frame for function called from JS.
+ − 2270
JSC::Interpreter *interp = exec->interpreter();
+ − 2271
JSC::Register *oldEnd = interp->registerFile().end();
+ − 2272
int argc = args.size() + 1; //add "this"
+ − 2273
JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize;
+ − 2274
if (!interp->registerFile().grow(newEnd))
+ − 2275
return 0; //### Stack overflow
+ − 2276
newCallFrame = JSC::CallFrame::create(oldEnd);
+ − 2277
newCallFrame[0] = thisObject;
+ − 2278
int dst = 0;
+ − 2279
JSC::ArgList::const_iterator it;
+ − 2280
for (it = args.begin(); it != args.end(); ++it)
+ − 2281
newCallFrame[++dst] = *it;
+ − 2282
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
+ − 2283
newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+ − 2284
} else {
+ − 2285
setContextFlags(newCallFrame, flags);
+ − 2286
#if ENABLE(JIT)
+ − 2287
exec->registers()[JSC::RegisterFile::Callee] = JSC::JSValue(callee); //JIT let the callee set the 'callee'
+ − 2288
#endif
+ − 2289
if (calledAsConstructor) {
+ − 2290
//update the new created this
+ − 2291
JSC::Register* thisRegister = thisRegisterForFrame(newCallFrame);
+ − 2292
*thisRegister = thisObject;
+ − 2293
}
+ − 2294
}
+ − 2295
currentFrame = newCallFrame;
+ − 2296
return newCallFrame;
+ − 2297
}
+ − 2298
+ − 2299
+ − 2300
/*!
+ − 2301
Pops the current execution context and restores the previous one.
+ − 2302
This function must be used in conjunction with pushContext().
+ − 2303
+ − 2304
\sa pushContext()
+ − 2305
*/
+ − 2306
void QScriptEngine::popContext()
+ − 2307
{
+ − 2308
if (agent())
+ − 2309
agent()->contextPop();
+ − 2310
Q_D(QScriptEngine);
+ − 2311
if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
+ − 2312
|| !currentContext()->parentContext()) {
+ − 2313
qWarning("QScriptEngine::popContext() doesn't match with pushContext()");
+ − 2314
return;
+ − 2315
}
+ − 2316
+ − 2317
d->popContext();
+ − 2318
}
+ − 2319
+ − 2320
/*! \internal
+ − 2321
counter part of QScriptEnginePrivate::pushContext
+ − 2322
*/
+ − 2323
void QScriptEnginePrivate::popContext()
+ − 2324
{
+ − 2325
uint flags = contextFlags(currentFrame);
+ − 2326
bool hasScope = flags & HasScopeContext;
+ − 2327
if (flags & ShouldRestoreCallFrame) { //normal case
+ − 2328
JSC::RegisterFile ®isterFile = currentFrame->interpreter()->registerFile();
+ − 2329
JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
+ − 2330
if (hasScope)
+ − 2331
currentFrame->scopeChain()->pop()->deref();
+ − 2332
registerFile.shrink(newEnd);
+ − 2333
} else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it.
+ − 2334
currentFrame->setScopeChain(currentFrame->scopeChain()->pop());
+ − 2335
currentFrame->scopeChain()->deref();
+ − 2336
}
+ − 2337
currentFrame = currentFrame->callerFrame();
+ − 2338
}
+ − 2339
+ − 2340
/*!
+ − 2341
Returns true if the last script evaluation resulted in an uncaught
+ − 2342
exception; otherwise returns false.
+ − 2343
+ − 2344
The exception state is cleared when evaluate() is called.
+ − 2345
+ − 2346
\sa uncaughtException(), uncaughtExceptionLineNumber(),
+ − 2347
uncaughtExceptionBacktrace()
+ − 2348
*/
+ − 2349
bool QScriptEngine::hasUncaughtException() const
+ − 2350
{
+ − 2351
Q_D(const QScriptEngine);
+ − 2352
JSC::ExecState* exec = d->globalExec();
+ − 2353
return exec->hadException() || d->currentException().isValid();
+ − 2354
}
+ − 2355
+ − 2356
/*!
+ − 2357
Returns the current uncaught exception, or an invalid QScriptValue
+ − 2358
if there is no uncaught exception.
+ − 2359
+ − 2360
The exception value is typically an \c{Error} object; in that case,
+ − 2361
you can call toString() on the return value to obtain an error
+ − 2362
message.
+ − 2363
+ − 2364
\sa hasUncaughtException(), uncaughtExceptionLineNumber(),
+ − 2365
uncaughtExceptionBacktrace()
+ − 2366
*/
+ − 2367
QScriptValue QScriptEngine::uncaughtException() const
+ − 2368
{
+ − 2369
Q_D(const QScriptEngine);
+ − 2370
QScriptValue result;
+ − 2371
JSC::ExecState* exec = d->globalExec();
+ − 2372
if (exec->hadException())
+ − 2373
result = const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(exec->exception());
+ − 2374
else
+ − 2375
result = d->currentException();
+ − 2376
return result;
+ − 2377
}
+ − 2378
+ − 2379
/*!
+ − 2380
Returns the line number where the last uncaught exception occurred.
+ − 2381
+ − 2382
Line numbers are 1-based, unless a different base was specified as
+ − 2383
the second argument to evaluate().
+ − 2384
+ − 2385
\sa hasUncaughtException(), uncaughtExceptionBacktrace()
+ − 2386
*/
+ − 2387
int QScriptEngine::uncaughtExceptionLineNumber() const
+ − 2388
{
+ − 2389
if (!hasUncaughtException())
+ − 2390
return -1;
+ − 2391
return uncaughtException().property(QLatin1String("lineNumber")).toInt32();
+ − 2392
}
+ − 2393
+ − 2394
/*!
+ − 2395
Returns a human-readable backtrace of the last uncaught exception.
+ − 2396
+ − 2397
Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
+ − 2398
+ − 2399
\sa uncaughtException()
+ − 2400
*/
+ − 2401
QStringList QScriptEngine::uncaughtExceptionBacktrace() const
+ − 2402
{
+ − 2403
if (!hasUncaughtException())
+ − 2404
return QStringList();
+ − 2405
// ### currently no way to get a full backtrace from JSC without installing a
+ − 2406
// debugger that reimplements exception() and store the backtrace there.
+ − 2407
QScriptValue value = uncaughtException();
+ − 2408
if (!value.isError())
+ − 2409
return QStringList();
+ − 2410
QStringList result;
+ − 2411
result.append(QString::fromLatin1("<anonymous>()@%0:%1")
+ − 2412
.arg(value.property(QLatin1String("fileName")).toString())
+ − 2413
.arg(value.property(QLatin1String("lineNumber")).toInt32()));
+ − 2414
return result;
+ − 2415
}
+ − 2416
+ − 2417
/*!
+ − 2418
\since 4.4
+ − 2419
+ − 2420
Clears any uncaught exceptions in this engine.
+ − 2421
+ − 2422
\sa hasUncaughtException()
+ − 2423
*/
+ − 2424
void QScriptEngine::clearExceptions()
+ − 2425
{
+ − 2426
Q_D(QScriptEngine);
+ − 2427
JSC::ExecState* exec = d->currentFrame;
+ − 2428
exec->clearException();
+ − 2429
d->clearCurrentException();
+ − 2430
}
+ − 2431
+ − 2432
/*!
+ − 2433
Returns the default prototype associated with the given \a metaTypeId,
+ − 2434
or an invalid QScriptValue if no default prototype has been set.
+ − 2435
+ − 2436
\sa setDefaultPrototype()
+ − 2437
*/
+ − 2438
QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const
+ − 2439
{
+ − 2440
Q_D(const QScriptEngine);
+ − 2441
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(d->defaultPrototype(metaTypeId));
+ − 2442
}
+ − 2443
+ − 2444
/*!
+ − 2445
Sets the default prototype of the C++ type identified by the given
+ − 2446
\a metaTypeId to \a prototype.
+ − 2447
+ − 2448
The default prototype provides a script interface for values of
+ − 2449
type \a metaTypeId when a value of that type is accessed from script
+ − 2450
code. Whenever the script engine (implicitly or explicitly) creates
+ − 2451
a QScriptValue from a value of type \a metaTypeId, the default
+ − 2452
prototype will be set as the QScriptValue's prototype.
+ − 2453
+ − 2454
The \a prototype object itself may be constructed using one of two
+ − 2455
principal techniques; the simplest is to subclass QScriptable, which
+ − 2456
enables you to define the scripting API of the type through QObject
+ − 2457
properties and slots. Another possibility is to create a script
+ − 2458
object by calling newObject(), and populate the object with the
+ − 2459
desired properties (e.g. native functions wrapped with
+ − 2460
newFunction()).
+ − 2461
+ − 2462
\sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example}
+ − 2463
*/
+ − 2464
void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype)
+ − 2465
{
+ − 2466
Q_D(QScriptEngine);
+ − 2467
d->setDefaultPrototype(metaTypeId, d->scriptValueToJSCValue(prototype));
+ − 2468
}
+ − 2469
+ − 2470
/*!
+ − 2471
\typedef QScriptEngine::FunctionSignature
+ − 2472
\relates QScriptEngine
+ − 2473
+ − 2474
The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
+ − 2475
+ − 2476
A function with such a signature can be passed to
+ − 2477
QScriptEngine::newFunction() to wrap the function.
+ − 2478
*/
+ − 2479
+ − 2480
/*!
+ − 2481
\typedef QScriptEngine::FunctionWithArgSignature
+ − 2482
\relates QScriptEngine
+ − 2483
+ − 2484
The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
+ − 2485
+ − 2486
A function with such a signature can be passed to
+ − 2487
QScriptEngine::newFunction() to wrap the function.
+ − 2488
*/
+ − 2489
+ − 2490
/*!
+ − 2491
\typedef QScriptEngine::MarshalFunction
+ − 2492
\internal
+ − 2493
*/
+ − 2494
+ − 2495
/*!
+ − 2496
\typedef QScriptEngine::DemarshalFunction
+ − 2497
\internal
+ − 2498
*/
+ − 2499
+ − 2500
/*!
+ − 2501
\internal
+ − 2502
*/
+ − 2503
QScriptValue QScriptEngine::create(int type, const void *ptr)
+ − 2504
{
+ − 2505
Q_D(QScriptEngine);
+ − 2506
return d->create(type, ptr);
+ − 2507
}
+ − 2508
+ − 2509
QScriptValue QScriptEnginePrivate::create(int type, const void *ptr)
+ − 2510
{
+ − 2511
Q_Q(QScriptEngine);
+ − 2512
Q_ASSERT(ptr != 0);
+ − 2513
QScriptValue result;
+ − 2514
QScriptTypeInfo *info = m_typeInfos.value(type);
+ − 2515
if (info && info->marshal) {
+ − 2516
result = info->marshal(q, ptr);
+ − 2517
} else {
+ − 2518
// check if it's one of the types we know
+ − 2519
switch (QMetaType::Type(type)) {
+ − 2520
case QMetaType::Void:
+ − 2521
return QScriptValue(q, QScriptValue::UndefinedValue);
+ − 2522
case QMetaType::Bool:
+ − 2523
return QScriptValue(q, *reinterpret_cast<const bool*>(ptr));
+ − 2524
case QMetaType::Int:
+ − 2525
return QScriptValue(q, *reinterpret_cast<const int*>(ptr));
+ − 2526
case QMetaType::UInt:
+ − 2527
return QScriptValue(q, *reinterpret_cast<const uint*>(ptr));
+ − 2528
case QMetaType::LongLong:
+ − 2529
return QScriptValue(q, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
+ − 2530
case QMetaType::ULongLong:
+ − 2531
#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
+ − 2532
#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
+ − 2533
return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
+ − 2534
#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
+ − 2535
return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
+ − 2536
#else
+ − 2537
return QScriptValue(q, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
+ − 2538
#endif
+ − 2539
case QMetaType::Double:
+ − 2540
return QScriptValue(q, qsreal(*reinterpret_cast<const double*>(ptr)));
+ − 2541
case QMetaType::QString:
+ − 2542
return QScriptValue(q, *reinterpret_cast<const QString*>(ptr));
+ − 2543
case QMetaType::Float:
+ − 2544
return QScriptValue(q, *reinterpret_cast<const float*>(ptr));
+ − 2545
case QMetaType::Short:
+ − 2546
return QScriptValue(q, *reinterpret_cast<const short*>(ptr));
+ − 2547
case QMetaType::UShort:
+ − 2548
return QScriptValue(q, *reinterpret_cast<const unsigned short*>(ptr));
+ − 2549
case QMetaType::Char:
+ − 2550
return QScriptValue(q, *reinterpret_cast<const char*>(ptr));
+ − 2551
case QMetaType::UChar:
+ − 2552
return QScriptValue(q, *reinterpret_cast<const unsigned char*>(ptr));
+ − 2553
case QMetaType::QChar:
+ − 2554
return QScriptValue(q, (*reinterpret_cast<const QChar*>(ptr)).unicode());
+ − 2555
case QMetaType::QStringList:
+ − 2556
result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr));
+ − 2557
break;
+ − 2558
case QMetaType::QVariantList:
+ − 2559
result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr));
+ − 2560
break;
+ − 2561
case QMetaType::QVariantMap:
+ − 2562
result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr));
+ − 2563
break;
+ − 2564
case QMetaType::QDateTime:
+ − 2565
result = q->newDate(*reinterpret_cast<const QDateTime *>(ptr));
+ − 2566
break;
+ − 2567
case QMetaType::QDate:
+ − 2568
result = q->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)));
+ − 2569
break;
+ − 2570
#ifndef QT_NO_REGEXP
+ − 2571
case QMetaType::QRegExp:
+ − 2572
result = q->newRegExp(*reinterpret_cast<const QRegExp *>(ptr));
+ − 2573
break;
+ − 2574
#endif
+ − 2575
#ifndef QT_NO_QOBJECT
+ − 2576
case QMetaType::QObjectStar:
+ − 2577
case QMetaType::QWidgetStar:
+ − 2578
result = q->newQObject(*reinterpret_cast<QObject* const *>(ptr));
+ − 2579
break;
+ − 2580
#endif
+ − 2581
default:
+ − 2582
if (type == qMetaTypeId<QScriptValue>()) {
+ − 2583
result = *reinterpret_cast<const QScriptValue*>(ptr);
+ − 2584
if (!result.isValid())
+ − 2585
return QScriptValue(q, QScriptValue::UndefinedValue);
+ − 2586
}
+ − 2587
+ − 2588
#ifndef QT_NO_QOBJECT
+ − 2589
// lazy registration of some common list types
+ − 2590
else if (type == qMetaTypeId<QObjectList>()) {
+ − 2591
qScriptRegisterSequenceMetaType<QObjectList>(q);
+ − 2592
return create(type, ptr);
+ − 2593
}
+ − 2594
#endif
+ − 2595
else if (type == qMetaTypeId<QList<int> >()) {
+ − 2596
qScriptRegisterSequenceMetaType<QList<int> >(q);
+ − 2597
return create(type, ptr);
+ − 2598
}
+ − 2599
+ − 2600
else {
+ − 2601
QByteArray typeName = QMetaType::typeName(type);
+ − 2602
if (typeName == "QVariant")
+ − 2603
result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr));
+ − 2604
if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
+ − 2605
return QScriptValue(q, QScriptValue::NullValue);
+ − 2606
else
+ − 2607
result = q->newVariant(QVariant(type, ptr));
+ − 2608
}
+ − 2609
}
+ − 2610
}
+ − 2611
if (result.isObject() && info && info->prototype
+ − 2612
&& JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) {
+ − 2613
result.setPrototype(scriptValueFromJSCValue(info->prototype));
+ − 2614
}
+ − 2615
return result;
+ − 2616
}
+ − 2617
+ − 2618
bool QScriptEnginePrivate::convert(const QScriptValue &value,
+ − 2619
int type, void *ptr,
+ − 2620
QScriptEnginePrivate *eng)
+ − 2621
{
+ − 2622
if (!eng)
+ − 2623
eng = QScriptValuePrivate::getEngine(value);
+ − 2624
if (eng) {
+ − 2625
QScriptTypeInfo *info = eng->m_typeInfos.value(type);
+ − 2626
if (info && info->demarshal) {
+ − 2627
info->demarshal(value, ptr);
+ − 2628
return true;
+ − 2629
}
+ − 2630
}
+ − 2631
+ − 2632
// check if it's one of the types we know
+ − 2633
switch (QMetaType::Type(type)) {
+ − 2634
case QMetaType::Bool:
+ − 2635
*reinterpret_cast<bool*>(ptr) = value.toBoolean();
+ − 2636
return true;
+ − 2637
case QMetaType::Int:
+ − 2638
*reinterpret_cast<int*>(ptr) = value.toInt32();
+ − 2639
return true;
+ − 2640
case QMetaType::UInt:
+ − 2641
*reinterpret_cast<uint*>(ptr) = value.toUInt32();
+ − 2642
return true;
+ − 2643
case QMetaType::LongLong:
+ − 2644
*reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger());
+ − 2645
return true;
+ − 2646
case QMetaType::ULongLong:
+ − 2647
*reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger());
+ − 2648
return true;
+ − 2649
case QMetaType::Double:
+ − 2650
*reinterpret_cast<double*>(ptr) = value.toNumber();
+ − 2651
return true;
+ − 2652
case QMetaType::QString:
+ − 2653
if (value.isUndefined() || value.isNull())
+ − 2654
*reinterpret_cast<QString*>(ptr) = QString();
+ − 2655
else
+ − 2656
*reinterpret_cast<QString*>(ptr) = value.toString();
+ − 2657
return true;
+ − 2658
case QMetaType::Float:
+ − 2659
*reinterpret_cast<float*>(ptr) = value.toNumber();
+ − 2660
return true;
+ − 2661
case QMetaType::Short:
+ − 2662
*reinterpret_cast<short*>(ptr) = short(value.toInt32());
+ − 2663
return true;
+ − 2664
case QMetaType::UShort:
+ − 2665
*reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();
+ − 2666
return true;
+ − 2667
case QMetaType::Char:
+ − 2668
*reinterpret_cast<char*>(ptr) = char(value.toInt32());
+ − 2669
return true;
+ − 2670
case QMetaType::UChar:
+ − 2671
*reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32());
+ − 2672
return true;
+ − 2673
case QMetaType::QChar:
+ − 2674
if (value.isString()) {
+ − 2675
QString str = value.toString();
+ − 2676
*reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
+ − 2677
} else {
+ − 2678
*reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16());
+ − 2679
}
+ − 2680
return true;
+ − 2681
case QMetaType::QDateTime:
+ − 2682
if (value.isDate()) {
+ − 2683
*reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();
+ − 2684
return true;
+ − 2685
} break;
+ − 2686
case QMetaType::QDate:
+ − 2687
if (value.isDate()) {
+ − 2688
*reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();
+ − 2689
return true;
+ − 2690
} break;
+ − 2691
#ifndef QT_NO_REGEXP
+ − 2692
case QMetaType::QRegExp:
+ − 2693
if (value.isRegExp()) {
+ − 2694
*reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();
+ − 2695
return true;
+ − 2696
} break;
+ − 2697
#endif
+ − 2698
#ifndef QT_NO_QOBJECT
+ − 2699
case QMetaType::QObjectStar:
+ − 2700
if (value.isQObject() || value.isNull()) {
+ − 2701
*reinterpret_cast<QObject* *>(ptr) = value.toQObject();
+ − 2702
return true;
+ − 2703
} break;
+ − 2704
case QMetaType::QWidgetStar:
+ − 2705
if (value.isQObject() || value.isNull()) {
+ − 2706
QObject *qo = value.toQObject();
+ − 2707
if (!qo || qo->isWidgetType()) {
+ − 2708
*reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
+ − 2709
return true;
+ − 2710
}
+ − 2711
} break;
+ − 2712
#endif
+ − 2713
case QMetaType::QStringList:
+ − 2714
if (value.isArray()) {
+ − 2715
*reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value);
+ − 2716
return true;
+ − 2717
} break;
+ − 2718
case QMetaType::QVariantList:
+ − 2719
if (value.isArray()) {
+ − 2720
*reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value);
+ − 2721
return true;
+ − 2722
} break;
+ − 2723
case QMetaType::QVariantMap:
+ − 2724
if (value.isObject()) {
+ − 2725
*reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value);
+ − 2726
return true;
+ − 2727
} break;
+ − 2728
default:
+ − 2729
;
+ − 2730
}
+ − 2731
+ − 2732
QByteArray name = QMetaType::typeName(type);
+ − 2733
#ifndef QT_NO_QOBJECT
+ − 2734
if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr)))
+ − 2735
return true;
+ − 2736
#endif
+ − 2737
if (value.isVariant() && name.endsWith('*')) {
+ − 2738
int valueType = QMetaType::type(name.left(name.size()-1));
+ − 2739
QVariant &var = QScriptValuePrivate::get(value)->variantValue();
+ − 2740
if (valueType == var.userType()) {
+ − 2741
*reinterpret_cast<void* *>(ptr) = var.data();
+ − 2742
return true;
+ − 2743
} else {
+ − 2744
// look in the prototype chain
+ − 2745
QScriptValue proto = value.prototype();
+ − 2746
while (proto.isObject()) {
+ − 2747
bool canCast = false;
+ − 2748
if (proto.isVariant()) {
+ − 2749
canCast = (type == proto.toVariant().userType())
+ − 2750
|| (valueType && (valueType == proto.toVariant().userType()));
+ − 2751
}
+ − 2752
#ifndef QT_NO_QOBJECT
+ − 2753
else if (proto.isQObject()) {
+ − 2754
QByteArray className = name.left(name.size()-1);
+ − 2755
if (QObject *qobject = proto.toQObject())
+ − 2756
canCast = qobject->qt_metacast(className) != 0;
+ − 2757
}
+ − 2758
#endif
+ − 2759
if (canCast) {
+ − 2760
QByteArray varTypeName = QMetaType::typeName(var.userType());
+ − 2761
if (varTypeName.endsWith('*'))
+ − 2762
*reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data());
+ − 2763
else
+ − 2764
*reinterpret_cast<void* *>(ptr) = var.data();
+ − 2765
return true;
+ − 2766
}
+ − 2767
proto = proto.prototype();
+ − 2768
}
+ − 2769
}
+ − 2770
} else if (value.isNull() && name.endsWith('*')) {
+ − 2771
*reinterpret_cast<void* *>(ptr) = 0;
+ − 2772
return true;
+ − 2773
} else if (type == qMetaTypeId<QScriptValue>()) {
+ − 2774
if (!eng)
+ − 2775
return false;
+ − 2776
*reinterpret_cast<QScriptValue*>(ptr) = value;
+ − 2777
return true;
+ − 2778
} else if (name == "QVariant") {
+ − 2779
*reinterpret_cast<QVariant*>(ptr) = value.toVariant();
+ − 2780
return true;
+ − 2781
}
+ − 2782
+ − 2783
// lazy registration of some common list types
+ − 2784
#ifndef QT_NO_QOBJECT
+ − 2785
else if (type == qMetaTypeId<QObjectList>()) {
+ − 2786
if (!eng)
+ − 2787
return false;
+ − 2788
qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
+ − 2789
return convert(value, type, ptr, eng);
+ − 2790
}
+ − 2791
#endif
+ − 2792
else if (type == qMetaTypeId<QList<int> >()) {
+ − 2793
if (!eng)
+ − 2794
return false;
+ − 2795
qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
+ − 2796
return convert(value, type, ptr, eng);
+ − 2797
}
+ − 2798
+ − 2799
#if 0
+ − 2800
if (!name.isEmpty()) {
+ − 2801
qWarning("QScriptEngine::convert: unable to convert value to type `%s'",
+ − 2802
name.constData());
+ − 2803
}
+ − 2804
#endif
+ − 2805
return false;
+ − 2806
}
+ − 2807
+ − 2808
bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
+ − 2809
{
+ − 2810
QScriptTypeInfo *info = m_typeInfos.value(type);
+ − 2811
return info && (info->demarshal != 0);
+ − 2812
}
+ − 2813
+ − 2814
/*!
+ − 2815
\internal
+ − 2816
*/
+ − 2817
bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr)
+ − 2818
{
+ − 2819
Q_D(QScriptEngine);
+ − 2820
return QScriptEnginePrivate::convert(value, type, ptr, d);
+ − 2821
}
+ − 2822
+ − 2823
/*!
+ − 2824
\internal
+ − 2825
*/
+ − 2826
bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
+ − 2827
{
+ − 2828
return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0);
+ − 2829
}
+ − 2830
+ − 2831
/*!
+ − 2832
\internal
+ − 2833
*/
+ − 2834
void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
+ − 2835
DemarshalFunction df,
+ − 2836
const QScriptValue &prototype)
+ − 2837
{
+ − 2838
Q_D(QScriptEngine);
+ − 2839
QScriptTypeInfo *info = d->m_typeInfos.value(type);
+ − 2840
if (!info) {
+ − 2841
info = new QScriptTypeInfo();
+ − 2842
d->m_typeInfos.insert(type, info);
+ − 2843
}
+ − 2844
info->marshal = mf;
+ − 2845
info->demarshal = df;
+ − 2846
info->prototype = d->scriptValueToJSCValue(prototype);
+ − 2847
}
+ − 2848
+ − 2849
/*!
+ − 2850
\since 4.5
+ − 2851
+ − 2852
Installs translator functions on the given \a object, or on the Global
+ − 2853
Object if no object is specified.
+ − 2854
+ − 2855
The relation between Qt Script translator functions and C++ translator
+ − 2856
functions is described in the following table:
+ − 2857
+ − 2858
\table
+ − 2859
\header \o Script Function \o Corresponding C++ Function
+ − 2860
\row \o qsTr() \o QObject::tr()
+ − 2861
\row \o QT_TR_NOOP() \o QT_TR_NOOP()
+ − 2862
\row \o qsTranslate() \o QCoreApplication::translate()
+ − 2863
\row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
+ − 2864
\endtable
+ − 2865
+ − 2866
\sa {Internationalization with Qt}
+ − 2867
*/
+ − 2868
void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
+ − 2869
{
+ − 2870
Q_D(QScriptEngine);
+ − 2871
JSC::ExecState* exec = d->currentFrame;
+ − 2872
JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
+ − 2873
JSC::JSGlobalObject *glob = d->originalGlobalObject();
+ − 2874
if (!jscObject || !jscObject.isObject())
+ − 2875
jscObject = glob;
+ − 2876
// unsigned attribs = JSC::DontEnum;
+ − 2877
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
+ − 2878
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
+ − 2879
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
+ − 2880
JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
+ − 2881
+ − 2882
glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
+ − 2883
}
+ − 2884
+ − 2885
/*!
+ − 2886
Imports the given \a extension into this QScriptEngine. Returns
+ − 2887
undefinedValue() if the extension was successfully imported. You
+ − 2888
can call hasUncaughtException() to check if an error occurred; in
+ − 2889
that case, the return value is the value that was thrown by the
+ − 2890
exception (usually an \c{Error} object).
+ − 2891
+ − 2892
QScriptEngine ensures that a particular extension is only imported
+ − 2893
once; subsequent calls to importExtension() with the same extension
+ − 2894
name will do nothing and return undefinedValue().
+ − 2895
+ − 2896
\sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions}
+ − 2897
*/
+ − 2898
QScriptValue QScriptEngine::importExtension(const QString &extension)
+ − 2899
{
+ − 2900
#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ − 2901
Q_UNUSED(extension);
+ − 2902
#else
+ − 2903
Q_D(QScriptEngine);
+ − 2904
if (d->importedExtensions.contains(extension))
+ − 2905
return undefinedValue(); // already imported
+ − 2906
+ − 2907
QScriptContext *context = currentContext();
+ − 2908
QCoreApplication *app = QCoreApplication::instance();
+ − 2909
if (!app)
+ − 2910
return context->throwError(QLatin1String("No application object"));
+ − 2911
+ − 2912
QObjectList staticPlugins = QPluginLoader::staticInstances();
+ − 2913
QStringList libraryPaths = app->libraryPaths();
+ − 2914
QString dot = QLatin1String(".");
+ − 2915
QStringList pathComponents = extension.split(dot);
+ − 2916
QString initDotJs = QLatin1String("__init__.js");
+ − 2917
+ − 2918
QString ext;
+ − 2919
for (int i = 0; i < pathComponents.count(); ++i) {
+ − 2920
if (!ext.isEmpty())
+ − 2921
ext.append(dot);
+ − 2922
ext.append(pathComponents.at(i));
+ − 2923
if (d->importedExtensions.contains(ext))
+ − 2924
continue; // already imported
+ − 2925
+ − 2926
if (d->extensionsBeingImported.contains(ext)) {
+ − 2927
return context->throwError(QString::fromLatin1("recursive import of %0")
+ − 2928
.arg(extension));
+ − 2929
}
+ − 2930
d->extensionsBeingImported.insert(ext);
+ − 2931
+ − 2932
QScriptExtensionInterface *iface = 0;
+ − 2933
QString initjsContents;
+ − 2934
QString initjsFileName;
+ − 2935
+ − 2936
// look for the extension in static plugins
+ − 2937
for (int j = 0; j < staticPlugins.size(); ++j) {
+ − 2938
iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j));
+ − 2939
if (!iface)
+ − 2940
continue;
+ − 2941
if (iface->keys().contains(ext))
+ − 2942
break; // use this one
+ − 2943
else
+ − 2944
iface = 0; // keep looking
+ − 2945
}
+ − 2946
+ − 2947
{
+ − 2948
// look for __init__.js resource
+ − 2949
QString path = QString::fromLatin1(":/qtscriptextension");
+ − 2950
for (int j = 0; j <= i; ++j) {
+ − 2951
path.append(QLatin1Char('/'));
+ − 2952
path.append(pathComponents.at(j));
+ − 2953
}
+ − 2954
path.append(QLatin1Char('/'));
+ − 2955
path.append(initDotJs);
+ − 2956
QFile file(path);
+ − 2957
if (file.open(QIODevice::ReadOnly)) {
+ − 2958
QTextStream ts(&file);
+ − 2959
initjsContents = ts.readAll();
+ − 2960
initjsFileName = path;
+ − 2961
file.close();
+ − 2962
}
+ − 2963
}
+ − 2964
+ − 2965
if (!iface && initjsContents.isEmpty()) {
+ − 2966
// look for the extension in library paths
+ − 2967
for (int j = 0; j < libraryPaths.count(); ++j) {
+ − 2968
QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script");
+ − 2969
QDir dir(libPath);
+ − 2970
if (!dir.exists(dot))
+ − 2971
continue;
+ − 2972
+ − 2973
// look for C++ plugin
+ − 2974
QFileInfoList files = dir.entryInfoList(QDir::Files);
+ − 2975
for (int k = 0; k < files.count(); ++k) {
+ − 2976
QFileInfo entry = files.at(k);
+ − 2977
QString filePath = entry.canonicalFilePath();
+ − 2978
QPluginLoader loader(filePath);
+ − 2979
iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
+ − 2980
if (iface) {
+ − 2981
if (iface->keys().contains(ext))
+ − 2982
break; // use this one
+ − 2983
else
+ − 2984
iface = 0; // keep looking
+ − 2985
}
+ − 2986
}
+ − 2987
+ − 2988
// look for __init__.js in the corresponding dir
+ − 2989
QDir dirdir(libPath);
+ − 2990
bool dirExists = dirdir.exists();
+ − 2991
for (int k = 0; dirExists && (k <= i); ++k)
+ − 2992
dirExists = dirdir.cd(pathComponents.at(k));
+ − 2993
if (dirExists && dirdir.exists(initDotJs)) {
+ − 2994
QFile file(dirdir.canonicalPath()
+ − 2995
+ QDir::separator() + initDotJs);
+ − 2996
if (file.open(QIODevice::ReadOnly)) {
+ − 2997
QTextStream ts(&file);
+ − 2998
initjsContents = ts.readAll();
+ − 2999
initjsFileName = file.fileName();
+ − 3000
file.close();
+ − 3001
}
+ − 3002
}
+ − 3003
+ − 3004
if (iface || !initjsContents.isEmpty())
+ − 3005
break;
+ − 3006
}
+ − 3007
}
+ − 3008
+ − 3009
if (!iface && initjsContents.isEmpty()) {
+ − 3010
d->extensionsBeingImported.remove(ext);
+ − 3011
return context->throwError(
+ − 3012
QString::fromLatin1("Unable to import %0: no such extension")
+ − 3013
.arg(extension));
+ − 3014
}
+ − 3015
+ − 3016
// initialize the extension in a new context
+ − 3017
QScriptContext *ctx = pushContext();
+ − 3018
ctx->setThisObject(globalObject());
+ − 3019
ctx->activationObject().setProperty(QLatin1String("__extension__"), ext,
+ − 3020
QScriptValue::ReadOnly | QScriptValue::Undeletable);
+ − 3021
ctx->activationObject().setProperty(QLatin1String("__setupPackage__"),
+ − 3022
newFunction(QScript::__setupPackage__));
+ − 3023
ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue));
+ − 3024
+ − 3025
// the script is evaluated first
+ − 3026
if (!initjsContents.isEmpty()) {
+ − 3027
QScriptValue ret = evaluate(initjsContents, initjsFileName);
+ − 3028
if (hasUncaughtException()) {
+ − 3029
popContext();
+ − 3030
d->extensionsBeingImported.remove(ext);
+ − 3031
return ret;
+ − 3032
}
+ − 3033
}
+ − 3034
+ − 3035
// next, the C++ plugin is called
+ − 3036
if (iface) {
+ − 3037
iface->initialize(ext, this);
+ − 3038
if (hasUncaughtException()) {
+ − 3039
QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
+ − 3040
popContext();
+ − 3041
d->extensionsBeingImported.remove(ext);
+ − 3042
return ret;
+ − 3043
}
+ − 3044
}
+ − 3045
+ − 3046
// if the __postInit__ function has been set, we call it
+ − 3047
QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__"));
+ − 3048
if (postInit.isFunction()) {
+ − 3049
postInit.call(globalObject());
+ − 3050
if (hasUncaughtException()) {
+ − 3051
QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
+ − 3052
popContext();
+ − 3053
d->extensionsBeingImported.remove(ext);
+ − 3054
return ret;
+ − 3055
}
+ − 3056
}
+ − 3057
+ − 3058
popContext();
+ − 3059
+ − 3060
d->importedExtensions.insert(ext);
+ − 3061
d->extensionsBeingImported.remove(ext);
+ − 3062
} // for (i)
+ − 3063
#endif // QT_NO_QOBJECT
+ − 3064
return undefinedValue();
+ − 3065
}
+ − 3066
+ − 3067
/*!
+ − 3068
\since 4.4
+ − 3069
+ − 3070
Returns a list naming the available extensions that can be
+ − 3071
imported using the importExtension() function. This list includes
+ − 3072
extensions that have been imported.
+ − 3073
+ − 3074
\sa importExtension(), importedExtensions()
+ − 3075
*/
+ − 3076
QStringList QScriptEngine::availableExtensions() const
+ − 3077
{
+ − 3078
#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ − 3079
return QStringList();
+ − 3080
#else
+ − 3081
QCoreApplication *app = QCoreApplication::instance();
+ − 3082
if (!app)
+ − 3083
return QStringList();
+ − 3084
+ − 3085
QSet<QString> result;
+ − 3086
+ − 3087
QObjectList staticPlugins = QPluginLoader::staticInstances();
+ − 3088
for (int i = 0; i < staticPlugins.size(); ++i) {
+ − 3089
QScriptExtensionInterface *iface;
+ − 3090
iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i));
+ − 3091
if (iface) {
+ − 3092
QStringList keys = iface->keys();
+ − 3093
for (int j = 0; j < keys.count(); ++j)
+ − 3094
result << keys.at(j);
+ − 3095
}
+ − 3096
}
+ − 3097
+ − 3098
QStringList libraryPaths = app->libraryPaths();
+ − 3099
for (int i = 0; i < libraryPaths.count(); ++i) {
+ − 3100
QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script");
+ − 3101
QDir dir(libPath);
+ − 3102
if (!dir.exists())
+ − 3103
continue;
+ − 3104
+ − 3105
// look for C++ plugins
+ − 3106
QFileInfoList files = dir.entryInfoList(QDir::Files);
+ − 3107
for (int j = 0; j < files.count(); ++j) {
+ − 3108
QFileInfo entry = files.at(j);
+ − 3109
QString filePath = entry.canonicalFilePath();
+ − 3110
QPluginLoader loader(filePath);
+ − 3111
QScriptExtensionInterface *iface;
+ − 3112
iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
+ − 3113
if (iface) {
+ − 3114
QStringList keys = iface->keys();
+ − 3115
for (int k = 0; k < keys.count(); ++k)
+ − 3116
result << keys.at(k);
+ − 3117
}
+ − 3118
}
+ − 3119
+ − 3120
// look for scripts
+ − 3121
QString initDotJs = QLatin1String("__init__.js");
+ − 3122
QList<QFileInfo> stack;
+ − 3123
stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ − 3124
while (!stack.isEmpty()) {
+ − 3125
QFileInfo entry = stack.takeLast();
+ − 3126
QDir dd(entry.canonicalFilePath());
+ − 3127
if (dd.exists(initDotJs)) {
+ − 3128
QString rpath = dir.relativeFilePath(dd.canonicalPath());
+ − 3129
QStringList components = rpath.split(QLatin1Char('/'));
+ − 3130
result << components.join(QLatin1String("."));
+ − 3131
stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ − 3132
}
+ − 3133
}
+ − 3134
}
+ − 3135
+ − 3136
QStringList lst = result.toList();
+ − 3137
qSort(lst);
+ − 3138
return lst;
+ − 3139
#endif
+ − 3140
}
+ − 3141
+ − 3142
/*!
+ − 3143
\since 4.4
+ − 3144
+ − 3145
Returns a list naming the extensions that have been imported
+ − 3146
using the importExtension() function.
+ − 3147
+ − 3148
\sa availableExtensions()
+ − 3149
*/
+ − 3150
QStringList QScriptEngine::importedExtensions() const
+ − 3151
{
+ − 3152
Q_D(const QScriptEngine);
+ − 3153
QStringList lst = d->importedExtensions.toList();
+ − 3154
qSort(lst);
+ − 3155
return lst;
+ − 3156
}
+ − 3157
+ − 3158
/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value)
+ − 3159
+ − 3160
Creates a QScriptValue with the given \a value.
+ − 3161
+ − 3162
Note that the template type \c{T} must be known to QMetaType.
+ − 3163
+ − 3164
See \l{Conversion Between QtScript and C++ Types} for a
+ − 3165
description of the built-in type conversion provided by
+ − 3166
QtScript. By default, the types that are not specially handled by
+ − 3167
QtScript are represented as QVariants (e.g. the \a value is passed
+ − 3168
to newVariant()); you can change this behavior by installing your
+ − 3169
own type conversion functions with qScriptRegisterMetaType().
+ − 3170
+ − 3171
\warning This function is not available with MSVC 6. Use
+ − 3172
qScriptValueFromValue() instead if you need to support that
+ − 3173
version of the compiler.
+ − 3174
+ − 3175
\sa fromScriptValue(), qScriptRegisterMetaType()
+ − 3176
*/
+ − 3177
+ − 3178
/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value)
+ − 3179
+ − 3180
Returns the given \a value converted to the template type \c{T}.
+ − 3181
+ − 3182
Note that \c{T} must be known to QMetaType.
+ − 3183
+ − 3184
See \l{Conversion Between QtScript and C++ Types} for a
+ − 3185
description of the built-in type conversion provided by
+ − 3186
QtScript.
+ − 3187
+ − 3188
\warning This function is not available with MSVC 6. Use
+ − 3189
qScriptValueToValue() or qscriptvalue_cast() instead if you need
+ − 3190
to support that version of the compiler.
+ − 3191
+ − 3192
\sa toScriptValue(), qScriptRegisterMetaType()
+ − 3193
*/
+ − 3194
+ − 3195
/*!
+ − 3196
\fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value)
+ − 3197
\since 4.3
+ − 3198
\relates QScriptEngine
+ − 3199
+ − 3200
Creates a QScriptValue using the given \a engine with the given \a
+ − 3201
value of template type \c{T}.
+ − 3202
+ − 3203
This function is equivalent to QScriptEngine::toScriptValue().
+ − 3204
It is provided as a work-around for MSVC 6, which doesn't support
+ − 3205
member template functions.
+ − 3206
+ − 3207
\sa qScriptValueToValue()
+ − 3208
*/
+ − 3209
+ − 3210
/*!
+ − 3211
\fn T qScriptValueToValue(const QScriptValue &value)
+ − 3212
\since 4.3
+ − 3213
\relates QScriptEngine
+ − 3214
+ − 3215
Returns the given \a value converted to the template type \c{T}.
+ − 3216
+ − 3217
This function is equivalent to QScriptEngine::fromScriptValue().
+ − 3218
It is provided as a work-around for MSVC 6, which doesn't
+ − 3219
support member template functions.
+ − 3220
+ − 3221
\sa qScriptValueFromValue()
+ − 3222
*/
+ − 3223
+ − 3224
/*!
+ − 3225
\fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container)
+ − 3226
\since 4.3
+ − 3227
\relates QScriptEngine
+ − 3228
+ − 3229
Creates an array in the form of a QScriptValue using the given \a engine
+ − 3230
with the given \a container of template type \c{Container}.
+ − 3231
+ − 3232
The \c Container type must provide a \c const_iterator class to enable the
+ − 3233
contents of the container to be copied into the array.
+ − 3234
+ − 3235
Additionally, the type of each element in the sequence should be
+ − 3236
suitable for conversion to a QScriptValue. See
+ − 3237
\l{Conversion Between QtScript and C++ Types} for more information
+ − 3238
about the restrictions on types that can be used with QScriptValue.
+ − 3239
+ − 3240
\sa qScriptValueFromValue()
+ − 3241
*/
+ − 3242
+ − 3243
/*!
+ − 3244
\fn void qScriptValueToSequence(const QScriptValue &value, Container &container)
+ − 3245
\since 4.3
+ − 3246
\relates QScriptEngine
+ − 3247
+ − 3248
Copies the elements in the sequence specified by \a value to the given
+ − 3249
\a container of template type \c{Container}.
+ − 3250
+ − 3251
The \a value used is typically an array, but any container can be copied
+ − 3252
as long as it provides a \c length property describing how many elements
+ − 3253
it contains.
+ − 3254
+ − 3255
Additionally, the type of each element in the sequence must be
+ − 3256
suitable for conversion to a C++ type from a QScriptValue. See
+ − 3257
\l{Conversion Between QtScript and C++ Types} for more information
+ − 3258
about the restrictions on types that can be used with
+ − 3259
QScriptValue.
+ − 3260
+ − 3261
\sa qscriptvalue_cast()
+ − 3262
*/
+ − 3263
+ − 3264
/*!
+ − 3265
\fn T qscriptvalue_cast(const QScriptValue &value)
+ − 3266
\since 4.3
+ − 3267
\relates QScriptValue
+ − 3268
+ − 3269
Returns the given \a value converted to the template type \c{T}.
+ − 3270
+ − 3271
\sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue()
+ − 3272
*/
+ − 3273
+ − 3274
/*! \fn int qScriptRegisterMetaType(
+ − 3275
QScriptEngine *engine,
+ − 3276
QScriptValue (*toScriptValue)(QScriptEngine *, const T &t),
+ − 3277
void (*fromScriptValue)(const QScriptValue &, T &t),
+ − 3278
const QScriptValue &prototype = QScriptValue())
+ − 3279
\relates QScriptEngine
+ − 3280
+ − 3281
Registers the type \c{T} in the given \a engine. \a toScriptValue must
+ − 3282
be a function that will convert from a value of type \c{T} to a
+ − 3283
QScriptValue, and \a fromScriptValue a function that does the
+ − 3284
opposite. \a prototype, if valid, is the prototype that's set on
+ − 3285
QScriptValues returned by \a toScriptValue.
+ − 3286
+ − 3287
Returns the internal ID used by QMetaType.
+ − 3288
+ − 3289
You only need to call this function if you want to provide custom
+ − 3290
conversion of values of type \c{T}, i.e. if the default
+ − 3291
QVariant-based representation and conversion is not
+ − 3292
appropriate. (Note that custom QObject-derived types also fall in
+ − 3293
this category; e.g. for a QObject-derived class called MyObject,
+ − 3294
you probably want to define conversion functions for MyObject*
+ − 3295
that utilize QScriptEngine::newQObject() and
+ − 3296
QScriptValue::toQObject().)
+ − 3297
+ − 3298
If you only want to define a common script interface for values of
+ − 3299
type \c{T}, and don't care how those values are represented
+ − 3300
(i.e. storing them in QVariants is fine), use
+ − 3301
\l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}()
+ − 3302
instead; this will minimize conversion costs.
+ − 3303
+ − 3304
You need to declare the custom type first with
+ − 3305
Q_DECLARE_METATYPE().
+ − 3306
+ − 3307
After a type has been registered, you can convert from a
+ − 3308
QScriptValue to that type using
+ − 3309
\l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and
+ − 3310
create a QScriptValue from a value of that type using
+ − 3311
\l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine
+ − 3312
will take care of calling the proper conversion function when
+ − 3313
calling C++ slots, and when getting or setting a C++ property;
+ − 3314
i.e. the custom type may be used seamlessly on both the C++ side
+ − 3315
and the script side.
+ − 3316
+ − 3317
The following is an example of how to use this function. We will
+ − 3318
specify custom conversion of our type \c{MyStruct}. Here's the C++
+ − 3319
type:
+ − 3320
+ − 3321
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20
+ − 3322
+ − 3323
We must declare it so that the type will be known to QMetaType:
+ − 3324
+ − 3325
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21
+ − 3326
+ − 3327
Next, the \c{MyStruct} conversion functions. We represent the
+ − 3328
\c{MyStruct} value as a script object and just copy the properties:
+ − 3329
+ − 3330
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22
+ − 3331
+ − 3332
Now we can register \c{MyStruct} with the engine:
+ − 3333
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23
+ − 3334
+ − 3335
Working with \c{MyStruct} values is now easy:
+ − 3336
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24
+ − 3337
+ − 3338
If you want to be able to construct values of your custom type
+ − 3339
from script code, you have to register a constructor function for
+ − 3340
the type. For example:
+ − 3341
+ − 3342
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25
+ − 3343
+ − 3344
\sa qScriptRegisterSequenceMetaType(), qRegisterMetaType()
+ − 3345
*/
+ − 3346
+ − 3347
/*!
+ − 3348
\macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType)
+ − 3349
\since 4.3
+ − 3350
\relates QScriptEngine
+ − 3351
+ − 3352
Declares the given \a QMetaObject. Used in combination with
+ − 3353
QScriptEngine::scriptValueFromQMetaObject() to make enums and
+ − 3354
instantiation of \a QMetaObject available to script code. The
+ − 3355
constructor generated by this macro takes a single argument of
+ − 3356
type \a ArgType; typically the argument is the parent type of the
+ − 3357
new instance, in which case \a ArgType is \c{QWidget*} or
+ − 3358
\c{QObject*}. Objects created by the constructor will have
+ − 3359
QScriptEngine::AutoOwnership ownership.
+ − 3360
*/
+ − 3361
+ − 3362
/*! \fn int qScriptRegisterSequenceMetaType(
+ − 3363
QScriptEngine *engine,
+ − 3364
const QScriptValue &prototype = QScriptValue())
+ − 3365
\relates QScriptEngine
+ − 3366
+ − 3367
Registers the sequence type \c{T} in the given \a engine. This
+ − 3368
function provides conversion functions that convert between \c{T}
+ − 3369
and Qt Script \c{Array} objects. \c{T} must provide a
+ − 3370
const_iterator class and begin(), end() and push_back()
+ − 3371
functions. If \a prototype is valid, it will be set as the
+ − 3372
prototype of \c{Array} objects due to conversion from \c{T};
+ − 3373
otherwise, the standard \c{Array} prototype will be used.
+ − 3374
+ − 3375
Returns the internal ID used by QMetaType.
+ − 3376
+ − 3377
You need to declare the container type first with
+ − 3378
Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++
+ − 3379
type, it must be declared using Q_DECLARE_METATYPE() as well.
+ − 3380
Example:
+ − 3381
+ − 3382
\snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26
+ − 3383
+ − 3384
\sa qScriptRegisterMetaType()
+ − 3385
*/
+ − 3386
+ − 3387
/*!
+ − 3388
Runs the garbage collector.
+ − 3389
+ − 3390
The garbage collector will attempt to reclaim memory by locating and
+ − 3391
disposing of objects that are no longer reachable in the script
+ − 3392
environment.
+ − 3393
+ − 3394
Normally you don't need to call this function; the garbage collector
+ − 3395
will automatically be invoked when the QScriptEngine decides that
+ − 3396
it's wise to do so (i.e. when a certain number of new objects have
+ − 3397
been created). However, you can call this function to explicitly
+ − 3398
request that garbage collection should be performed as soon as
+ − 3399
possible.
+ − 3400
*/
+ − 3401
void QScriptEngine::collectGarbage()
+ − 3402
{
+ − 3403
Q_D(QScriptEngine);
+ − 3404
d->collectGarbage();
+ − 3405
}
+ − 3406
+ − 3407
/*!
+ − 3408
+ − 3409
Sets the interval between calls to QCoreApplication::processEvents
+ − 3410
to \a interval milliseconds.
+ − 3411
+ − 3412
While the interpreter is running, all event processing is by default
+ − 3413
blocked. This means for instance that the gui will not be updated
+ − 3414
and timers will not be fired. To allow event processing during
+ − 3415
interpreter execution one can specify the processing interval to be
+ − 3416
a positive value, indicating the number of milliseconds between each
+ − 3417
time QCoreApplication::processEvents() is called.
+ − 3418
+ − 3419
The default value is -1, which disables event processing during
+ − 3420
interpreter execution.
+ − 3421
+ − 3422
You can use QCoreApplication::postEvent() to post an event that
+ − 3423
performs custom processing at the next interval. For example, you
+ − 3424
could keep track of the total running time of the script and call
+ − 3425
abortEvaluation() when you detect that the script has been running
+ − 3426
for a long time without completing.
+ − 3427
+ − 3428
\sa processEventsInterval()
+ − 3429
*/
+ − 3430
void QScriptEngine::setProcessEventsInterval(int interval)
+ − 3431
{
+ − 3432
Q_D(QScriptEngine);
+ − 3433
d->processEventsInterval = interval;
+ − 3434
+ − 3435
if (interval > 0)
+ − 3436
d->globalData->timeoutChecker->setCheckInterval(interval);
+ − 3437
+ − 3438
d->timeoutChecker()->setShouldProcessEvents(interval > 0);
+ − 3439
}
+ − 3440
+ − 3441
/*!
+ − 3442
+ − 3443
Returns the interval in milliseconds between calls to
+ − 3444
QCoreApplication::processEvents() while the interpreter is running.
+ − 3445
+ − 3446
\sa setProcessEventsInterval()
+ − 3447
*/
+ − 3448
int QScriptEngine::processEventsInterval() const
+ − 3449
{
+ − 3450
Q_D(const QScriptEngine);
+ − 3451
return d->processEventsInterval;
+ − 3452
}
+ − 3453
+ − 3454
/*!
+ − 3455
\since 4.4
+ − 3456
+ − 3457
Returns true if this engine is currently evaluating a script,
+ − 3458
otherwise returns false.
+ − 3459
+ − 3460
\sa evaluate(), abortEvaluation()
+ − 3461
*/
+ − 3462
bool QScriptEngine::isEvaluating() const
+ − 3463
{
+ − 3464
Q_D(const QScriptEngine);
+ − 3465
return (d->currentFrame != d->globalExec()) || d->inEval;
+ − 3466
}
+ − 3467
+ − 3468
/*!
+ − 3469
\since 4.4
+ − 3470
+ − 3471
Aborts any script evaluation currently taking place in this engine.
+ − 3472
The given \a result is passed back as the result of the evaluation
+ − 3473
(i.e. it is returned from the call to evaluate() being aborted).
+ − 3474
+ − 3475
If the engine isn't evaluating a script (i.e. isEvaluating() returns
+ − 3476
false), this function does nothing.
+ − 3477
+ − 3478
Call this function if you need to abort a running script for some
+ − 3479
reason, e.g. when you have detected that the script has been
+ − 3480
running for several seconds without completing.
+ − 3481
+ − 3482
\sa evaluate(), isEvaluating(), setProcessEventsInterval()
+ − 3483
*/
+ − 3484
void QScriptEngine::abortEvaluation(const QScriptValue &result)
+ − 3485
{
+ − 3486
Q_D(QScriptEngine);
+ − 3487
+ − 3488
d->timeoutChecker()->setShouldAbort(true);
+ − 3489
d->abortResult = result;
+ − 3490
}
+ − 3491
+ − 3492
#ifndef QT_NO_QOBJECT
+ − 3493
+ − 3494
/*!
+ − 3495
\since 4.4
+ − 3496
\relates QScriptEngine
+ − 3497
+ − 3498
Creates a connection from the \a signal in the \a sender to the
+ − 3499
given \a function. If \a receiver is an object, it will act as the
+ − 3500
`this' object when the signal handler function is invoked. Returns
+ − 3501
true if the connection succeeds; otherwise returns false.
+ − 3502
+ − 3503
\sa qScriptDisconnect(), QScriptEngine::signalHandlerException()
+ − 3504
*/
+ − 3505
bool qScriptConnect(QObject *sender, const char *signal,
+ − 3506
const QScriptValue &receiver, const QScriptValue &function)
+ − 3507
{
+ − 3508
if (!sender || !signal)
+ − 3509
return false;
+ − 3510
if (!function.isFunction())
+ − 3511
return false;
+ − 3512
if (receiver.isObject() && (receiver.engine() != function.engine()))
+ − 3513
return false;
+ − 3514
QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
+ − 3515
JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
+ − 3516
JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
+ − 3517
return engine->scriptConnect(sender, signal, jscReceiver, jscFunction,
+ − 3518
Qt::AutoConnection);
+ − 3519
}
+ − 3520
+ − 3521
/*!
+ − 3522
\since 4.4
+ − 3523
\relates QScriptEngine
+ − 3524
+ − 3525
Disconnects the \a signal in the \a sender from the given (\a
+ − 3526
receiver, \a function) pair. Returns true if the connection is
+ − 3527
successfully broken; otherwise returns false.
+ − 3528
+ − 3529
\sa qScriptConnect()
+ − 3530
*/
+ − 3531
bool qScriptDisconnect(QObject *sender, const char *signal,
+ − 3532
const QScriptValue &receiver, const QScriptValue &function)
+ − 3533
{
+ − 3534
if (!sender || !signal)
+ − 3535
return false;
+ − 3536
if (!function.isFunction())
+ − 3537
return false;
+ − 3538
if (receiver.isObject() && (receiver.engine() != function.engine()))
+ − 3539
return false;
+ − 3540
QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
+ − 3541
JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
+ − 3542
JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
+ − 3543
return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction);
+ − 3544
}
+ − 3545
+ − 3546
/*!
+ − 3547
\since 4.4
+ − 3548
\fn void QScriptEngine::signalHandlerException(const QScriptValue &exception)
+ − 3549
+ − 3550
This signal is emitted when a script function connected to a signal causes
+ − 3551
an \a exception.
+ − 3552
+ − 3553
\sa qScriptConnect()
+ − 3554
*/
+ − 3555
+ − 3556
QT_BEGIN_INCLUDE_NAMESPACE
+ − 3557
#include "moc_qscriptengine.cpp"
+ − 3558
QT_END_INCLUDE_NAMESPACE
+ − 3559
+ − 3560
#endif // QT_NO_QOBJECT
+ − 3561
+ − 3562
/*!
+ − 3563
\since 4.4
+ − 3564
+ − 3565
Installs the given \a agent on this engine. The agent will be
+ − 3566
notified of various events pertaining to script execution. This is
+ − 3567
useful when you want to find out exactly what the engine is doing,
+ − 3568
e.g. when evaluate() is called. The agent interface is the basis of
+ − 3569
tools like debuggers and profilers.
+ − 3570
+ − 3571
The engine maintains ownership of the \a agent.
+ − 3572
+ − 3573
Calling this function will replace the existing agent, if any.
+ − 3574
+ − 3575
\sa agent()
+ − 3576
*/
+ − 3577
void QScriptEngine::setAgent(QScriptEngineAgent *agent)
+ − 3578
{
+ − 3579
Q_D(QScriptEngine);
+ − 3580
if (agent && (agent->engine() != this)) {
+ − 3581
qWarning("QScriptEngine::setAgent(): "
+ − 3582
"cannot set agent belonging to different engine");
+ − 3583
return;
+ − 3584
}
+ − 3585
if (d->activeAgent)
+ − 3586
QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
+ − 3587
d->activeAgent = agent;
+ − 3588
if (agent) {
+ − 3589
QScriptEngineAgentPrivate::get(agent)->attach();
+ − 3590
}
+ − 3591
}
+ − 3592
+ − 3593
/*!
+ − 3594
\since 4.4
+ − 3595
+ − 3596
Returns the agent currently installed on this engine, or 0 if no
+ − 3597
agent is installed.
+ − 3598
+ − 3599
\sa setAgent()
+ − 3600
*/
+ − 3601
QScriptEngineAgent *QScriptEngine::agent() const
+ − 3602
{
+ − 3603
Q_D(const QScriptEngine);
+ − 3604
return d->activeAgent;
+ − 3605
}
+ − 3606
+ − 3607
/*!
+ − 3608
\since 4.4
+ − 3609
+ − 3610
Returns a handle that represents the given string, \a str.
+ − 3611
+ − 3612
QScriptString can be used to quickly look up properties, and
+ − 3613
compare property names, of script objects.
+ − 3614
+ − 3615
\sa QScriptValue::property()
+ − 3616
*/
+ − 3617
QScriptString QScriptEngine::toStringHandle(const QString &str)
+ − 3618
{
+ − 3619
Q_D(QScriptEngine);
+ − 3620
QScriptString result;
+ − 3621
QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated);
+ − 3622
QScriptStringPrivate::init(result, p);
+ − 3623
d->registerScriptString(p);
+ − 3624
return result;
+ − 3625
}
+ − 3626
+ − 3627
/*!
+ − 3628
\since 4.5
+ − 3629
+ − 3630
Converts the given \a value to an object, if such a conversion is
+ − 3631
possible; otherwise returns an invalid QScriptValue. The conversion
+ − 3632
is performed according to the following table:
+ − 3633
+ − 3634
\table
+ − 3635
\header \o Input Type \o Result
+ − 3636
\row \o Undefined \o An invalid QScriptValue.
+ − 3637
\row \o Null \o An invalid QScriptValue.
+ − 3638
\row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
+ − 3639
\row \o Number \o A new Number object whose internal value is set to the value of the number.
+ − 3640
\row \o String \o A new String object whose internal value is set to the value of the string.
+ − 3641
\row \o Object \o The result is the object itself (no conversion).
+ − 3642
\endtable
+ − 3643
+ − 3644
\sa newObject()
+ − 3645
*/
+ − 3646
QScriptValue QScriptEngine::toObject(const QScriptValue &value)
+ − 3647
{
+ − 3648
Q_D(QScriptEngine);
+ − 3649
JSC::JSValue jscValue = d->scriptValueToJSCValue(value);
+ − 3650
if (!jscValue || jscValue.isUndefined() || jscValue.isNull())
+ − 3651
return QScriptValue();
+ − 3652
JSC::ExecState* exec = d->currentFrame;
+ − 3653
JSC::JSValue result = jscValue.toObject(exec);
+ − 3654
return d->scriptValueFromJSCValue(result);
+ − 3655
}
+ − 3656
+ − 3657
/*!
+ − 3658
\internal
+ − 3659
+ − 3660
Returns the object with the given \a id, or an invalid
+ − 3661
QScriptValue if there is no object with that id.
+ − 3662
+ − 3663
\sa QScriptValue::objectId()
+ − 3664
*/
+ − 3665
QScriptValue QScriptEngine::objectById(qint64 id) const
+ − 3666
{
+ − 3667
Q_D(const QScriptEngine);
+ − 3668
// Assumes that the cell was not been garbage collected
+ − 3669
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
+ − 3670
}
+ − 3671
+ − 3672
/*!
+ − 3673
\since 4.5
+ − 3674
\class QScriptSyntaxCheckResult
+ − 3675
+ − 3676
\brief The QScriptSyntaxCheckResult class provides the result of a script syntax check.
+ − 3677
+ − 3678
\ingroup script
+ − 3679
\mainclass
+ − 3680
+ − 3681
QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to
+ − 3682
provide information about the syntactical (in)correctness of a script.
+ − 3683
*/
+ − 3684
+ − 3685
/*!
+ − 3686
\enum QScriptSyntaxCheckResult::State
+ − 3687
+ − 3688
This enum specifies the state of a syntax check.
+ − 3689
+ − 3690
\value Error The program contains a syntax error.
+ − 3691
\value Intermediate The program is incomplete.
+ − 3692
\value Valid The program is a syntactically correct Qt Script program.
+ − 3693
*/
+ − 3694
+ − 3695
/*!
+ − 3696
Constructs a new QScriptSyntaxCheckResult from the \a other result.
+ − 3697
*/
+ − 3698
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other)
+ − 3699
: d_ptr(other.d_ptr)
+ − 3700
{
+ − 3701
}
+ − 3702
+ − 3703
/*!
+ − 3704
\internal
+ − 3705
*/
+ − 3706
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d)
+ − 3707
: d_ptr(d)
+ − 3708
{
+ − 3709
}
+ − 3710
+ − 3711
/*!
+ − 3712
\internal
+ − 3713
*/
+ − 3714
QScriptSyntaxCheckResult::QScriptSyntaxCheckResult()
+ − 3715
: d_ptr(0)
+ − 3716
{
+ − 3717
}
+ − 3718
+ − 3719
/*!
+ − 3720
Destroys this QScriptSyntaxCheckResult.
+ − 3721
*/
+ − 3722
QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult()
+ − 3723
{
+ − 3724
}
+ − 3725
+ − 3726
/*!
+ − 3727
Returns the state of this QScriptSyntaxCheckResult.
+ − 3728
*/
+ − 3729
QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const
+ − 3730
{
+ − 3731
Q_D(const QScriptSyntaxCheckResult);
+ − 3732
if (!d)
+ − 3733
return Valid;
+ − 3734
return d->state;
+ − 3735
}
+ − 3736
+ − 3737
/*!
+ − 3738
Returns the error line number of this QScriptSyntaxCheckResult, or -1 if
+ − 3739
there is no error.
+ − 3740
+ − 3741
\sa state(), errorMessage()
+ − 3742
*/
+ − 3743
int QScriptSyntaxCheckResult::errorLineNumber() const
+ − 3744
{
+ − 3745
Q_D(const QScriptSyntaxCheckResult);
+ − 3746
if (!d)
+ − 3747
return -1;
+ − 3748
return d->errorLineNumber;
+ − 3749
}
+ − 3750
+ − 3751
/*!
+ − 3752
Returns the error column number of this QScriptSyntaxCheckResult, or -1 if
+ − 3753
there is no error.
+ − 3754
+ − 3755
\sa state(), errorLineNumber()
+ − 3756
*/
+ − 3757
int QScriptSyntaxCheckResult::errorColumnNumber() const
+ − 3758
{
+ − 3759
Q_D(const QScriptSyntaxCheckResult);
+ − 3760
if (!d)
+ − 3761
return -1;
+ − 3762
return d->errorColumnNumber;
+ − 3763
}
+ − 3764
+ − 3765
/*!
+ − 3766
Returns the error message of this QScriptSyntaxCheckResult, or an empty
+ − 3767
string if there is no error.
+ − 3768
+ − 3769
\sa state(), errorLineNumber()
+ − 3770
*/
+ − 3771
QString QScriptSyntaxCheckResult::errorMessage() const
+ − 3772
{
+ − 3773
Q_D(const QScriptSyntaxCheckResult);
+ − 3774
if (!d)
+ − 3775
return QString();
+ − 3776
return d->errorMessage;
+ − 3777
}
+ − 3778
+ − 3779
/*!
+ − 3780
Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a
+ − 3781
reference to this QScriptSyntaxCheckResult.
+ − 3782
*/
+ − 3783
QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other)
+ − 3784
{
+ − 3785
d_ptr = other.d_ptr;
+ − 3786
return *this;
+ − 3787
}
+ − 3788
+ − 3789
#ifdef QT_BUILD_INTERNAL
+ − 3790
Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()
+ − 3791
{
+ − 3792
#if ENABLE(JIT)
+ − 3793
return true;
+ − 3794
#else
+ − 3795
return false;
+ − 3796
#endif
+ − 3797
}
+ − 3798
#endif
+ − 3799
+ − 3800
QT_END_NAMESPACE