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