~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/script/api/qscriptengine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

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