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