summaryrefslogtreecommitdiff
path: root/src/script/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/api')
-rw-r--r--src/script/api/api.pri35
-rw-r--r--src/script/api/qscriptable.cpp164
-rw-r--r--src/script/api/qscriptable.h70
-rw-r--r--src/script/api/qscriptable_p.h61
-rw-r--r--src/script/api/qscriptclass.cpp379
-rw-r--r--src/script/api/qscriptclass.h100
-rw-r--r--src/script/api/qscriptclasspropertyiterator.cpp204
-rw-r--r--src/script/api/qscriptclasspropertyiterator.h75
-rw-r--r--src/script/api/qscriptcontext.cpp784
-rw-r--r--src/script/api/qscriptcontext.h104
-rw-r--r--src/script/api/qscriptcontext_p.h58
-rw-r--r--src/script/api/qscriptcontextinfo.cpp556
-rw-r--r--src/script/api/qscriptcontextinfo.h106
-rw-r--r--src/script/api/qscriptengine.cpp4456
-rw-r--r--src/script/api/qscriptengine.h451
-rw-r--r--src/script/api/qscriptengine_p.h1115
-rw-r--r--src/script/api/qscriptengineagent.cpp510
-rw-r--r--src/script/api/qscriptengineagent.h91
-rw-r--r--src/script/api/qscriptengineagent_p.h125
-rw-r--r--src/script/api/qscriptextensioninterface.h52
-rw-r--r--src/script/api/qscriptextensionplugin.cpp125
-rw-r--r--src/script/api/qscriptextensionplugin.h58
-rw-r--r--src/script/api/qscriptprogram.cpp216
-rw-r--r--src/script/api/qscriptprogram.h68
-rw-r--r--src/script/api/qscriptprogram_p.h80
-rw-r--r--src/script/api/qscriptstring.cpp214
-rw-r--r--src/script/api/qscriptstring.h69
-rw-r--r--src/script/api/qscriptstring_p.h108
-rw-r--r--src/script/api/qscriptvalue.cpp2136
-rw-r--r--src/script/api/qscriptvalue.h223
-rw-r--r--src/script/api/qscriptvalue_p.h145
-rw-r--r--src/script/api/qscriptvalueiterator.cpp362
-rw-r--r--src/script/api/qscriptvalueiterator.h79
33 files changed, 13379 insertions, 0 deletions
diff --git a/src/script/api/api.pri b/src/script/api/api.pri
new file mode 100644
index 0000000..aebadd5
--- /dev/null
+++ b/src/script/api/api.pri
@@ -0,0 +1,35 @@
+SOURCES += \
+ $$PWD/qscriptclass.cpp \
+ $$PWD/qscriptclasspropertyiterator.cpp \
+ $$PWD/qscriptcontext.cpp \
+ $$PWD/qscriptcontextinfo.cpp \
+ $$PWD/qscriptengine.cpp \
+ $$PWD/qscriptengineagent.cpp \
+ $$PWD/qscriptextensionplugin.cpp \
+ $$PWD/qscriptprogram.cpp \
+ $$PWD/qscriptstring.cpp \
+ $$PWD/qscriptvalue.cpp \
+ $$PWD/qscriptvalueiterator.cpp \
+ $$PWD/qscriptable.cpp
+
+HEADERS += \
+ $$PWD/qscriptclass.h \
+ $$PWD/qscriptclasspropertyiterator.h \
+ $$PWD/qscriptcontext.h \
+ $$PWD/qscriptcontext_p.h \
+ $$PWD/qscriptcontextinfo.h \
+ $$PWD/qscriptengine.h \
+ $$PWD/qscriptengine_p.h \
+ $$PWD/qscriptengineagent.h \
+ $$PWD/qscriptengineagent_p.h \
+ $$PWD/qscriptextensioninterface.h \
+ $$PWD/qscriptextensionplugin.h \
+ $$PWD/qscriptprogram.h \
+ $$PWD/qscriptprogram_p.h \
+ $$PWD/qscriptstring.h \
+ $$PWD/qscriptstring_p.h \
+ $$PWD/qscriptvalue.h \
+ $$PWD/qscriptvalue_p.h \
+ $$PWD/qscriptvalueiterator.h \
+ $$PWD/qscriptable.h \
+ $$PWD/qscriptable_p.h
diff --git a/src/script/api/qscriptable.cpp b/src/script/api/qscriptable.cpp
new file mode 100644
index 0000000..1580cfa
--- /dev/null
+++ b/src/script/api/qscriptable.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptable.h"
+#include "qscriptable_p.h"
+#include "qscriptengine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.3
+ \class QScriptable
+
+ \brief The QScriptable class provides access to the Qt Script environment from Qt C++ member functions.
+
+ \ingroup script
+
+
+ With QScriptEngine::newQObject(), you can expose the signals and
+ slots and properties of any QObject (or subclass) to script
+ code. QScriptable augments this functionality by giving your C++
+ members access to the Qt Script environment they are invoked in;
+ conceptually, it is similar to QObject::sender().
+
+ By subclassing QScriptable, you get the following functions in your
+ class: thisObject(), argumentCount(), argument(), context() and
+ engine(). With these functions, you have full access to the Qt
+ Script environment from the slots and property access functions of
+ your class, when they are invoked from script code.
+
+ For example, you can throw a Qt Script exception from a slot;
+ manipulate the `this' object associated with the function call;
+ inspect the arguments stored in the QScriptContext to know the
+ "real" arguments passed to the function from script code; and call
+ script functions from your slot.
+
+ A typical use case of QScriptable is to implement prototype objects
+ for custom C++ types. You define the scriptable interface of your
+ custom type in a QScriptable subclass using properties and slots;
+ then you wrap an instance of your class using
+ QScriptEngine::newQObject(), and finally pass the result to
+ QScriptEngine::setDefaultPrototype(). See the \l{Default Prototypes Example}
+ to see how this can be done.
+
+ The following is what subclassing QScriptable typically looks
+ like:
+
+ \snippet doc/src/snippets/code/src_script_qscriptable.cpp 0
+
+ The only difference from regular QObject subclassing is that you
+ also inherit from QScriptable.
+
+ In the implementation of your slots, you can then use the functions
+ inherited from QScriptable:
+
+ \snippet doc/src/snippets/code/src_script_qscriptable.cpp 1
+
+ \sa {Default Prototypes Example}, QScriptEngine::newFunction()
+*/
+
+/*!
+ \internal
+*/
+QScriptable::QScriptable()
+ : d_ptr(new QScriptablePrivate())
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+*/
+QScriptable::~QScriptable()
+{
+}
+
+/*!
+ Returns a pointer to the QScriptEngine associated with the current
+ Qt function call, or 0 if the Qt function was not invoked from
+ script code.
+*/
+QScriptEngine *QScriptable::engine() const
+{
+ Q_D(const QScriptable);
+ return d->engine;
+}
+
+/*!
+ Returns a pointer to the QScriptContext associated with the current
+ Qt function call, or 0 if the Qt function was not invoked from
+ script code.
+*/
+QScriptContext *QScriptable::context() const
+{
+ if (QScriptEngine *e = engine())
+ return e->currentContext();
+
+ return 0;
+}
+
+/*!
+ Returns the `this' object associated with the current Qt function
+ call, or an invalid QScriptValue if the Qt function was not invoked
+ from script code.
+*/
+
+QScriptValue QScriptable::thisObject() const
+{
+ if (QScriptContext *c = context())
+ return c->thisObject();
+
+ return QScriptValue();
+}
+
+/*!
+ Returns the number of arguments passed to the function in this
+ invocation, or -1 if the Qt function was not invoked from script
+ code.
+
+ \sa argument()
+*/
+int QScriptable::argumentCount() const
+{
+ if (QScriptContext *c = context())
+ return c->argumentCount();
+
+ return -1;
+}
+
+/*!
+ Returns the function argument at the given \a index, or an invalid
+ QScriptValue if the Qt function was not invoked from script code.
+
+ \sa argumentCount()
+*/
+QScriptValue QScriptable::argument(int index) const
+{
+ if (QScriptContext *c = context())
+ return c->argument(index);
+
+ return QScriptValue();
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptable.h b/src/script/api/qscriptable.h
new file mode 100644
index 0000000..0460407
--- /dev/null
+++ b/src/script/api/qscriptable.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTABLE_H
+#define QSCRIPTABLE_H
+
+#include <QtCore/qobjectdefs.h>
+
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+#ifndef QT_NO_QOBJECT
+
+class QScriptEngine;
+class QScriptContext;
+class QScriptValue;
+
+class QScriptablePrivate;
+
+class Q_SCRIPT_EXPORT QScriptable
+{
+public:
+ QScriptable();
+ ~QScriptable();
+
+ QScriptEngine *engine() const;
+ QScriptContext *context() const;
+ QScriptValue thisObject() const;
+ int argumentCount() const;
+ QScriptValue argument(int index) const;
+
+private:
+ QScopedPointer<QScriptablePrivate> d_ptr;
+
+ Q_DISABLE_COPY(QScriptable)
+ Q_DECLARE_PRIVATE(QScriptable)
+};
+
+#endif // QT_NO_QOBJECT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTABLE_H
diff --git a/src/script/api/qscriptable_p.h b/src/script/api/qscriptable_p.h
new file mode 100644
index 0000000..6c3665c
--- /dev/null
+++ b/src/script/api/qscriptable_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTABLE_P_H
+#define QSCRIPTABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_NAMESPACE
+
+class QScriptable;
+class QScriptablePrivate
+{
+ Q_DECLARE_PUBLIC(QScriptable)
+public:
+ inline QScriptablePrivate()
+ : engine(0)
+ { }
+
+ static inline QScriptablePrivate *get(QScriptable *q)
+ { return q->d_func(); }
+
+ QScriptEngine *engine;
+
+ QScriptable *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptclass.cpp b/src/script/api/qscriptclass.cpp
new file mode 100644
index 0000000..3674d4b
--- /dev/null
+++ b/src/script/api/qscriptclass.cpp
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptclass.h"
+#include "qscriptstring.h"
+
+/*!
+ \since 4.4
+ \class QScriptClass
+
+ \brief The QScriptClass class provides an interface for defining custom behavior of (a class of) Qt Script objects.
+
+ \ingroup script
+ \mainclass
+
+ The QScriptClass class defines an interface for handling various
+ aspects of interaction with the Qt Script objects associated with
+ the class. Such objects are created by calling
+ QScriptEngine::newObject(), passing a pointer to the QScriptClass as
+ argument.
+
+ By subclassing QScriptClass, you can define precisely how access to
+ properties of the objects that use your class is handled. This
+ enables a fully dynamic handling of properties, e.g. it's more
+ powerful than QScriptEngine::newQObject(). For example, you can use
+ QScriptClass to implement array-type objects (i.e. objects that
+ handle the \c{length} property, and properties whose names are valid
+ array indexes, in a special way), or to implement a "live"
+ (runtime-defined) proxy to an underlying object.
+
+ If you just need to handle access to a set of properties that are
+ known at the time an object is created (i.e. "semi-statically"), you
+ might consider using QScriptValue::setProperty() to define
+ getter/setter functions for the relevant properties, rather than
+ subclassing QScriptClass.
+
+ Reimplement queryProperty() to specify which properties are handled
+ in a custom way by your script class (i.e. should be
+ \bold{delegated} to the QScriptClass), and which properties should
+ be handled just like normal Qt Script object properties.
+
+ Reimplement property() and setProperty() to perform the actual
+ access (read or write) to the properties that your class
+ handles. Additionally, you can reimplement propertyFlags() to
+ specify custom flags for your properties.
+
+ Reimplement newIterator() to provide an iterator for objects of your
+ custom class. This is only necessary if objects of your class can
+ have custom properties that you want to be reported when an object
+ is used together with the QScriptValueIterator class, or when an
+ object is used in a for-in enumeration statement in a script.
+
+ When implementing custom classes of objects, you typically use
+ QScriptValue::setData() to store instance-specific data as part of
+ object initialization; the data won't be accessible from scripts
+ directly, but you can access it in e.g. your reimplementations of
+ property() and setProperty() (by calling QScriptValue::data()) to
+ perform custom processing.
+
+ Reimplement prototype() to provide a custom prototype object for
+ your script class.
+
+ Reimplement supportsExtension() and extension() if your custom
+ script class supports one or more of the extensions specified by the
+ Extension enum.
+
+ \sa QScriptClassPropertyIterator, QScriptEngine::newObject(), {Custom Script Class Example}
+*/
+
+/*!
+ \enum QScriptClass::Extension
+
+ This enum specifies the possible extensions to a QScriptClass.
+
+ \value Callable Instances of this class can be called as functions.
+
+ \value HasInstance Instances of this class implement [[HasInstance]].
+
+ \sa extension()
+*/
+
+/*!
+ \enum QScriptClass::QueryFlag
+
+ This enum describes flags that are used to query a QScriptClass
+ regarding how access to a property should be handled.
+
+ \value HandlesReadAccess The QScriptClass handles read access to this property.
+ \value HandlesWriteAccess The QScriptClass handles write access to this property.
+
+ \sa queryProperty()
+*/
+
+QT_BEGIN_NAMESPACE
+
+class QScriptClassPrivate
+{
+ Q_DECLARE_PUBLIC(QScriptClass)
+public:
+ QScriptClassPrivate() {}
+ virtual ~QScriptClassPrivate() {}
+
+ QScriptEngine *engine;
+
+ QScriptClass *q_ptr;
+};
+
+/*!
+ Constructs a QScriptClass object to be used in the given \a engine.
+
+ The engine does not take ownership of the QScriptClass object.
+*/
+QScriptClass::QScriptClass(QScriptEngine *engine)
+ : d_ptr(new QScriptClassPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->engine = engine;
+}
+
+/*!
+ \internal
+*/
+QScriptClass::QScriptClass(QScriptEngine *engine, QScriptClassPrivate &dd)
+ : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->engine = engine;
+}
+
+/*!
+ Destroys the QScriptClass object.
+
+ If a QScriptClass object is deleted before the associated engine(),
+ any Qt Script objects using the QScriptClass will be "demoted" to
+ normal Qt Script objects.
+*/
+QScriptClass::~QScriptClass()
+{
+}
+
+/*!
+ Returns the engine that this QScriptClass is associated with.
+*/
+QScriptEngine *QScriptClass::engine() const
+{
+ Q_D(const QScriptClass);
+ return d->engine;
+}
+
+/*!
+ Returns the object to be used as the prototype of new instances
+ of this class (created with QScriptEngine::newObject()).
+
+ The default implementation returns an invalid QScriptValue, meaning
+ that the standard Object prototype will be used. Reimplement this
+ function to provide your own custom prototype.
+
+ Typically you initialize your prototype object in the constructor of
+ your class, then return it in this function.
+
+ See the "Making Use of Prototype-Based Inheritance" section in the
+ QtScript documentation for more information on how prototypes are
+ used.
+*/
+QScriptValue QScriptClass::prototype() const
+{
+ return QScriptValue();
+}
+
+/*!
+ Returns the name of the script class.
+
+ Qt Script uses this name to generate a default string representation
+ of objects in case you do not provide a toString function.
+
+ The default implementation returns a null string.
+*/
+QString QScriptClass::name() const
+{
+ return QString();
+}
+
+/*!
+ Queries this script class for how access to the property with the
+ given \a name of the given \a object should be handled. The given \a
+ flags specify the aspects of interest. This function should return a
+ subset of \a flags to indicate which aspects of property access
+ should be further handled by the script class.
+
+ For example, if the \a flags contain HandlesReadAccess, and you
+ would like your class to handle the reading of the property (through
+ the property() function), the returned flags should include
+ HandlesReadAccess. If the returned flags do not contain
+ HandlesReadAccess, the property will be handled as a normal script
+ object property.
+
+ You can optionally use the \a id argument to store a value that will
+ subsequently be passed on to functions such as property() and
+ setProperty().
+
+ The default implementation of this function returns 0.
+
+ Note: This function is only called if the given property isn't
+ already a normal property of the object. For example, say you
+ advertise that you want to handle read access to property \c{foo},
+ but not write access; if \c{foo} is then assigned a value, it will
+ become a normal script object property, and subsequently you will no
+ longer be queried regarding read access to \c{foo}.
+
+ \sa property()
+*/
+QScriptClass::QueryFlags QScriptClass::queryProperty(
+ const QScriptValue &object, const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(flags);
+ Q_UNUSED(id);
+ return 0;
+}
+
+/*!
+ Returns the value of the property with the given \a name of the given
+ \a object.
+
+ The \a id argument is only useful if you assigned a value to it in
+ queryProperty().
+
+ The default implementation does nothing and returns an invalid QScriptValue.
+
+ \sa setProperty(), propertyFlags()
+*/
+QScriptValue QScriptClass::property(const QScriptValue &object,
+ const QScriptString &name, uint id)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(id);
+ return QScriptValue();
+}
+
+/*!
+ Returns the flags of the property with the given \a name of the given
+ \a object.
+
+ The \a id argument is only useful if you assigned a value to it in
+ queryProperty().
+
+ The default implementation returns 0.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptClass::propertyFlags(
+ const QScriptValue &object, const QScriptString &name, uint id)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(id);
+ return 0;
+}
+
+/*!
+ Sets the property with the given \a name of the given \a object to
+ the given \a value.
+
+ The \a id argument is only useful if you assigned a value to it in
+ queryProperty().
+
+ The default implementation does nothing.
+
+ An invalid \a value represents a request to remove the property.
+
+ \sa property()
+*/
+void QScriptClass::setProperty(QScriptValue &object, const QScriptString &name,
+ uint id, const QScriptValue &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(id);
+ Q_UNUSED(value);
+}
+
+/*!
+ Returns an iterator for traversing custom properties of the given \a
+ object.
+
+ The default implementation returns 0, meaning that there are no
+ custom properties to traverse.
+
+ Reimplement this function if objects of your script class can have
+ one or more custom properties (e.g. those reported to be handled by
+ queryProperty()) that you want to appear when an object's properties
+ are enumerated (e.g. by a for-in statement in a script).
+
+ Qt Script takes ownership of the new iterator object.
+
+ \sa QScriptValueIterator
+*/
+QScriptClassPropertyIterator *QScriptClass::newIterator(const QScriptValue &object)
+{
+ Q_UNUSED(object);
+ return 0;
+}
+
+/*!
+ Returns true if the QScriptClass supports the given \a extension;
+ otherwise, false is returned. By default, no extensions
+ are supported.
+
+ Reimplement this function to indicate which extensions your custom
+ class supports.
+
+ \sa extension()
+*/
+bool QScriptClass::supportsExtension(Extension extension) const
+{
+ Q_UNUSED(extension);
+ return false;
+}
+
+/*!
+ This virtual function can be reimplemented in a QScriptClass
+ subclass to provide support for extensions. The optional \a argument
+ can be provided as input to the \a extension; the result must be
+ returned in the form of a QVariant. You can call supportsExtension()
+ to check if an extension is supported by the QScriptClass. By
+ default, no extensions are supported, and this function returns an
+ invalid QVariant.
+
+ If you implement the Callable extension, Qt Script will call this
+ function when an instance of your class is called as a function
+ (e.g. from a script or using QScriptValue::call()). The \a argument
+ will contain a pointer to the QScriptContext that represents the
+ function call, and you should return a QVariant that holds the
+ result of the function call. In the following example the sum of the
+ arguments to the script function are added up and returned:
+
+ \snippet doc/src/snippets/code/src_script_qscriptclass.cpp 0
+
+ If you implement the HasInstance extension, Qt Script will call this
+ function as part of evaluating the \c{instanceof} operator, as
+ described in ECMA-262 Section 11.8.6. The \a argument is a
+ QScriptValueList containing two items: The first item is the object
+ that HasInstance is being applied to (an instance of your class),
+ and the second item can be any value. extension() should return true
+ if the value delegates behavior to the object, false otherwise.
+
+ \sa supportsExtension()
+*/
+QVariant QScriptClass::extension(Extension extension, const QVariant &argument)
+{
+ Q_UNUSED(extension);
+ Q_UNUSED(argument);
+ return QVariant();
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptclass.h b/src/script/api/qscriptclass.h
new file mode 100644
index 0000000..2155c38
--- /dev/null
+++ b/src/script/api/qscriptclass.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCLASS_H
+#define QSCRIPTCLASS_H
+
+#include <QtCore/qstring.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptString;
+class QScriptClassPropertyIterator;
+
+class QScriptClassPrivate;
+class Q_SCRIPT_EXPORT QScriptClass
+{
+public:
+ enum QueryFlag {
+ HandlesReadAccess = 0x01,
+ HandlesWriteAccess = 0x02
+ };
+ Q_DECLARE_FLAGS(QueryFlags, QueryFlag)
+
+ enum Extension {
+ Callable,
+ HasInstance
+ };
+
+ QScriptClass(QScriptEngine *engine);
+ virtual ~QScriptClass();
+
+ QScriptEngine *engine() const;
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint id);
+
+ virtual void setProperty(QScriptValue &object, const QScriptString &name,
+ uint id, const QScriptValue &value);
+
+ virtual QScriptValue::PropertyFlags propertyFlags(
+ const QScriptValue &object, const QScriptString &name, uint id);
+
+ virtual QScriptClassPropertyIterator *newIterator(const QScriptValue &object);
+
+ virtual QScriptValue prototype() const;
+
+ virtual QString name() const;
+
+ virtual bool supportsExtension(Extension extension) const;
+ virtual QVariant extension(Extension extension,
+ const QVariant &argument = QVariant());
+
+protected:
+ QScriptClass(QScriptEngine *engine, QScriptClassPrivate &dd);
+ QScopedPointer<QScriptClassPrivate> d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QScriptClass)
+ Q_DISABLE_COPY(QScriptClass)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QScriptClass::QueryFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptclasspropertyiterator.cpp b/src/script/api/qscriptclasspropertyiterator.cpp
new file mode 100644
index 0000000..ba70fff
--- /dev/null
+++ b/src/script/api/qscriptclasspropertyiterator.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptclasspropertyiterator.h"
+
+#include "qscriptstring.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.4
+ \class QScriptClassPropertyIterator
+
+ \brief The QScriptClassPropertyIterator class provides an iterator interface for custom Qt Script objects.
+
+ \ingroup script
+
+ This class is only relevant if you have subclassed QScriptClass and
+ want to provide enumeration of your custom properties (e.g. when
+ objects of your class are used with QScriptValueIterator, or with
+ the for-in statement in scripts).
+
+ The object() function returns the Qt Script object the iterator is
+ traversing.
+
+ toFront(), hasNext() and next() provide forward iteration.
+
+ toBack(), hasPrevious() and previous() provide backward iteration.
+
+ name(), id() and flags() return information about the last property
+ that was jumped over using next() or previous().
+
+ \sa QScriptClass::newIterator(), QScriptValueIterator
+*/
+
+class QScriptClassPropertyIteratorPrivate
+{
+ Q_DECLARE_PUBLIC(QScriptClassPropertyIterator)
+public:
+ QScriptClassPropertyIteratorPrivate() {}
+ virtual ~QScriptClassPropertyIteratorPrivate() {}
+
+ QScriptValue object;
+
+ QScriptClassPropertyIterator *q_ptr;
+};
+
+/*!
+ Constructs an iterator for traversing \a object.
+
+ Subclasses should ensure that the iterator is set to the front of the
+ sequence of properties (before the first property).
+*/
+QScriptClassPropertyIterator::QScriptClassPropertyIterator(const QScriptValue &object)
+ : d_ptr(new QScriptClassPropertyIteratorPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->object = object;
+}
+
+/*!
+ \internal
+*/
+QScriptClassPropertyIterator::QScriptClassPropertyIterator(const QScriptValue &object,
+ QScriptClassPropertyIteratorPrivate &dd)
+ : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->object = object;
+}
+
+/*!
+ Destroys the iterator.
+*/
+QScriptClassPropertyIterator::~QScriptClassPropertyIterator()
+{
+}
+
+/*!
+ Returns the Qt Script object this iterator is traversing.
+*/
+QScriptValue QScriptClassPropertyIterator::object() const
+{
+ Q_D(const QScriptClassPropertyIterator);
+ return d->object;
+}
+
+/*!
+ \fn bool QScriptClassPropertyIterator::hasNext() const
+
+ Returns true if there is at least one item ahead of the iterator
+ (i.e. the iterator is \e not at the back of the property sequence);
+ otherwise returns false.
+
+ \sa next(), hasPrevious()
+*/
+
+/*!
+ \fn void QScriptClassPropertyIterator::next()
+
+ Advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), previous(), name()
+*/
+
+/*!
+ \fn bool QScriptClassPropertyIterator::hasPrevious() const
+
+ Returns true if there is at least one item behind the iterator
+ (i.e. the iterator is \e not at the front of the property sequence);
+ otherwise returns false.
+
+ \sa previous(), hasNext()
+*/
+
+/*!
+ \fn void QScriptClassPropertyIterator::previous()
+
+ Moves the iterator back by one position.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), next(), name()
+*/
+
+/*!
+ \fn void QScriptClassPropertyIterator::toFront()
+
+ Moves the iterator to the front of the QScriptValue (before the
+ first property).
+
+ \sa toBack(), next()
+*/
+
+/*!
+ \fn void QScriptClassPropertyIterator::toBack()
+
+ Moves the iterator to the back of the QScriptValue (after the
+ last property).
+
+ \sa toFront(), previous()
+*/
+
+/*!
+ \fn QScriptString QScriptClassPropertyIterator::name() const
+
+ Returns the name of the last property that was jumped over using
+ next() or previous().
+
+ \sa id()
+*/
+
+/*!
+ \fn uint QScriptClassPropertyIterator::id() const
+
+ Returns the id of the last property that was jumped over using
+ next() or previous().
+
+ The default implementation returns 0.
+
+ \sa name()
+*/
+uint QScriptClassPropertyIterator::id() const
+{
+ return 0;
+}
+
+/*!
+ Returns the flags of the last property that was jumped over using
+ next() or previous().
+
+ The default implementation calls the propertyFlags() function of
+ object() with argument name().
+*/
+QScriptValue::PropertyFlags QScriptClassPropertyIterator::flags() const
+{
+ return object().propertyFlags(name());
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptclasspropertyiterator.h b/src/script/api/qscriptclasspropertyiterator.h
new file mode 100644
index 0000000..a954a4d
--- /dev/null
+++ b/src/script/api/qscriptclasspropertyiterator.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCLASSPROPERTYITERATOR_H
+#define QSCRIPTCLASSPROPERTYITERATOR_H
+
+#include <QtCore/qstring.h>
+
+#include <QtCore/qscopedpointer.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptClassPropertyIteratorPrivate;
+class Q_SCRIPT_EXPORT QScriptClassPropertyIterator
+{
+protected:
+ QScriptClassPropertyIterator(const QScriptValue &object);
+
+public:
+ virtual ~QScriptClassPropertyIterator();
+
+ QScriptValue object() const;
+
+ virtual bool hasNext() const = 0;
+ virtual void next() = 0;
+
+ virtual bool hasPrevious() const = 0;
+ virtual void previous() = 0;
+
+ virtual void toFront() = 0;
+ virtual void toBack() = 0;
+
+ virtual QScriptString name() const = 0;
+ virtual uint id() const;
+ virtual QScriptValue::PropertyFlags flags() const;
+
+protected:
+ QScriptClassPropertyIterator(const QScriptValue &object, QScriptClassPropertyIteratorPrivate &dd);
+ QScopedPointer<QScriptClassPropertyIteratorPrivate> d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QScriptClassPropertyIterator)
+ Q_DISABLE_COPY(QScriptClassPropertyIterator)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp
new file mode 100644
index 0000000..5454df5
--- /dev/null
+++ b/src/script/api/qscriptcontext.cpp
@@ -0,0 +1,784 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptcontext.h"
+
+#include "qscriptcontext_p.h"
+#include "qscriptcontextinfo.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "../bridge/qscriptactivationobject_p.h"
+
+#include "Arguments.h"
+#include "CodeBlock.h"
+#include "Error.h"
+#include "JSFunction.h"
+#include "JSObject.h"
+#include "JSGlobalObject.h"
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.3
+ \class QScriptContext
+
+ \brief The QScriptContext class represents a Qt Script function invocation.
+
+ \ingroup script
+ \mainclass
+
+ A QScriptContext provides access to the `this' object and arguments
+ passed to a script function. You typically want to access this
+ information when you're writing a native (C++) function (see
+ QScriptEngine::newFunction()) that will be called from script
+ code. For example, when the script code
+
+ \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 0
+
+ is evaluated, a QScriptContext will be created, and the context will
+ carry the arguments as QScriptValues; in this particular case, the
+ arguments will be one QScriptValue containing the number 20.5, a second
+ QScriptValue containing the string \c{"hello"}, and a third QScriptValue
+ containing a Qt Script object.
+
+ Use argumentCount() to get the number of arguments passed to the
+ function, and argument() to get an argument at a certain index. The
+ argumentsObject() function returns a Qt Script array object
+ containing all the arguments; you can use the QScriptValueIterator
+ to iterate over its elements, or pass the array on as arguments to
+ another script function using QScriptValue::call().
+
+ Use thisObject() to get the `this' object associated with the function call,
+ and setThisObject() to set the `this' object. If you are implementing a
+ native "instance method", you typically fetch the thisObject() and access
+ one or more of its properties:
+
+ \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 1
+
+ Use isCalledAsConstructor() to determine if the function was called
+ as a constructor (e.g. \c{"new foo()"} (as constructor) or just
+ \c{"foo()"}). When a function is called as a constructor, the
+ thisObject() contains the newly constructed object that the function
+ is expected to initialize.
+
+ Use throwValue() or throwError() to throw an exception.
+
+ Use callee() to obtain the QScriptValue that represents the function being
+ called. This can for example be used to call the function recursively.
+
+ Use parentContext() to get a pointer to the context that precedes
+ this context in the activation stack. This is mostly useful for
+ debugging purposes (e.g. when constructing some form of backtrace).
+
+ The activationObject() function returns the object that is used to
+ hold the local variables associated with this function call. You can
+ replace the activation object by calling setActivationObject(). A
+ typical usage of these functions is when you want script code to be
+ evaluated in the context of the parent context, e.g. to implement an
+ include() function:
+
+ \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 2
+
+ Use backtrace() to get a human-readable backtrace associated with
+ this context. This can be useful for debugging purposes when
+ implementing native functions. The toString() function provides a
+ string representation of the context. (QScriptContextInfo provides
+ more detailed debugging-related information about the
+ QScriptContext.)
+
+ Use engine() to obtain a pointer to the QScriptEngine that this context
+ resides in.
+
+ \sa QScriptContextInfo, QScriptEngine::newFunction(), QScriptable
+*/
+
+/*!
+ \enum QScriptContext::ExecutionState
+
+ This enum specifies the frameution state of the context.
+
+ \value NormalState The context is in a normal state.
+
+ \value ExceptionState The context is in an exceptional state.
+*/
+
+/*!
+ \enum QScriptContext::Error
+
+ This enum specifies types of error.
+
+ \value ReferenceError A reference error.
+
+ \value SyntaxError A syntax error.
+
+ \value TypeError A type error.
+
+ \value RangeError A range error.
+
+ \value URIError A URI error.
+
+ \value UnknownError An unknown error.
+*/
+
+/*!
+ \internal
+*/
+QScriptContext::QScriptContext()
+{
+ //QScriptContext doesn't exist, pointer to QScriptContext are just pointer to JSC::CallFrame
+ Q_ASSERT(false);
+}
+
+/*!
+ Throws an exception with the given \a value.
+ Returns the value thrown (the same as the argument).
+
+ \sa throwError(), state()
+*/
+QScriptValue QScriptContext::throwValue(const QScriptValue &value)
+{
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ JSC::JSValue jscValue = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(value);
+ frame->setException(jscValue);
+ return value;
+}
+
+/*!
+ Throws an \a error with the given \a text.
+ Returns the created error object.
+
+ The \a text will be stored in the \c{message} property of the error
+ object.
+
+ The error object will be initialized to contain information about
+ the location where the error occurred; specifically, it will have
+ properties \c{lineNumber}, \c{fileName} and \c{stack}. These
+ properties are described in \l {QtScript Extensions to ECMAScript}.
+
+ \sa throwValue(), state()
+*/
+QScriptValue QScriptContext::throwError(Error error, const QString &text)
+{
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ JSC::ErrorType jscError = JSC::GeneralError;
+ switch (error) {
+ case UnknownError:
+ break;
+ case ReferenceError:
+ jscError = JSC::ReferenceError;
+ break;
+ case SyntaxError:
+ jscError = JSC::SyntaxError;
+ break;
+ case TypeError:
+ jscError = JSC::TypeError;
+ break;
+ case RangeError:
+ jscError = JSC::RangeError;
+ break;
+ case URIError:
+ jscError = JSC::URIError;
+ break;
+ }
+ JSC::JSObject *result = JSC::throwError(frame, jscError, text);
+ return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
+}
+
+/*!
+ \overload
+
+ Throws an error with the given \a text.
+ Returns the created error object.
+
+ \sa throwValue(), state()
+*/
+QScriptValue QScriptContext::throwError(const QString &text)
+{
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ JSC::JSObject *result = JSC::throwError(frame, JSC::GeneralError, text);
+ return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Destroys this QScriptContext.
+*/
+QScriptContext::~QScriptContext()
+{
+ //QScriptContext doesn't exist, pointer to QScriptContext are just pointer to JSC::CallFrame
+ Q_ASSERT(false);
+}
+
+/*!
+ Returns the QScriptEngine that this QScriptContext belongs to.
+*/
+QScriptEngine *QScriptContext::engine() const
+{
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame));
+}
+
+/*!
+ Returns the function argument at the given \a index.
+
+ If \a index >= argumentCount(), a QScriptValue of
+ the primitive type Undefined is returned.
+
+ \sa argumentCount()
+*/
+QScriptValue QScriptContext::argument(int index) const
+{
+ if (index < 0)
+ return QScriptValue();
+ if (index >= argumentCount())
+ return QScriptValue(QScriptValue::UndefinedValue);
+ QScriptValue v = argumentsObject().property(index);
+ return v;
+}
+
+/*!
+ Returns the callee. The callee is the function object that this
+ QScriptContext represents an invocation of.
+*/
+QScriptValue QScriptContext::callee() const
+{
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(eng);
+ if (frame->callee() == eng->originalGlobalObject()) {
+ // This is a pushContext()-created context; the callee is a lie.
+ Q_ASSERT(QScriptEnginePrivate::contextFlags(const_cast<JSC::CallFrame*>(frame)) & QScriptEnginePrivate::NativeContext);
+ return QScriptValue();
+ }
+ return eng->scriptValueFromJSCValue(frame->callee());
+}
+
+/*!
+ Returns the arguments object of this QScriptContext.
+
+ The arguments object has properties \c callee (equal to callee())
+ and \c length (equal to argumentCount()), and properties \c 0, \c 1,
+ ..., argumentCount() - 1 that provide access to the argument
+ values. Initially, property \c P (0 <= \c P < argumentCount()) has
+ the same value as argument(\c P). In the case when \c P is less
+ than the number of formal parameters of the function, \c P shares
+ its value with the corresponding property of the activation object
+ (activationObject()). This means that changing this property changes
+ the corresponding property of the activation object and vice versa.
+
+ \sa argument(), activationObject()
+*/
+QScriptValue QScriptContext::argumentsObject() const
+{
+ JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+
+ if (frame == frame->lexicalGlobalObject()->globalExec()) {
+ // <global> context doesn't have arguments. return an empty object
+ return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject();
+ }
+
+ //for a js function
+ if (frame->codeBlock() && frame->callee()) {
+ if (!QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
+ // We have a built-in JS host call.
+ // codeBlock is needed by retrieveArguments(), but since it
+ // contains junk, we would crash. Return an invalid value for now.
+ return QScriptValue();
+ }
+ JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee()));
+ return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
+ }
+
+ if (frame->callerFrame()->hasHostCallFrameFlag()) {
+ // <eval> context doesn't have arguments. return an empty object
+ return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject();
+ }
+
+ //for a native function
+ if (!frame->optionalCalleeArguments()
+ && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { // Make sure we don't go here for host JSFunctions
+ Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later
+ JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters);
+ frame->setCalleeArguments(arguments);
+ }
+ return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->optionalCalleeArguments());
+}
+
+/*!
+ Returns true if the function was called as a constructor
+ (e.g. \c{"new foo()"}); otherwise returns false.
+
+ When a function is called as constructor, the thisObject()
+ contains the newly constructed object to be initialized.
+
+ \note This function is only guaranteed to work for a context
+ corresponding to native functions.
+*/
+bool QScriptContext::isCalledAsConstructor() const
+{
+ JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+
+ //For native functions, look up flags.
+ uint flags = QScriptEnginePrivate::contextFlags(frame);
+ if (flags & QScriptEnginePrivate::NativeContext)
+ return flags & QScriptEnginePrivate::CalledAsConstructorContext;
+
+ //Not a native function, try to look up in the bytecode if we where called from op_construct
+ JSC::Instruction* returnPC = frame->returnPC();
+
+ if (!returnPC)
+ return false;
+
+ JSC::CallFrame *callerFrame = QScriptEnginePrivate::frameForContext(parentContext());
+ if (!callerFrame)
+ return false;
+
+ if (returnPC[-JSC::op_construct_length].u.opcode == frame->interpreter()->getOpcode(JSC::op_construct)) {
+ //We are maybe called from the op_construct opcode which has 6 opperands.
+ //But we need to check we are not called from op_call with 4 opperands
+
+ //we make sure that the returnPC[-1] (thisRegister) is smaller than the returnPC[-3] (registerOffset)
+ //as if it was an op_call, the returnPC[-1] would be the registerOffset, bigger than returnPC[-3] (funcRegister)
+ return returnPC[-1].u.operand < returnPC[-3].u.operand;
+ }
+ return false;
+}
+
+/*!
+ Returns the parent context of this QScriptContext.
+*/
+QScriptContext *QScriptContext::parentContext() const
+{
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag();
+ return QScriptEnginePrivate::contextForFrame(callerFrame);
+}
+
+/*!
+ Returns the number of arguments passed to the function
+ in this invocation.
+
+ Note that the argument count can be different from the
+ formal number of arguments (the \c{length} property of
+ callee()).
+
+ \sa argument()
+*/
+int QScriptContext::argumentCount() const
+{
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ int argc = frame->argumentCount();
+ if (argc != 0)
+ --argc; // -1 due to "this"
+ return argc;
+}
+
+/*!
+ \internal
+*/
+QScriptValue QScriptContext::returnValue() const
+{
+ qWarning("QScriptContext::returnValue() not implemented");
+ return QScriptValue();
+}
+
+/*!
+ \internal
+*/
+void QScriptContext::setReturnValue(const QScriptValue &result)
+{
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ JSC::CallFrame *callerFrame = frame->callerFrame();
+ if (!callerFrame->codeBlock())
+ return;
+ Q_ASSERT_X(false, Q_FUNC_INFO, "check me");
+ int dst = frame->registers()[JSC::RegisterFile::ReturnValueRegister].i(); // returnValueRegister() is private
+ callerFrame[dst] = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(result);
+}
+
+/*!
+ Returns the activation object of this QScriptContext. The activation
+ object provides access to the local variables associated with this
+ context.
+
+ \note The activation object might not be available if there is no
+ active QScriptEngineAgent, as it might be optimized.
+
+ \sa argument(), argumentsObject()
+*/
+
+QScriptValue QScriptContext::activationObject() const
+{
+ JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ JSC::JSObject *result = 0;
+
+ uint flags = QScriptEnginePrivate::contextFlags(frame);
+ if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) {
+ //For native functions, lazily create it if needed
+ QScript::QScriptActivationObject *scope = new (frame) QScript::QScriptActivationObject(frame);
+ frame->setScopeChain(frame->scopeChain()->copy()->push(scope));
+ result = scope;
+ QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext);
+ } else {
+ // look in scope chain
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+ for (it = node->begin(); it != node->end(); ++it) {
+ if ((*it) && (*it)->isVariableObject()) {
+ result = *it;
+ break;
+ }
+ }
+ }
+ if (!result) {
+ if (!parentContext())
+ return engine()->globalObject();
+
+ qWarning("QScriptContext::activationObject: could not get activation object for frame");
+ return QScriptValue();
+ /*JSC::CodeBlock *codeBlock = frame->codeBlock();
+ if (!codeBlock) {
+ // non-Qt native function
+ Q_ASSERT(true); //### this should in theorry not happen
+ result = new (frame)QScript::QScriptActivationObject(frame);
+ } else {
+ // ### this is wrong
+ JSC::FunctionBodyNode *body = static_cast<JSC::FunctionBodyNode*>(codeBlock->ownerNode());
+ result = new (frame)JSC::JSActivation(frame, body);
+ }*/
+ }
+
+ if (result && result->inherits(&QScript::QScriptActivationObject::info)
+ && (static_cast<QScript::QScriptActivationObject*>(result)->delegate() != 0)) {
+ // Return the object that property access is being delegated to
+ result = static_cast<QScript::QScriptActivationObject*>(result)->delegate();
+ }
+
+ return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Sets the activation object of this QScriptContext to be the given \a
+ activation.
+
+ If \a activation is not an object, this function does nothing.
+
+ \note For a context corresponding to a JavaScript function, this is only
+ guaranteed to work if there was an QScriptEngineAgent active on the
+ engine while the function was evaluated.
+*/
+void QScriptContext::setActivationObject(const QScriptValue &activation)
+{
+ if (!activation.isObject())
+ return;
+ else if (activation.engine() != engine()) {
+ qWarning("QScriptContext::setActivationObject() failed: "
+ "cannot set an object created in "
+ "a different engine");
+ return;
+ }
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(engine);
+ JSC::JSObject *object = JSC::asObject(engine->scriptValueToJSCValue(activation));
+ if (object == engine->originalGlobalObjectProxy)
+ object = engine->originalGlobalObject();
+
+ uint flags = QScriptEnginePrivate::contextFlags(frame);
+ if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) {
+ //For native functions, we create a scope node
+ JSC::JSObject *scope = object;
+ if (!scope->isVariableObject()) {
+ // Create a QScriptActivationObject that acts as a proxy
+ scope = new (frame) QScript::QScriptActivationObject(frame, scope);
+ }
+ frame->setScopeChain(frame->scopeChain()->copy()->push(scope));
+ QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext);
+ return;
+ }
+
+ // else replace the first activation object in the scope chain
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ while (node != 0) {
+ if (node->object && node->object->isVariableObject()) {
+ if (!object->isVariableObject()) {
+ if (node->object->inherits(&QScript::QScriptActivationObject::info)) {
+ static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object);
+ } else {
+ // Create a QScriptActivationObject that acts as a proxy
+ node->object = new (frame) QScript::QScriptActivationObject(frame, object);
+ }
+ } else {
+ node->object = object;
+ }
+ break;
+ }
+ node = node->next;
+ }
+}
+
+/*!
+ Returns the `this' object associated with this QScriptContext.
+*/
+QScriptValue QScriptContext::thisObject() const
+{
+ JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(engine);
+ JSC::JSValue result = engine->thisForContext(frame);
+ if (!result || result.isNull())
+ result = frame->globalThisValue();
+ return engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Sets the `this' object associated with this QScriptContext to be
+ \a thisObject.
+
+ If \a thisObject is not an object, this function does nothing.
+*/
+void QScriptContext::setThisObject(const QScriptValue &thisObject)
+{
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
+ if (!thisObject.isObject())
+ return;
+ if (thisObject.engine() != engine()) {
+ qWarning("QScriptContext::setThisObject() failed: "
+ "cannot set an object created in "
+ "a different engine");
+ return;
+ }
+ if (frame == frame->lexicalGlobalObject()->globalExec()) {
+ engine()->setGlobalObject(thisObject);
+ return;
+ }
+ JSC::JSValue jscThisObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(thisObject);
+ JSC::CodeBlock *cb = frame->codeBlock();
+ if (cb != 0) {
+ frame[cb->thisRegister()] = jscThisObject;
+ } else {
+ JSC::Register* thisRegister = QScriptEnginePrivate::thisRegisterForFrame(frame);
+ thisRegister[0] = jscThisObject;
+ }
+}
+
+/*!
+ Returns the frameution state of this QScriptContext.
+*/
+QScriptContext::ExecutionState QScriptContext::state() const
+{
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ if (frame->hadException())
+ return QScriptContext::ExceptionState;
+ return QScriptContext::NormalState;
+}
+
+/*!
+ Returns a human-readable backtrace of this QScriptContext.
+
+ Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
+
+ To access individual pieces of debugging-related information (for
+ example, to construct your own backtrace representation), use
+ QScriptContextInfo.
+
+ \sa QScriptEngine::uncaughtExceptionBacktrace(), QScriptContextInfo, toString()
+*/
+QStringList QScriptContext::backtrace() const
+{
+ QStringList result;
+ const QScriptContext *ctx = this;
+ while (ctx) {
+ result.append(ctx->toString());
+ ctx = ctx->parentContext();
+ }
+ return result;
+}
+
+/*!
+ \since 4.4
+
+ Returns a string representation of this context.
+ This is useful for debugging.
+
+ \sa backtrace()
+*/
+QString QScriptContext::toString() const
+{
+ QScriptContextInfo info(this);
+ QString result;
+
+ QString functionName = info.functionName();
+ if (functionName.isEmpty()) {
+ if (parentContext()) {
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ if (info.functionType() == QScriptContextInfo::ScriptFunction)
+ result.append(QLatin1String("<anonymous>"));
+ else if(frame->callerFrame()->hasHostCallFrameFlag())
+ result.append(QLatin1String("<eval>"));
+ else
+ result.append(QLatin1String("<native>"));
+ } else {
+ result.append(QLatin1String("<global>"));
+ }
+ } else {
+ result.append(functionName);
+ }
+
+ QStringList parameterNames = info.functionParameterNames();
+ result.append(QLatin1Char('('));
+ for (int i = 0; i < argumentCount(); ++i) {
+ if (i > 0)
+ result.append(QLatin1String(", "));
+ if (i < parameterNames.count()) {
+ result.append(parameterNames.at(i));
+ result.append(QLatin1String(" = "));
+ }
+ QScriptValue arg = argument(i);
+ if (arg.isString())
+ result.append(QLatin1Char('\''));
+ result.append(arg.toString());
+ if (arg.isString())
+ result.append(QLatin1Char('\''));
+
+ }
+ result.append(QLatin1Char(')'));
+
+ QString fileName = info.fileName();
+ int lineNumber = info.lineNumber();
+ result.append(QLatin1String(" at "));
+ if (!fileName.isEmpty()) {
+ result.append(fileName);
+ result.append(QLatin1Char(':'));
+ }
+ result.append(QString::number(lineNumber));
+ return result;
+}
+
+/*!
+ \internal
+ \since 4.5
+
+ Returns the scope chain of this QScriptContext.
+*/
+QScriptValueList QScriptContext::scopeChain() const
+{
+ activationObject(); //ensure the creation of the normal scope for native context
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(engine);
+ QScriptValueList result;
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+ for (it = node->begin(); it != node->end(); ++it) {
+ JSC::JSObject *object = *it;
+ if (!object)
+ continue;
+ if (object->inherits(&QScript::QScriptActivationObject::info)
+ && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
+ // Return the object that property access is being delegated to
+ object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
+ }
+ result.append(engine->scriptValueFromJSCValue(object));
+ }
+ return result;
+}
+
+/*!
+ \internal
+ \since 4.5
+
+ Adds the given \a object to the front of this context's scope chain.
+
+ If \a object is not an object, this function does nothing.
+*/
+void QScriptContext::pushScope(const QScriptValue &object)
+{
+ activationObject(); //ensure the creation of the normal scope for native context
+ if (!object.isObject())
+ return;
+ else if (object.engine() != engine()) {
+ qWarning("QScriptContext::pushScope() failed: "
+ "cannot push an object created in "
+ "a different engine");
+ return;
+ }
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(engine);
+ JSC::JSObject *jscObject = JSC::asObject(engine->scriptValueToJSCValue(object));
+ if (jscObject == engine->originalGlobalObjectProxy)
+ jscObject = engine->originalGlobalObject();
+ JSC::ScopeChainNode *scope = frame->scopeChain();
+ Q_ASSERT(scope != 0);
+ if (!scope->object) {
+ // pushing to an "empty" chain
+ if (!jscObject->isGlobalObject()) {
+ qWarning("QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object");
+ return;
+ }
+ scope->object = jscObject;
+ }
+ else
+ frame->setScopeChain(scope->push(jscObject));
+}
+
+/*!
+ \internal
+ \since 4.5
+
+ Removes the front object from this context's scope chain, and
+ returns the removed object.
+
+ If the scope chain is already empty, this function returns an
+ invalid QScriptValue.
+*/
+QScriptValue QScriptContext::popScope()
+{
+ activationObject(); //ensure the creation of the normal scope for native context
+ JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
+ JSC::ScopeChainNode *scope = frame->scopeChain();
+ Q_ASSERT(scope != 0);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+ QScript::APIShim shim(engine);
+ QScriptValue result = engine->scriptValueFromJSCValue(scope->object);
+ if (!scope->next) {
+ // We cannot have a null scope chain, so just zap the object pointer.
+ scope->object = 0;
+ } else {
+ frame->setScopeChain(scope->pop());
+ }
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptcontext.h b/src/script/api/qscriptcontext.h
new file mode 100644
index 0000000..8bd43e6
--- /dev/null
+++ b/src/script/api/qscriptcontext.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCONTEXT_H
+#define QSCRIPTCONTEXT_H
+
+#include <QtCore/qobjectdefs.h>
+
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptContextPrivate;
+
+class Q_SCRIPT_EXPORT QScriptContext
+{
+public:
+ enum ExecutionState {
+ NormalState,
+ ExceptionState
+ };
+
+ enum Error {
+ UnknownError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ RangeError,
+ URIError
+ };
+
+ ~QScriptContext();
+
+ QScriptContext *parentContext() const;
+ QScriptEngine *engine() const;
+
+ ExecutionState state() const;
+ QScriptValue callee() const;
+
+ int argumentCount() const;
+ QScriptValue argument(int index) const;
+ QScriptValue argumentsObject() const;
+
+ QScriptValueList scopeChain() const;
+ void pushScope(const QScriptValue &object);
+ QScriptValue popScope();
+
+ QScriptValue returnValue() const;
+ void setReturnValue(const QScriptValue &result);
+
+ QScriptValue activationObject() const;
+ void setActivationObject(const QScriptValue &activation);
+
+ QScriptValue thisObject() const;
+ void setThisObject(const QScriptValue &thisObject);
+
+ bool isCalledAsConstructor() const;
+
+ QScriptValue throwValue(const QScriptValue &value);
+ QScriptValue throwError(Error error, const QString &text);
+ QScriptValue throwError(const QString &text);
+
+ QStringList backtrace() const;
+
+ QString toString() const;
+
+private:
+ QScriptContext();
+
+ QScriptContextPrivate *d_ptr;
+
+ Q_DECLARE_PRIVATE(QScriptContext)
+ Q_DISABLE_COPY(QScriptContext)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptcontext_p.h b/src/script/api/qscriptcontext_p.h
new file mode 100644
index 0000000..2919637
--- /dev/null
+++ b/src/script/api/qscriptcontext_p.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCONTEXT_P_H
+#define QSCRIPTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+namespace JSC
+{
+ class JSObject;
+ class ArgList;
+ class ExecState;
+}
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEnginePrivate;
+
+class QScriptContext;
+
+QT_END_NAMESPACE
+
+#include "wtf/Platform.h"
+#include "JSValue.h"
+
+#endif
diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp
new file mode 100644
index 0000000..182bc4a
--- /dev/null
+++ b/src/script/api/qscriptcontextinfo.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptcontextinfo.h"
+
+#include "qscriptcontext_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "../bridge/qscriptqobject_p.h"
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmetaobject.h>
+#include "CodeBlock.h"
+#include "JSFunction.h"
+#if ENABLE(JIT)
+#include "MacroAssemblerCodeRef.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.4
+ \class QScriptContextInfo
+
+ \brief The QScriptContextInfo class provides additional information about a QScriptContext.
+
+ \ingroup script
+
+
+ QScriptContextInfo is typically used for debugging purposes. It can
+ provide information about the code being executed, such as the type
+ of the called function, and the original source code location of the
+ current statement.
+
+ If the called function is executing Qt Script code, you can obtain
+ the script location with the functions fileName() and lineNumber().
+
+ You can obtain the starting line number and ending line number of a
+ Qt Script function definition with functionStartLineNumber() and
+ functionEndLineNumber(), respectively.
+
+ For Qt Script functions and Qt methods (e.g. slots), you can call
+ functionParameterNames() to get the names of the formal parameters of the
+ function.
+
+ For Qt methods and Qt property accessors, you can obtain the index
+ of the underlying QMetaMethod or QMetaProperty by calling
+ functionMetaIndex().
+
+ \sa QScriptContext, QScriptEngineAgent
+*/
+
+/*!
+ \enum QScriptContextInfo::FunctionType
+
+ This enum specifies the type of function being called.
+
+ \value ScriptFunction The function is a Qt Script function, i.e. it was defined through a call to QScriptEngine::evaluate().
+ \value QtFunction The function is a Qt function (a signal, slot or method).
+ \value QtPropertyFunction The function is a Qt property getter or setter.
+ \value NativeFunction The function is a built-in Qt Script function, or it was defined through a call to QScriptEngine::newFunction().
+*/
+
+class QScriptContextInfoPrivate
+{
+ Q_DECLARE_PUBLIC(QScriptContextInfo)
+public:
+ QScriptContextInfoPrivate();
+ QScriptContextInfoPrivate(const QScriptContext *context);
+ ~QScriptContextInfoPrivate();
+
+ qint64 scriptId;
+ int lineNumber;
+ int columnNumber;
+ QString fileName;
+
+ QString functionName;
+ QScriptContextInfo::FunctionType functionType;
+
+ int functionStartLineNumber;
+ int functionEndLineNumber;
+ int functionMetaIndex;
+
+ QStringList parameterNames;
+
+ QBasicAtomicInt ref;
+
+ QScriptContextInfo *q_ptr;
+};
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::QScriptContextInfoPrivate()
+{
+ ref = 0;
+ functionType = QScriptContextInfo::NativeFunction;
+ functionMetaIndex = -1;
+ functionStartLineNumber = -1;
+ functionEndLineNumber = -1;
+ scriptId = -1;
+ lineNumber = -1;
+ columnNumber = -1;
+}
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context)
+{
+ Q_ASSERT(context);
+ ref = 0;
+ functionType = QScriptContextInfo::NativeFunction;
+ functionMetaIndex = -1;
+ functionStartLineNumber = -1;
+ functionEndLineNumber = -1;
+ scriptId = -1;
+ lineNumber = -1;
+ columnNumber = -1;
+
+ JSC::CallFrame *frame = const_cast<JSC::CallFrame *>(QScriptEnginePrivate::frameForContext(context));
+
+ // Get the line number:
+
+ //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
+ JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
+ if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context
+ frame = rewindContext; //for retreiving the global context's "fake" frame
+ // An agent might have provided the line number.
+ lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
+ } else {
+ // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
+ while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
+ rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
+ if (rewindContext) {
+ frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame
+
+ JSC::Instruction *returnPC = rewindContext->returnPC();
+ JSC::CodeBlock *codeBlock = frame->codeBlock();
+ if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
+#if ENABLE(JIT)
+ JSC::JITCode code = codeBlock->getJITCode();
+ unsigned jitOffset = code.offsetOf(JSC::ReturnAddressPtr(returnPC).value());
+ // We can only use the JIT code offset if it's smaller than the JIT size;
+ // otherwise calling getBytecodeIndex() is meaningless.
+ if (jitOffset < code.size()) {
+ unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC));
+#else
+ unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin();
+#endif
+ bytecodeOffset--; //because returnPC is on the next instruction. We want the current one
+ lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
+#if ENABLE(JIT)
+ }
+#endif
+ }
+ }
+ }
+
+ // Get the filename and the scriptId:
+ JSC::CodeBlock *codeBlock = frame->codeBlock();
+ if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
+ JSC::SourceProvider *source = codeBlock->source();
+ scriptId = source->asID();
+ fileName = source->url();
+ }
+
+ // Get the others information:
+ JSC::JSObject *callee = frame->callee();
+ if (callee && callee->inherits(&JSC::InternalFunction::info))
+ functionName = JSC::asInternalFunction(callee)->name(frame);
+ if (callee && callee->inherits(&JSC::JSFunction::info)
+ && !JSC::asFunction(callee)->isHostFunction()) {
+ functionType = QScriptContextInfo::ScriptFunction;
+ JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable();
+ functionStartLineNumber = body->lineNo();
+ functionEndLineNumber = body->lastLine();
+ for (size_t i = 0; i < body->parameterCount(); ++i)
+ parameterNames.append(body->parameterName(i));
+ // ### get the function name from the AST
+ } else if (callee && callee->inherits(&QScript::QtFunction::info)) {
+ functionType = QScriptContextInfo::QtFunction;
+ // ### the slot can be overloaded -- need to get the particular overload from the context
+ functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->initialIndex();
+ const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject();
+ if (meta != 0) {
+ QMetaMethod method = meta->method(functionMetaIndex);
+ QList<QByteArray> formals = method.parameterNames();
+ for (int i = 0; i < formals.count(); ++i)
+ parameterNames.append(QLatin1String(formals.at(i)));
+ }
+ }
+ else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) {
+ functionType = QScriptContextInfo::QtPropertyFunction;
+ functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex();
+ }
+}
+
+/*!
+ \internal
+*/
+QScriptContextInfoPrivate::~QScriptContextInfoPrivate()
+{
+}
+
+/*!
+ Constructs a new QScriptContextInfo from the given \a context.
+
+ The relevant information is extracted from the \a context at
+ construction time; i.e. if you continue script execution in the \a
+ context, the new state of the context will not be reflected in a
+ previously created QScriptContextInfo.
+*/
+QScriptContextInfo::QScriptContextInfo(const QScriptContext *context)
+ : d_ptr(0)
+{
+ if (context) {
+ d_ptr = new QScriptContextInfoPrivate(context);
+ d_ptr->q_ptr = this;
+ }
+}
+
+/*!
+ Constructs a new QScriptContextInfo from the \a other info.
+*/
+QScriptContextInfo::QScriptContextInfo(const QScriptContextInfo &other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ Constructs a null QScriptContextInfo.
+
+ \sa isNull()
+*/
+QScriptContextInfo::QScriptContextInfo()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Destroys the QScriptContextInfo.
+*/
+QScriptContextInfo::~QScriptContextInfo()
+{
+}
+
+/*!
+ Assigns the \a other info to this QScriptContextInfo,
+ and returns a reference to this QScriptContextInfo.
+*/
+QScriptContextInfo &QScriptContextInfo::operator=(const QScriptContextInfo &other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns the ID of the script where the code being executed was
+ defined, or -1 if the ID is not available (i.e. a native function is
+ being executed).
+
+ \sa QScriptEngineAgent::scriptLoad()
+*/
+qint64 QScriptContextInfo::scriptId() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->scriptId;
+}
+
+/*!
+ Returns the name of the file where the code being executed was
+ defined, if available; otherwise returns an empty string.
+
+ For Qt Script code, this function returns the fileName argument
+ that was passed to QScriptEngine::evaluate().
+
+ \sa lineNumber(), functionName()
+*/
+QString QScriptContextInfo::fileName() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QString();
+ return d->fileName;
+}
+
+/*!
+ Returns the line number corresponding to the statement being
+ executed, or -1 if the line number is not available.
+
+ The line number is only available if Qt Script code is being
+ executed.
+
+ \sa columnNumber(), fileName()
+*/
+int QScriptContextInfo::lineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->lineNumber;
+}
+
+/*!
+ \obsolete
+*/
+int QScriptContextInfo::columnNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->columnNumber;
+}
+
+/*!
+ Returns the name of the called function, or an empty string if
+ the name is not available.
+
+ For script functions of type QtPropertyFunction, this function
+ always returns the name of the property; you can use
+ QScriptContext::argumentCount() to differentiate between reads and
+ writes.
+
+ \sa fileName(), functionType()
+*/
+QString QScriptContextInfo::functionName() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QString();
+ return d->functionName;
+}
+
+/*!
+ Returns the type of the called function.
+
+ \sa functionName(), QScriptContext::callee()
+*/
+QScriptContextInfo::FunctionType QScriptContextInfo::functionType() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return NativeFunction;
+ return d->functionType;
+}
+
+/*!
+ Returns the line number where the definition of the called function
+ starts, or -1 if the line number is not available.
+
+ The starting line number is only available if the functionType() is
+ ScriptFunction.
+
+ \sa functionEndLineNumber(), fileName()
+*/
+int QScriptContextInfo::functionStartLineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionStartLineNumber;
+}
+
+/*!
+ Returns the line number where the definition of the called function
+ ends, or -1 if the line number is not available.
+
+ The ending line number is only available if the functionType() is
+ ScriptFunction.
+
+ \sa functionStartLineNumber()
+*/
+int QScriptContextInfo::functionEndLineNumber() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionEndLineNumber;
+}
+
+/*!
+ Returns the names of the formal parameters of the called function,
+ or an empty QStringList if the parameter names are not available.
+
+ \sa QScriptContext::argument()
+*/
+QStringList QScriptContextInfo::functionParameterNames() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return QStringList();
+ return d->parameterNames;
+}
+
+/*!
+ Returns the meta index of the called function, or -1 if the meta
+ index is not available.
+
+ The meta index is only available if the functionType() is QtFunction
+ or QtPropertyFunction. For QtFunction, the meta index can be passed
+ to QMetaObject::method() to obtain the corresponding method
+ definition; for QtPropertyFunction, the meta index can be passed to
+ QMetaObject::property() to obtain the corresponding property
+ definition.
+
+ \sa QScriptContext::thisObject()
+*/
+int QScriptContextInfo::functionMetaIndex() const
+{
+ Q_D(const QScriptContextInfo);
+ if (!d)
+ return -1;
+ return d->functionMetaIndex;
+}
+
+/*!
+ Returns true if this QScriptContextInfo is null, i.e. does not
+ contain any information.
+*/
+bool QScriptContextInfo::isNull() const
+{
+ Q_D(const QScriptContextInfo);
+ return (d == 0);
+}
+
+/*!
+ Returns true if this QScriptContextInfo is equal to the \a other
+ info, otherwise returns false.
+*/
+bool QScriptContextInfo::operator==(const QScriptContextInfo &other) const
+{
+ Q_D(const QScriptContextInfo);
+ const QScriptContextInfoPrivate *od = other.d_func();
+ if (d == od)
+ return true;
+ if (!d || !od)
+ return false;
+ return ((d->scriptId == od->scriptId)
+ && (d->lineNumber == od->lineNumber)
+ && (d->columnNumber == od->columnNumber)
+ && (d->fileName == od->fileName)
+ && (d->functionName == od->functionName)
+ && (d->functionType == od->functionType)
+ && (d->functionStartLineNumber == od->functionStartLineNumber)
+ && (d->functionEndLineNumber == od->functionEndLineNumber)
+ && (d->functionMetaIndex == od->functionMetaIndex)
+ && (d->parameterNames == od->parameterNames));
+}
+
+/*!
+ Returns true if this QScriptContextInfo is not equal to the \a other
+ info, otherwise returns false.
+*/
+bool QScriptContextInfo::operator!=(const QScriptContextInfo &other) const
+{
+ return !(*this == other);
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QScriptContextInfo &info)
+ \since 4.4
+ \relates QScriptContextInfo
+
+ Writes the given \a info to the specified \a stream.
+*/
+QDataStream &operator<<(QDataStream &out, const QScriptContextInfo &info)
+{
+ out << info.scriptId();
+ out << (qint32)info.lineNumber();
+ out << (qint32)info.columnNumber();
+
+ out << (quint32)info.functionType();
+ out << (qint32)info.functionStartLineNumber();
+ out << (qint32)info.functionEndLineNumber();
+ out << (qint32)info.functionMetaIndex();
+
+ out << info.fileName();
+ out << info.functionName();
+ out << info.functionParameterNames();
+
+ return out;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QScriptContextInfo &info)
+ \since 4.4
+ \relates QScriptContextInfo
+
+ Reads a QScriptContextInfo from the specified \a stream into the
+ given \a info.
+*/
+Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &in, QScriptContextInfo &info)
+{
+ if (!info.d_ptr) {
+ info.d_ptr = new QScriptContextInfoPrivate();
+ }
+
+ in >> info.d_ptr->scriptId;
+
+ qint32 line;
+ in >> line;
+ info.d_ptr->lineNumber = line;
+
+ qint32 column;
+ in >> column;
+ info.d_ptr->columnNumber = column;
+
+ quint32 ftype;
+ in >> ftype;
+ info.d_ptr->functionType = QScriptContextInfo::FunctionType(ftype);
+
+ qint32 startLine;
+ in >> startLine;
+ info.d_ptr->functionStartLineNumber = startLine;
+
+ qint32 endLine;
+ in >> endLine;
+ info.d_ptr->functionEndLineNumber = endLine;
+
+ qint32 metaIndex;
+ in >> metaIndex;
+ info.d_ptr->functionMetaIndex = metaIndex;
+
+ in >> info.d_ptr->fileName;
+ in >> info.d_ptr->functionName;
+ in >> info.d_ptr->parameterNames;
+
+ return in;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptcontextinfo.h b/src/script/api/qscriptcontextinfo.h
new file mode 100644
index 0000000..ebb407d
--- /dev/null
+++ b/src/script/api/qscriptcontextinfo.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTCONTEXTINFO_H
+#define QSCRIPTCONTEXTINFO_H
+
+#include <QtCore/qobjectdefs.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptContext;
+#ifndef QT_NO_DATASTREAM
+class QDataStream;
+#endif
+
+class QScriptContextInfoPrivate;
+class Q_SCRIPT_EXPORT QScriptContextInfo
+{
+public:
+#ifndef QT_NO_DATASTREAM
+ friend Q_SCRIPT_EXPORT QDataStream &operator<<(QDataStream &, const QScriptContextInfo &);
+ friend Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &, QScriptContextInfo &);
+#endif
+
+ enum FunctionType {
+ ScriptFunction,
+ QtFunction,
+ QtPropertyFunction,
+ NativeFunction
+ };
+
+ QScriptContextInfo(const QScriptContext *context);
+ QScriptContextInfo(const QScriptContextInfo &other);
+ QScriptContextInfo();
+ ~QScriptContextInfo();
+
+ QScriptContextInfo &operator=(const QScriptContextInfo &other);
+
+ bool isNull() const;
+
+ qint64 scriptId() const;
+ QString fileName() const;
+ int lineNumber() const;
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED int columnNumber() const;
+#endif
+
+ QString functionName() const;
+ FunctionType functionType() const;
+
+ QStringList functionParameterNames() const;
+
+ int functionStartLineNumber() const;
+ int functionEndLineNumber() const;
+
+ int functionMetaIndex() const;
+
+ bool operator==(const QScriptContextInfo &other) const;
+ bool operator!=(const QScriptContextInfo &other) const;
+
+private:
+ QExplicitlySharedDataPointer<QScriptContextInfoPrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QScriptContextInfo)
+};
+
+typedef QList<QScriptContextInfo> QScriptContextInfoList;
+
+#ifndef QT_NO_DATASTREAM
+Q_SCRIPT_EXPORT QDataStream &operator<<(QDataStream &, const QScriptContextInfo &);
+Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &, QScriptContextInfo &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
new file mode 100644
index 0000000..a3a965e
--- /dev/null
+++ b/src/script/api/qscriptengine.cpp
@@ -0,0 +1,4456 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptengine.h"
+#include "qscriptsyntaxchecker_p.h"
+
+#include "qscriptengine_p.h"
+#include "qscriptengineagent_p.h"
+#include "qscriptcontext_p.h"
+#include "qscriptstring_p.h"
+#include "qscriptvalue_p.h"
+#include "qscriptvalueiterator.h"
+#include "qscriptclass.h"
+#include "qscriptcontextinfo.h"
+#include "qscriptprogram.h"
+#include "qscriptprogram_p.h"
+#include "qdebug.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+
+#include <math.h>
+
+#include "CodeBlock.h"
+#include "Error.h"
+#include "Interpreter.h"
+
+#include "ExceptionHelpers.h"
+#include "PrototypeFunction.h"
+#include "InitializeThreading.h"
+#include "ObjectPrototype.h"
+#include "SourceCode.h"
+#include "FunctionPrototype.h"
+#include "TimeoutChecker.h"
+#include "JSFunction.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "Operations.h"
+
+#include "bridge/qscriptfunction_p.h"
+#include "bridge/qscriptclassobject_p.h"
+#include "bridge/qscriptvariant_p.h"
+#include "bridge/qscriptqobject_p.h"
+#include "bridge/qscriptglobalobject_p.h"
+#include "bridge/qscriptactivationobject_p.h"
+#include "bridge/qscriptstaticscopeobject_p.h"
+
+#ifndef QT_NO_QOBJECT
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qpluginloader.h>
+#include <QtCore/qset.h>
+#include <QtCore/qtextstream.h>
+#include "qscriptextensioninterface.h"
+#endif
+
+Q_DECLARE_METATYPE(QScriptValue)
+#ifndef QT_NO_QOBJECT
+Q_DECLARE_METATYPE(QObjectList)
+#endif
+Q_DECLARE_METATYPE(QList<int>)
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.3
+ \class QScriptEngine
+ \reentrant
+
+ \brief The QScriptEngine class provides an environment for evaluating Qt Script code.
+
+ \ingroup script
+ \mainclass
+
+ See the \l{QtScript} documentation for information about the Qt Script language,
+ and how to get started with scripting your C++ application.
+
+ \section1 Evaluating Scripts
+
+ Use evaluate() to evaluate script code; this is the C++ equivalent
+ of the built-in script function \c{eval()}.
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0
+
+ evaluate() returns a QScriptValue that holds the result of the
+ evaluation. The QScriptValue class provides functions for converting
+ the result to various C++ types (e.g. QScriptValue::toString()
+ and QScriptValue::toNumber()).
+
+ The following code snippet shows how a script function can be
+ defined and then invoked from C++ using QScriptValue::call():
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1
+
+ As can be seen from the above snippets, a script is provided to the
+ engine in the form of a string. One common way of loading scripts is
+ by reading the contents of a file and passing it to evaluate():
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2
+
+ Here we pass the name of the file as the second argument to
+ evaluate(). This does not affect evaluation in any way; the second
+ argument is a general-purpose string that is used to identify the
+ script for debugging purposes (for example, our filename will now
+ show up in any uncaughtExceptionBacktrace() involving the script).
+
+ \section1 Engine Configuration
+
+ The globalObject() function returns the \bold {Global Object}
+ associated with the script engine. Properties of the Global Object
+ are accessible from any script code (i.e. they are global
+ variables). Typically, before evaluating "user" scripts, you will
+ want to configure a script engine by adding one or more properties
+ to the Global Object:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3
+
+ Adding custom properties to the scripting environment is one of the
+ standard means of providing a scripting API that is specific to your
+ application. Usually these custom properties are objects created by
+ the newQObject() or newObject() functions, or constructor functions
+ created by newFunction().
+
+ \section1 Script Exceptions
+
+ evaluate() can throw a script exception (e.g. due to a syntax
+ error); in that case, the return value is the value that was thrown
+ (typically an \c{Error} object). You can check whether the
+ evaluation caused an exception by calling hasUncaughtException(). In
+ that case, you can call toString() on the error object to obtain an
+ error message. The current uncaught exception is also available
+ through uncaughtException().
+ Calling clearExceptions() will cause any uncaught exceptions to be
+ cleared.
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
+
+ The checkSyntax() function can be used to determine whether code can be
+ usefully passed to evaluate().
+
+ \section1 Script Object Creation
+
+ Use newObject() to create a standard Qt Script object; this is the
+ C++ equivalent of the script statement \c{new Object()}. You can use
+ the object-specific functionality in QScriptValue to manipulate the
+ script object (e.g. QScriptValue::setProperty()). Similarly, use
+ newArray() to create a Qt Script array object. Use newDate() to
+ create a \c{Date} object, and newRegExp() to create a \c{RegExp}
+ object.
+
+ \section1 QObject Integration
+
+ Use newQObject() to wrap a QObject (or subclass)
+ pointer. newQObject() returns a proxy script object; properties,
+ children, and signals and slots of the QObject are available as
+ properties of the proxy object. No binding code is needed because it
+ is done dynamically using the Qt meta object system.
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5
+
+ Use qScriptConnect() to connect a C++ signal to a script function;
+ this is the Qt Script equivalent of QObject::connect(). When a
+ script function is invoked in response to a C++ signal, it can cause
+ a script exception; you can connect to the signalHandlerException()
+ signal to catch such an exception.
+
+ Use newQMetaObject() to wrap a QMetaObject; this gives you a "script
+ representation" of a QObject-based class. newQMetaObject() returns a
+ proxy script object; enum values of the class are available as
+ properties of the proxy object. You can also specify a function that
+ will be used to construct objects of the class (e.g. when the
+ constructor is invoked from a script). For classes that have a
+ "standard" Qt constructor, Qt Script can provide a default script
+ constructor for you; see scriptValueFromQMetaObject().
+
+ See the \l{QtScript} documentation for more information on
+ the QObject integration.
+
+ \section1 Support for Custom C++ Types
+
+ Use newVariant() to wrap a QVariant. This can be used to store
+ values of custom (non-QObject) C++ types that have been registered
+ with the Qt meta-type system. To make such types scriptable, you
+ typically associate a prototype (delegate) object with the C++ type
+ by calling setDefaultPrototype(); the prototype object defines the
+ scripting API for the C++ type. Unlike the QObject integration,
+ there is no automatic binding possible here; i.e. you have to create
+ the scripting API yourself, for example by using the QScriptable
+ class.
+
+ Use fromScriptValue() to cast from a QScriptValue to another type,
+ and toScriptValue() to create a QScriptValue from another value.
+ You can specify how the conversion of C++ types is to be performed
+ with qScriptRegisterMetaType() and qScriptRegisterSequenceMetaType().
+ By default, Qt Script will use QVariant to store values of custom
+ types.
+
+ \section1 Importing Extensions
+
+ Use importExtension() to import plugin-based extensions into the
+ engine. Call availableExtensions() to obtain a list naming all the
+ available extensions, and importedExtensions() to obtain a list
+ naming only those extensions that have been imported.
+
+ Call pushContext() to open up a new variable scope, and popContext()
+ to close the current scope. This is useful if you are implementing
+ an extension that evaluates script code containing temporary
+ variable definitions (e.g. \c{var foo = 123;}) that are safe to
+ discard when evaluation has completed.
+
+ \section1 Native Functions
+
+ Use newFunction() to wrap native (C++) functions, including
+ constructors for your own custom types, so that these can be invoked
+ from script code. Such functions must have the signature
+ QScriptEngine::FunctionSignature. You may then pass the function as
+ argument to newFunction(). Here is an example of a function that
+ returns the sum of its first two arguments:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6
+
+ To expose this function to script code, you can set it as a property
+ of the Global Object:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7
+
+ Once this is done, script code can call your function in the exact
+ same manner as a "normal" script function:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8
+
+ \section1 Long-running Scripts
+
+ If you need to evaluate possibly long-running scripts from the main
+ (GUI) thread, you should first call setProcessEventsInterval() to
+ make sure that the GUI stays responsive. You can abort a currently
+ running script by calling abortEvaluation(). You can determine
+ whether an engine is currently running a script by calling
+ isEvaluating().
+
+ \section1 Garbage Collection
+
+ Qt Script objects may be garbage collected when they are no longer
+ referenced. There is no guarantee as to when automatic garbage
+ collection will take place.
+
+ The collectGarbage() function can be called to explicitly request
+ garbage collection.
+
+ The reportAdditionalMemoryCost() function can be called to indicate
+ that a Qt Script object occupies memory that isn't managed by the
+ scripting environment. Reporting the additional cost makes it more
+ likely that the garbage collector will be triggered. This can be
+ useful, for example, when many custom, native Qt Script objects are
+ allocated.
+
+ \section1 Core Debugging/Tracing Facilities
+
+ Since Qt 4.4, you can be notified of events pertaining to script
+ execution (e.g. script function calls and statement execution)
+ through the QScriptEngineAgent interface; see the setAgent()
+ function. This can be used to implement debugging and profiling of a
+ QScriptEngine.
+
+ \sa QScriptValue, QScriptContext, QScriptEngineAgent
+
+*/
+
+/*!
+ \enum QScriptEngine::ValueOwnership
+
+ This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject().
+
+ \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 & Ownership}.)
+
+ \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).
+
+ \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).
+
+*/
+
+/*!
+ \enum QScriptEngine::QObjectWrapOption
+
+ These flags specify options when wrapping a QObject pointer with newQObject().
+
+ \value ExcludeChildObjects The script object will not expose child objects as properties.
+ \value ExcludeSuperClassMethods The script object will not expose signals and slots inherited from the superclass.
+ \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass.
+ \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties
+ \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot.
+ \value ExcludeSlots The script object will not expose the QObject's slots.
+ \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.
+ \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object.
+ \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties.
+*/
+
+class QScriptSyntaxCheckResultPrivate
+{
+public:
+ QScriptSyntaxCheckResultPrivate() { ref = 0; }
+ ~QScriptSyntaxCheckResultPrivate() {}
+
+ QScriptSyntaxCheckResult::State state;
+ int errorColumnNumber;
+ int errorLineNumber;
+ QString errorMessage;
+ QBasicAtomicInt ref;
+};
+
+class QScriptTypeInfo
+{
+public:
+ QScriptTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0)
+ { }
+
+ QByteArray signature;
+ QScriptEngine::MarshalFunction marshal;
+ QScriptEngine::DemarshalFunction demarshal;
+ JSC::JSValue prototype;
+};
+
+namespace QScript
+{
+
+static const qsreal D32 = 4294967296.0;
+
+qint32 ToInt32(qsreal n)
+{
+ if (qIsNaN(n) || qIsInf(n) || (n == 0))
+ return 0;
+
+ qsreal sign = (n < 0) ? -1.0 : 1.0;
+ qsreal abs_n = fabs(n);
+
+ n = ::fmod(sign * ::floor(abs_n), D32);
+ const double D31 = D32 / 2.0;
+
+ if (sign == -1 && n < -D31)
+ n += D32;
+
+ else if (sign != -1 && n >= D31)
+ n -= D32;
+
+ return qint32 (n);
+}
+
+quint32 ToUInt32(qsreal n)
+{
+ if (qIsNaN(n) || qIsInf(n) || (n == 0))
+ return 0;
+
+ qsreal sign = (n < 0) ? -1.0 : 1.0;
+ qsreal abs_n = fabs(n);
+
+ n = ::fmod(sign * ::floor(abs_n), D32);
+
+ if (n < 0)
+ n += D32;
+
+ return quint32 (n);
+}
+
+quint16 ToUInt16(qsreal n)
+{
+ static const qsreal D16 = 65536.0;
+
+ if (qIsNaN(n) || qIsInf(n) || (n == 0))
+ return 0;
+
+ qsreal sign = (n < 0) ? -1.0 : 1.0;
+ qsreal abs_n = fabs(n);
+
+ n = ::fmod(sign * ::floor(abs_n), D16);
+
+ if (n < 0)
+ n += D16;
+
+ return quint16 (n);
+}
+
+qsreal ToInteger(qsreal n)
+{
+ if (qIsNaN(n))
+ return 0;
+
+ if (n == 0 || qIsInf(n))
+ return n;
+
+ int sign = n < 0 ? -1 : 1;
+ return sign * ::floor(::fabs(n));
+}
+
+#ifdef Q_CC_MSVC
+// MSVC2008 crashes if these are inlined.
+
+QString ToString(qsreal value)
+{
+ return JSC::UString::from(value);
+}
+
+qsreal ToNumber(const QString &value)
+{
+ return ((JSC::UString)value).toDouble();
+}
+
+#endif
+
+static const qsreal MsPerSecond = 1000.0;
+
+static inline int MsFromTime(qsreal t)
+{
+ int r = int(::fmod(t, MsPerSecond));
+ return (r >= 0) ? r : r + int(MsPerSecond);
+}
+
+/*!
+ \internal
+ Converts a JS date value (milliseconds) to a QDateTime (local time).
+*/
+QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t)
+{
+ if (qIsNaN(t))
+ return QDateTime();
+ JSC::GregorianDateTime tm;
+ JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm);
+ int ms = MsFromTime(t);
+ QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
+ QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
+ return convertedUTC.toLocalTime();
+}
+
+/*!
+ \internal
+ Converts a QDateTime to a JS date value (milliseconds).
+*/
+qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt)
+{
+ if (!dt.isValid())
+ return qSNaN();
+ QDateTime utc = dt.toUTC();
+ QDate date = utc.date();
+ QTime time = utc.time();
+ JSC::GregorianDateTime tm;
+ tm.year = date.year() - 1900;
+ tm.month = date.month() - 1;
+ tm.monthDay = date.day();
+ tm.weekDay = date.dayOfWeek();
+ tm.yearDay = date.dayOfYear();
+ tm.hour = time.hour();
+ tm.minute = time.minute();
+ tm.second = time.second();
+ return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true);
+}
+
+void GlobalClientData::mark(JSC::MarkStack& markStack)
+{
+ engine->mark(markStack);
+}
+
+class TimeoutCheckerProxy : public JSC::TimeoutChecker
+{
+public:
+ TimeoutCheckerProxy(const JSC::TimeoutChecker& originalChecker)
+ : JSC::TimeoutChecker(originalChecker)
+ , m_shouldProcessEvents(false)
+ , m_shouldAbortEvaluation(false)
+ {}
+
+ void setShouldProcessEvents(bool shouldProcess) { m_shouldProcessEvents = shouldProcess; }
+ void setShouldAbort(bool shouldAbort) { m_shouldAbortEvaluation = shouldAbort; }
+ bool shouldAbort() { return m_shouldAbortEvaluation; }
+
+ virtual bool didTimeOut(JSC::ExecState* exec)
+ {
+ if (JSC::TimeoutChecker::didTimeOut(exec))
+ return true;
+
+ if (m_shouldProcessEvents)
+ QCoreApplication::processEvents();
+
+ return m_shouldAbortEvaluation;
+ }
+
+private:
+ bool m_shouldProcessEvents;
+ bool m_shouldAbortEvaluation;
+};
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+qsreal integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ qsreal sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ qsreal result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ qsreal multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+qsreal integerFromString(const QString &str, int radix)
+{
+ QByteArray ba = str.trimmed().toUtf8();
+ return integerFromString(ba.constData(), ba.size(), radix);
+}
+
+bool isFunction(JSC::JSValue value)
+{
+ if (!value || !value.isObject())
+ return false;
+ JSC::CallData callData;
+ return (JSC::asObject(value)->getCallData(callData) != JSC::CallTypeNone);
+}
+
+static JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+
+JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
+{
+#ifndef QT_NO_QOBJECT
+ if (args.size() == 0) {
+ return JSC::throwError(exec, JSC::GeneralError, "Function.prototype.disconnect: no arguments given");
+ }
+
+ if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: this object is not a signal");
+ }
+
+ QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
+
+ const QMetaObject *meta = qtSignal->metaObject();
+ if (!meta) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.discconnect: cannot disconnect from deleted QObject");
+ }
+
+ QMetaMethod sig = meta->method(qtSignal->initialIndex());
+ if (sig.methodType() != QMetaMethod::Signal) {
+ QString message = QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal")
+ .arg(QLatin1String(qtSignal->metaObject()->className()))
+ .arg(QLatin1String(sig.signature()));
+ return JSC::throwError(exec, JSC::TypeError, message);
+ }
+
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+
+ JSC::JSValue receiver;
+ JSC::JSValue slot;
+ JSC::JSValue arg0 = args.at(0);
+ if (args.size() < 2) {
+ slot = arg0;
+ } else {
+ receiver = arg0;
+ JSC::JSValue arg1 = args.at(1);
+ if (isFunction(arg1))
+ slot = arg1;
+ else {
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1);
+ slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype);
+ }
+ }
+
+ if (!isFunction(slot)) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: target is not a function");
+ }
+
+ bool ok = engine->scriptDisconnect(thisObject, receiver, slot);
+ if (!ok) {
+ QString message = QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1")
+ .arg(QLatin1String(qtSignal->metaObject()->className()))
+ .arg(QLatin1String(sig.signature()));
+ return JSC::throwError(exec, JSC::GeneralError, message);
+ }
+ return JSC::jsUndefined();
+#else
+ Q_UNUSED(eng);
+ return context->throwError(QScriptContext::TypeError,
+ QLatin1String("Function.prototype.disconnect"));
+#endif // QT_NO_QOBJECT
+}
+
+JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
+{
+#ifndef QT_NO_QOBJECT
+ if (args.size() == 0) {
+ return JSC::throwError(exec, JSC::GeneralError,"Function.prototype.connect: no arguments given");
+ }
+
+ if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: this object is not a signal");
+ }
+
+ QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
+
+ const QMetaObject *meta = qtSignal->metaObject();
+ if (!meta) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: cannot connect to deleted QObject");
+ }
+
+ QMetaMethod sig = meta->method(qtSignal->initialIndex());
+ if (sig.methodType() != QMetaMethod::Signal) {
+ QString message = QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal")
+ .arg(QLatin1String(qtSignal->metaObject()->className()))
+ .arg(QLatin1String(sig.signature()));
+ return JSC::throwError(exec, JSC::TypeError, message);
+ }
+
+ {
+ QList<int> overloads = qtSignal->overloadedIndexes();
+ if (!overloads.isEmpty()) {
+ overloads.append(qtSignal->initialIndex());
+ QByteArray signature = sig.signature();
+ QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n")
+ .arg(QLatin1String(qtSignal->metaObject()->className()))
+ .arg(QLatin1String(signature.left(signature.indexOf('('))));
+ for (int i = 0; i < overloads.size(); ++i) {
+ QMetaMethod mtd = meta->method(overloads.at(i));
+ message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature())));
+ }
+ message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload")
+ .arg(QLatin1String(signature)));
+ return JSC::throwError(exec, JSC::GeneralError, message);
+ }
+ }
+
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+
+ JSC::JSValue receiver;
+ JSC::JSValue slot;
+ JSC::JSValue arg0 = args.at(0);
+ if (args.size() < 2) {
+ slot = arg0;
+ } else {
+ receiver = arg0;
+ JSC::JSValue arg1 = args.at(1);
+ if (isFunction(arg1))
+ slot = arg1;
+ else {
+ QScript::SaveFrameHelper saveFrame(engine, exec);
+ JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1);
+ slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype);
+ }
+ }
+
+ if (!isFunction(slot)) {
+ return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: target is not a function");
+ }
+
+ bool ok = engine->scriptConnect(thisObject, receiver, slot, Qt::AutoConnection);
+ if (!ok) {
+ QString message = QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1")
+ .arg(QLatin1String(qtSignal->metaObject()->className()))
+ .arg(QLatin1String(sig.signature()));
+ return JSC::throwError(exec, JSC::GeneralError, message);
+ }
+ return JSC::jsUndefined();
+#else
+ Q_UNUSED(eng);
+ Q_UNUSED(classInfo);
+ return context->throwError(QScriptContext::TypeError,
+ QLatin1String("Function.prototype.connect"));
+#endif // QT_NO_QOBJECT
+}
+
+static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+
+JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList& args)
+{
+ QString result;
+ for (unsigned i = 0; i < args.size(); ++i) {
+ if (i != 0)
+ result.append(QLatin1Char(' '));
+ QString s(args.at(i).toString(exec));
+ if (exec->hadException())
+ break;
+ result.append(s);
+ }
+ if (exec->hadException())
+ return exec->exception();
+ qDebug("%s", qPrintable(result));
+ return JSC::jsUndefined();
+}
+
+JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ engine->collectGarbage();
+ return JSC::jsUndefined();
+}
+
+JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
+{
+ return JSC::JSValue(exec, 1);
+}
+
+#ifndef QT_NO_TRANSLATION
+
+static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+static JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+
+JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 2)
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
+ if (!args.at(0).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): first argument (context) must be a string");
+ if (!args.at(1).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): second argument (text) must be a string");
+ if ((args.size() > 2) && !args.at(2).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (comment) must be a string");
+ if ((args.size() > 3) && !args.at(3).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fourth argument (encoding) must be a string");
+ if ((args.size() > 4) && !args.at(4).isNumber())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number");
+#ifndef QT_NO_QOBJECT
+ JSC::UString context = args.at(0).toString(exec);
+#endif
+ JSC::UString text = args.at(1).toString(exec);
+#ifndef QT_NO_QOBJECT
+ JSC::UString comment;
+ if (args.size() > 2)
+ comment = args.at(2).toString(exec);
+ QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8;
+ if (args.size() > 3) {
+ JSC::UString encStr = args.at(3).toString(exec);
+ if (encStr == "CodecForTr")
+ encoding = QCoreApplication::CodecForTr;
+ else if (encStr == "UnicodeUTF8")
+ encoding = QCoreApplication::UnicodeUTF8;
+ else
+ return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr));
+ }
+ int n = -1;
+ if (args.size() > 4)
+ n = args.at(4).toInt32(exec);
+#endif
+ JSC::UString result;
+#ifndef QT_NO_QOBJECT
+ result = QCoreApplication::translate(context.UTF8String().c_str(),
+ text.UTF8String().c_str(),
+ comment.UTF8String().c_str(),
+ encoding, n);
+#else
+ result = text;
+#endif
+ return JSC::jsString(exec, result);
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 2)
+ return JSC::jsUndefined();
+ return args.at(1);
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::throwError(exec, JSC::GeneralError, "qsTr() requires at least one argument");
+ if (!args.at(0).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTr(): first argument (text) must be a string");
+ if ((args.size() > 1) && !args.at(1).isString())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string");
+ if ((args.size() > 2) && !args.at(2).isNumber())
+ return JSC::throwError(exec, JSC::GeneralError, "qsTr(): third argument (n) must be a number");
+#ifndef QT_NO_QOBJECT
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ JSC::UString context;
+ // The first non-empty source URL in the call stack determines the translation context.
+ {
+ JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag();
+ while (frame) {
+ if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)
+ && frame->codeBlock()->source()
+ && !frame->codeBlock()->source()->url().isEmpty()) {
+ context = engine->translationContextFromUrl(frame->codeBlock()->source()->url());
+ break;
+ }
+ frame = frame->callerFrame()->removeHostCallFrameFlag();
+ }
+ }
+#endif
+ JSC::UString text = args.at(0).toString(exec);
+#ifndef QT_NO_QOBJECT
+ JSC::UString comment;
+ if (args.size() > 1)
+ comment = args.at(1).toString(exec);
+ int n = -1;
+ if (args.size() > 2)
+ n = args.at(2).toInt32(exec);
+#endif
+ JSC::UString result;
+#ifndef QT_NO_QOBJECT
+ result = QCoreApplication::translate(context.UTF8String().c_str(),
+ text.UTF8String().c_str(),
+ comment.UTF8String().c_str(),
+ QCoreApplication::UnicodeUTF8, n);
+#else
+ result = text;
+#endif
+ return JSC::jsString(exec, result);
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::jsUndefined();
+ return args.at(0);
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::throwError(exec, JSC::GeneralError, "qsTrId() requires at least one argument");
+ if (!args.at(0).isString())
+ return JSC::throwError(exec, JSC::TypeError, "qsTrId(): first argument (id) must be a string");
+ if ((args.size() > 1) && !args.at(1).isNumber())
+ return JSC::throwError(exec, JSC::TypeError, "qsTrId(): second argument (n) must be a number");
+ JSC::UString id = args.at(0).toString(exec);
+ int n = -1;
+ if (args.size() > 1)
+ n = args.at(1).toInt32(exec);
+ return JSC::jsString(exec, qtTrId(id.UTF8String().c_str(), n));
+}
+
+JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
+{
+ if (args.size() < 1)
+ return JSC::jsUndefined();
+ return args.at(0);
+}
+#endif // QT_NO_TRANSLATION
+
+static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
+
+JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
+{
+ QString value(thisObject.toString(exec));
+ JSC::JSValue arg = (args.size() != 0) ? args.at(0) : JSC::jsUndefined();
+ QString result;
+ if (arg.isString())
+ result = value.arg(arg.toString(exec));
+ else if (arg.isNumber())
+ result = value.arg(arg.toNumber(exec));
+ return JSC::jsString(exec, result);
+}
+
+
+#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY)
+static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng)
+{
+ QString path = ctx->argument(0).toString();
+ QStringList components = path.split(QLatin1Char('.'));
+ QScriptValue o = eng->globalObject();
+ for (int i = 0; i < components.count(); ++i) {
+ QString name = components.at(i);
+ QScriptValue oo = o.property(name);
+ if (!oo.isValid()) {
+ oo = eng->newObject();
+ o.setProperty(name, oo);
+ }
+ o = oo;
+ }
+ return o;
+}
+#endif
+
+} // namespace QScript
+
+QScriptEnginePrivate::QScriptEnginePrivate()
+ : originalGlobalObjectProxy(0), currentFrame(0),
+ qobjectPrototype(0), qmetaobjectPrototype(0), variantPrototype(0),
+ activeAgent(0), agentLineNumber(-1),
+ registeredScriptValues(0), freeScriptValues(0), freeScriptValuesCount(0),
+ registeredScriptStrings(0), processEventsInterval(-1), inEval(false)
+{
+ qMetaTypeId<QScriptValue>();
+ qMetaTypeId<QList<int> >();
+#ifndef QT_NO_QOBJECT
+ qMetaTypeId<QObjectList>();
+#endif
+
+ if (!QCoreApplication::instance()) {
+ qFatal("QScriptEngine: Must construct a Q(Core)Application before a QScriptEngine");
+ return;
+ }
+ JSC::initializeThreading();
+ JSC::IdentifierTable *oldTable = JSC::currentIdentifierTable();
+ globalData = JSC::JSGlobalData::create().releaseRef();
+ globalData->clientData = new QScript::GlobalClientData(this);
+ JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
+
+ JSC::ExecState* exec = globalObject->globalExec();
+
+ scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
+ staticScopeObjectStructure = QScriptStaticScopeObject::createStructure(JSC::jsNull());
+
+ qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
+
+ qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ qmetaobjectWrapperObjectStructure = QScript::QMetaObjectWrapperObject::createStructure(qmetaobjectPrototype);
+
+ variantPrototype = new (exec) QScript::QVariantPrototype(exec, QScript::QVariantPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
+ variantWrapperObjectStructure = QScriptObject::createStructure(variantPrototype);
+
+ globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "print"), QScript::functionPrint));
+ globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "gc"), QScript::functionGC));
+ globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "version"), QScript::functionVersion));
+
+ // ### rather than extending Function.prototype, consider creating a QtSignal.prototype
+ globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "disconnect"), QScript::functionDisconnect));
+ globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "connect"), QScript::functionConnect));
+
+ JSC::TimeoutChecker* originalChecker = globalData->timeoutChecker;
+ globalData->timeoutChecker = new QScript::TimeoutCheckerProxy(*originalChecker);
+ delete originalChecker;
+
+ currentFrame = exec;
+
+ cachedTranslationUrl = JSC::UString();
+ cachedTranslationContext = JSC::UString();
+ JSC::setCurrentIdentifierTable(oldTable);
+}
+
+QScriptEnginePrivate::~QScriptEnginePrivate()
+{
+ QScript::APIShim shim(this);
+
+ //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
+ QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
+ for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it)
+ it.value()->disconnectFromEngine();
+
+ while (!ownedAgents.isEmpty())
+ delete ownedAgents.takeFirst();
+
+ detachAllRegisteredScriptPrograms();
+ detachAllRegisteredScriptValues();
+ detachAllRegisteredScriptStrings();
+ qDeleteAll(m_qobjectData);
+ qDeleteAll(m_typeInfos);
+ globalData->heap.destroy();
+ globalData->deref();
+ while (freeScriptValues) {
+ QScriptValuePrivate *p = freeScriptValues;
+ freeScriptValues = p->next;
+ qFree(p);
+ }
+}
+
+QVariant QScriptEnginePrivate::jscValueToVariant(JSC::ExecState *exec, JSC::JSValue value, int targetType)
+{
+ QVariant v(targetType, (void *)0);
+ if (convertValue(exec, value, targetType, v.data()))
+ return v;
+ if (uint(targetType) == QVariant::LastType)
+ return toVariant(exec, value);
+ if (isVariant(value)) {
+ v = variantValue(value);
+ if (v.canConvert(QVariant::Type(targetType))) {
+ v.convert(QVariant::Type(targetType));
+ return v;
+ }
+ QByteArray typeName = v.typeName();
+ if (typeName.endsWith('*')
+ && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) {
+ return QVariant(targetType, *reinterpret_cast<void* *>(v.data()));
+ }
+ }
+ return QVariant();
+}
+
+JSC::JSValue QScriptEnginePrivate::arrayFromStringList(JSC::ExecState *exec, const QStringList &lst)
+{
+ JSC::JSValue arr = newArray(exec, lst.size());
+ for (int i = 0; i < lst.size(); ++i)
+ setProperty(exec, arr, i, JSC::jsString(exec, lst.at(i)));
+ return arr;
+}
+
+QStringList QScriptEnginePrivate::stringListFromArray(JSC::ExecState *exec, JSC::JSValue arr)
+{
+ QStringList lst;
+ uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
+ for (uint i = 0; i < len; ++i)
+ lst.append(toString(exec, property(exec, arr, i)));
+ return lst;
+}
+
+JSC::JSValue QScriptEnginePrivate::arrayFromVariantList(JSC::ExecState *exec, const QVariantList &lst)
+{
+ JSC::JSValue arr = newArray(exec, lst.size());
+ for (int i = 0; i < lst.size(); ++i)
+ setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i)));
+ return arr;
+}
+
+QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSArray *arr)
+{
+ QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
+ if (eng->visitedConversionObjects.contains(arr))
+ return QVariantList(); // Avoid recursion.
+ eng->visitedConversionObjects.insert(arr);
+ QVariantList lst;
+ uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
+ for (uint i = 0; i < len; ++i)
+ lst.append(toVariant(exec, property(exec, arr, i)));
+ eng->visitedConversionObjects.remove(arr);
+ return lst;
+}
+
+JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap)
+{
+ JSC::JSValue obj = JSC::constructEmptyObject(exec);
+ QVariantMap::const_iterator it;
+ for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
+ setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value()));
+ return obj;
+}
+
+QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSObject *obj)
+{
+ QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
+ if (eng->visitedConversionObjects.contains(obj))
+ return QVariantMap(); // Avoid recursion.
+ eng->visitedConversionObjects.insert(obj);
+ JSC::PropertyNameArray propertyNames(exec);
+ obj->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties);
+ QVariantMap vmap;
+ JSC::PropertyNameArray::const_iterator it = propertyNames.begin();
+ for( ; it != propertyNames.end(); ++it)
+ vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it)));
+ eng->visitedConversionObjects.remove(obj);
+ return vmap;
+}
+
+JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
+{
+ QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
+ if (!info)
+ return JSC::JSValue();
+ return info->prototype;
+}
+
+void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prototype)
+{
+ QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
+ if (!info) {
+ info = new QScriptTypeInfo();
+ m_typeInfos.insert(metaTypeId, info);
+ }
+ info->prototype = prototype;
+}
+
+JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const
+{
+ return globalData->head;
+}
+
+JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const
+{
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ return glob->customGlobalObject;
+}
+
+JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy()
+{
+ if (!originalGlobalObjectProxy) {
+ JSC::ExecState* exec = currentFrame;
+ originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ }
+ return originalGlobalObjectProxy;
+}
+
+JSC::JSObject *QScriptEnginePrivate::globalObject() const
+{
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ if (glob->customGlobalObject)
+ return glob->customGlobalObject;
+ return glob;
+}
+
+void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object)
+{
+ if (object == globalObject())
+ return;
+ QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
+ if (object == originalGlobalObjectProxy) {
+ glob->customGlobalObject = 0;
+ // Sync the internal prototype, since JSObject::prototype() is not virtual.
+ glob->setPrototype(originalGlobalObjectProxy->prototype());
+ } else {
+ Q_ASSERT(object != originalGlobalObject());
+ glob->customGlobalObject = object;
+ // Sync the internal prototype, since JSObject::prototype() is not virtual.
+ glob->setPrototype(object->prototype());
+ }
+}
+
+/*!
+ \internal
+
+ If the given \a value is the original global object, returns the custom
+ global object or a proxy to the original global object; otherwise returns \a
+ value.
+*/
+JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value)
+{
+ if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject())
+ return value;
+ Q_ASSERT(JSC::asObject(value) == originalGlobalObject());
+ if (customGlobalObject())
+ return customGlobalObject();
+ if (!originalGlobalObjectProxy)
+ originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
+ return originalGlobalObjectProxy;
+}
+/*!
+ \internal
+ Return the 'this' value for a given context
+*/
+JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame)
+{
+ if (frame->codeBlock() != 0) {
+ return frame->thisValue();
+ } else if(frame == frame->lexicalGlobalObject()->globalExec()) {
+ return frame->globalThisValue();
+ } else {
+ JSC::Register *thisRegister = thisRegisterForFrame(frame);
+ return thisRegister->jsValue();
+ }
+}
+
+JSC::Register* QScriptEnginePrivate::thisRegisterForFrame(JSC::ExecState *frame)
+{
+ Q_ASSERT(frame->codeBlock() == 0); // only for native calls
+ return frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount();
+}
+
+/*! \internal
+ For native context, we use the ReturnValueRegister entry in the stackframe header to store flags.
+ We can do that because this header is not used as the native function return their value thought C++
+
+ when setting flags, NativeContext should always be set
+
+ contextFlags returns 0 for non native context
+ */
+uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec)
+{
+ if (exec->codeBlock())
+ return 0; //js function doesn't have flags
+
+ return exec->returnValueRegister();
+}
+
+void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags)
+{
+ Q_ASSERT(!exec->codeBlock());
+ exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::Register::withInt(flags);
+}
+
+
+void QScriptEnginePrivate::mark(JSC::MarkStack& markStack)
+{
+ Q_Q(QScriptEngine);
+
+ if (originalGlobalObject()) {
+ markStack.append(originalGlobalObject());
+ markStack.append(globalObject());
+ if (originalGlobalObjectProxy)
+ markStack.append(originalGlobalObjectProxy);
+ }
+
+ if (qobjectPrototype)
+ markStack.append(qobjectPrototype);
+ if (qmetaobjectPrototype)
+ markStack.append(qmetaobjectPrototype);
+ if (variantPrototype)
+ markStack.append(variantPrototype);
+
+ {
+ QScriptValuePrivate *it;
+ for (it = registeredScriptValues; it != 0; it = it->next) {
+ if (it->isJSC())
+ markStack.append(it->jscValue);
+ }
+ }
+
+ {
+ QHash<int, QScriptTypeInfo*>::const_iterator it;
+ for (it = m_typeInfos.constBegin(); it != m_typeInfos.constEnd(); ++it) {
+ if ((*it)->prototype)
+ markStack.append((*it)->prototype);
+ }
+ }
+
+ if (q) {
+ QScriptContext *context = q->currentContext();
+
+ while (context) {
+ JSC::ScopeChainNode *node = frameForContext(context)->scopeChain();
+ JSC::ScopeChainIterator it(node);
+ for (it = node->begin(); it != node->end(); ++it) {
+ JSC::JSObject *object = *it;
+ if (object)
+ markStack.append(object);
+ }
+
+ context = context->parentContext();
+ }
+ }
+
+#ifndef QT_NO_QOBJECT
+ markStack.drain(); // make sure everything is marked before marking qobject data
+ {
+ QHash<QObject*, QScript::QObjectData*>::const_iterator it;
+ for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) {
+ QScript::QObjectData *qdata = it.value();
+ qdata->mark(markStack);
+ }
+ }
+#endif
+}
+
+bool QScriptEnginePrivate::isCollecting() const
+{
+ return globalData->heap.isBusy();
+}
+
+void QScriptEnginePrivate::collectGarbage()
+{
+ QScript::APIShim shim(this);
+ globalData->heap.collectAllGarbage();
+}
+
+void QScriptEnginePrivate::reportAdditionalMemoryCost(int size)
+{
+ if (size > 0)
+ globalData->heap.reportExtraMemoryCost(size);
+}
+
+QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const
+{
+ return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker);
+}
+
+void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
+{
+ ownedAgents.removeOne(agent);
+ if (activeAgent == agent) {
+ QScriptEngineAgentPrivate::get(agent)->detach();
+ activeAgent = 0;
+ }
+}
+
+JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
+ JSC::EvalExecutable *executable,
+ bool &compile)
+{
+ Q_Q(QScriptEngine);
+ QBoolBlocker inEvalBlocker(inEval, true);
+ q->currentContext()->activationObject(); //force the creation of a context for native function;
+
+ JSC::Debugger* debugger = originalGlobalObject()->debugger();
+ if (debugger)
+ debugger->evaluateStart(sourceId);
+
+ q->clearExceptions();
+ JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject);
+
+ if (compile) {
+ JSC::JSObject* error = executable->compile(exec, exec->scopeChain());
+ if (error) {
+ compile = false;
+ exec->setException(error);
+
+ if (debugger) {
+ debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, error), sourceId, false);
+ debugger->evaluateStop(error, sourceId);
+ }
+
+ return error;
+ }
+ }
+
+ JSC::JSValue thisValue = thisForContext(exec);
+ JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull())
+ ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
+ JSC::JSValue exceptionValue;
+ timeoutChecker()->setShouldAbort(false);
+ if (processEventsInterval > 0)
+ timeoutChecker()->reset();
+
+ JSC::JSValue result = exec->interpreter()->execute(executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
+
+ if (timeoutChecker()->shouldAbort()) {
+ if (abortResult.isError())
+ exec->setException(scriptValueToJSCValue(abortResult));
+
+ if (debugger)
+ debugger->evaluateStop(scriptValueToJSCValue(abortResult), sourceId);
+
+ return scriptValueToJSCValue(abortResult);
+ }
+
+ if (exceptionValue) {
+ exec->setException(exceptionValue);
+
+ if (debugger)
+ debugger->evaluateStop(exceptionValue, sourceId);
+
+ return exceptionValue;
+ }
+
+ if (debugger)
+ debugger->evaluateStop(result, sourceId);
+
+ Q_ASSERT(!exec->hadException());
+ return result;
+}
+
+#ifndef QT_NO_QOBJECT
+
+JSC::JSValue QScriptEnginePrivate::newQObject(
+ QObject *object, QScriptEngine::ValueOwnership ownership,
+ const QScriptEngine::QObjectWrapOptions &options)
+{
+ if (!object)
+ return JSC::jsNull();
+ JSC::ExecState* exec = currentFrame;
+ QScript::QObjectData *data = qobjectData(object);
+ bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0;
+ QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject;
+ QScriptObject *result = 0;
+ if (preferExisting) {
+ result = data->findWrapper(ownership, opt);
+ if (result)
+ return result;
+ }
+ result = new (exec) QScriptObject(qobjectWrapperObjectStructure);
+ if (preferExisting)
+ data->registerWrapper(result, ownership, opt);
+ result->setDelegate(new QScript::QObjectDelegate(object, ownership, options));
+ /*if (setDefaultPrototype)*/ {
+ const QMetaObject *meta = object->metaObject();
+ while (meta) {
+ QByteArray typeString = meta->className();
+ typeString.append('*');
+ int typeId = QMetaType::type(typeString);
+ if (typeId != 0) {
+ JSC::JSValue proto = defaultPrototype(typeId);
+ if (proto) {
+ result->setPrototype(proto);
+ break;
+ }
+ }
+ meta = meta->superClass();
+ }
+ }
+ return result;
+}
+
+JSC::JSValue QScriptEnginePrivate::newQMetaObject(
+ const QMetaObject *metaObject, JSC::JSValue ctor)
+{
+ if (!metaObject)
+ return JSC::jsNull();
+ JSC::ExecState* exec = currentFrame;
+ QScript::QMetaObjectWrapperObject *result = new (exec) QScript::QMetaObjectWrapperObject(exec, metaObject, ctor, qmetaobjectWrapperObjectStructure);
+ return result;
+}
+
+bool QScriptEnginePrivate::convertToNativeQObject(JSC::ExecState *exec, JSC::JSValue value,
+ const QByteArray &targetType,
+ void **result)
+{
+ if (!targetType.endsWith('*'))
+ return false;
+ if (QObject *qobject = toQObject(exec, value)) {
+ int start = targetType.startsWith("const ") ? 6 : 0;
+ QByteArray className = targetType.mid(start, targetType.size()-start-1);
+ if (void *instance = qobject->qt_metacast(className)) {
+ *result = instance;
+ return true;
+ }
+ }
+ return false;
+}
+
+QScript::QObjectData *QScriptEnginePrivate::qobjectData(QObject *object)
+{
+ QHash<QObject*, QScript::QObjectData*>::const_iterator it;
+ it = m_qobjectData.constFind(object);
+ if (it != m_qobjectData.constEnd())
+ return it.value();
+
+ QScript::QObjectData *data = new QScript::QObjectData(this);
+ m_qobjectData.insert(object, data);
+ QObject::connect(object, SIGNAL(destroyed(QObject*)),
+ q_func(), SLOT(_q_objectDestroyed(QObject*)));
+ return data;
+}
+
+void QScriptEnginePrivate::_q_objectDestroyed(QObject *object)
+{
+ QHash<QObject*, QScript::QObjectData*>::iterator it;
+ it = m_qobjectData.find(object);
+ Q_ASSERT(it != m_qobjectData.end());
+ QScript::QObjectData *data = it.value();
+ m_qobjectData.erase(it);
+ delete data;
+}
+
+void QScriptEnginePrivate::disposeQObject(QObject *object)
+{
+ // TODO
+/* if (isCollecting()) {
+ // wait until we're done with GC before deleting it
+ int index = m_qobjectsToBeDeleted.indexOf(object);
+ if (index == -1)
+ m_qobjectsToBeDeleted.append(object);
+ } else*/ {
+ delete object;
+ }
+}
+
+void QScriptEnginePrivate::emitSignalHandlerException()
+{
+ Q_Q(QScriptEngine);
+ emit q->signalHandlerException(q->uncaughtException());
+}
+
+bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal,
+ JSC::JSValue receiver, JSC::JSValue function,
+ Qt::ConnectionType type)
+{
+ Q_ASSERT(sender);
+ Q_ASSERT(signal);
+ const QMetaObject *meta = sender->metaObject();
+ int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
+ if (index == -1)
+ return false;
+ return scriptConnect(sender, index, receiver, function, /*wrapper=*/JSC::JSValue(), type);
+}
+
+bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal,
+ JSC::JSValue receiver, JSC::JSValue function)
+{
+ Q_ASSERT(sender);
+ Q_ASSERT(signal);
+ const QMetaObject *meta = sender->metaObject();
+ int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
+ if (index == -1)
+ return false;
+ return scriptDisconnect(sender, index, receiver, function);
+}
+
+bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex,
+ JSC::JSValue receiver, JSC::JSValue function,
+ JSC::JSValue senderWrapper,
+ Qt::ConnectionType type)
+{
+ QScript::QObjectData *data = qobjectData(sender);
+ return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type);
+}
+
+bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex,
+ JSC::JSValue receiver, JSC::JSValue function)
+{
+ QScript::QObjectData *data = qobjectData(sender);
+ if (!data)
+ return false;
+ return data->removeSignalHandler(sender, signalIndex, receiver, function);
+}
+
+bool QScriptEnginePrivate::scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
+ JSC::JSValue function, Qt::ConnectionType type)
+{
+ QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
+ int index = fun->mostGeneralMethod();
+ return scriptConnect(fun->qobject(), index, receiver, function, fun->wrapperObject(), type);
+}
+
+bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
+ JSC::JSValue function)
+{
+ QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
+ int index = fun->mostGeneralMethod();
+ return scriptDisconnect(fun->qobject(), index, receiver, function);
+}
+
+#endif
+
+void QScriptEnginePrivate::detachAllRegisteredScriptPrograms()
+{
+ QSet<QScriptProgramPrivate*>::const_iterator it;
+ for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it)
+ (*it)->detachFromEngine();
+ registeredScriptPrograms.clear();
+}
+
+void QScriptEnginePrivate::detachAllRegisteredScriptValues()
+{
+ QScriptValuePrivate *it;
+ QScriptValuePrivate *next;
+ for (it = registeredScriptValues; it != 0; it = next) {
+ it->detachFromEngine();
+ next = it->next;
+ it->prev = 0;
+ it->next = 0;
+ }
+ registeredScriptValues = 0;
+}
+
+void QScriptEnginePrivate::detachAllRegisteredScriptStrings()
+{
+ QScriptStringPrivate *it;
+ QScriptStringPrivate *next;
+ for (it = registeredScriptStrings; it != 0; it = next) {
+ it->detachFromEngine();
+ next = it->next;
+ it->prev = 0;
+ it->next = 0;
+ }
+ registeredScriptStrings = 0;
+}
+
+#ifndef QT_NO_REGEXP
+
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp &regexp)
+{
+ JSC::JSValue buf[2];
+ JSC::ArgList args(buf, sizeof(buf));
+
+ //convert the pattern to a ECMAScript pattern
+ QString pattern = qt_regexp_toCanonical(regexp.pattern(), regexp.patternSyntax());
+ if (regexp.isMinimal()) {
+ QString ecmaPattern;
+ int len = pattern.length();
+ ecmaPattern.reserve(len);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+ bool inBracket = false;
+ while (i < len) {
+ QChar c = wc[i++];
+ ecmaPattern += c;
+ switch (c.unicode()) {
+ case '?':
+ case '+':
+ case '*':
+ case '}':
+ if (!inBracket)
+ ecmaPattern += QLatin1Char('?');
+ break;
+ case '\\':
+ if (i < len)
+ ecmaPattern += wc[i++];
+ break;
+ case '[':
+ inBracket = true;
+ break;
+ case ']':
+ inBracket = false;
+ break;
+ default:
+ break;
+ }
+ }
+ pattern = ecmaPattern;
+ }
+
+ JSC::UString jscPattern = pattern;
+ QString flags;
+ if (regexp.caseSensitivity() == Qt::CaseInsensitive)
+ flags.append(QLatin1Char('i'));
+ JSC::UString jscFlags = flags;
+ buf[0] = JSC::jsString(exec, jscPattern);
+ buf[1] = JSC::jsString(exec, jscFlags);
+ return JSC::constructRegExp(exec, args);
+}
+
+#endif
+
+JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QString &pattern, const QString &flags)
+{
+ JSC::JSValue buf[2];
+ JSC::ArgList args(buf, sizeof(buf));
+ JSC::UString jscPattern = pattern;
+ QString strippedFlags;
+ if (flags.contains(QLatin1Char('i')))
+ strippedFlags += QLatin1Char('i');
+ if (flags.contains(QLatin1Char('m')))
+ strippedFlags += QLatin1Char('m');
+ if (flags.contains(QLatin1Char('g')))
+ strippedFlags += QLatin1Char('g');
+ JSC::UString jscFlags = strippedFlags;
+ buf[0] = JSC::jsString(exec, jscPattern);
+ buf[1] = JSC::jsString(exec, jscFlags);
+ return JSC::constructRegExp(exec, args);
+}
+
+JSC::JSValue QScriptEnginePrivate::newVariant(const QVariant &value)
+{
+ QScriptObject *obj = new (currentFrame) QScriptObject(variantWrapperObjectStructure);
+ obj->setDelegate(new QScript::QVariantDelegate(value));
+ JSC::JSValue proto = defaultPrototype(value.userType());
+ if (proto)
+ obj->setPrototype(proto);
+ return obj;
+}
+
+JSC::JSValue QScriptEnginePrivate::newVariant(JSC::JSValue objectValue,
+ const QVariant &value)
+{
+ if (!isObject(objectValue))
+ return newVariant(value);
+ JSC::JSObject *jscObject = JSC::asObject(objectValue);
+ if (!jscObject->inherits(&QScriptObject::info)) {
+ qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
+ return JSC::JSValue();
+ }
+ QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
+ if (!isVariant(objectValue)) {
+ jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
+ } else {
+ setVariantValue(objectValue, value);
+ }
+ return objectValue;
+}
+
+#ifndef QT_NO_REGEXP
+
+QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value)
+{
+ if (!isRegExp(value))
+ return QRegExp();
+ QString pattern = toString(exec, property(exec, value, "source", QScriptValue::ResolvePrototype));
+ Qt::CaseSensitivity kase = Qt::CaseSensitive;
+ if (toBool(exec, property(exec, value, "ignoreCase", QScriptValue::ResolvePrototype)))
+ kase = Qt::CaseInsensitive;
+ return QRegExp(pattern, kase, QRegExp::RegExp2);
+}
+
+#endif
+
+QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue value)
+{
+ if (!value) {
+ return QVariant();
+ } else if (isObject(value)) {
+ if (isVariant(value))
+ return variantValue(value);
+#ifndef QT_NO_QOBJECT
+ else if (isQObject(value))
+ return QVariant::fromValue(toQObject(exec, value));
+#endif
+ else if (isDate(value))
+ return QVariant(toDateTime(exec, value));
+#ifndef QT_NO_REGEXP
+ else if (isRegExp(value))
+ return QVariant(toRegExp(exec, value));
+#endif
+ else if (isArray(value))
+ return variantListFromArray(exec, JSC::asArray(value));
+ else if (QScriptDeclarativeClass *dc = declarativeClass(value))
+ return dc->toVariant(declarativeObject(value));
+ return variantMapFromObject(exec, JSC::asObject(value));
+ } else if (value.isInt32()) {
+ return QVariant(toInt32(exec, value));
+ } else if (value.isDouble()) {
+ return QVariant(toNumber(exec, value));
+ } else if (value.isString()) {
+ return QVariant(toString(exec, value));
+ } else if (value.isBoolean()) {
+ return QVariant(toBool(exec, value));
+ }
+ return QVariant();
+}
+
+JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode)
+{
+ JSC::JSValue result;
+ if (!(resolveMode & QScriptValue::ResolvePrototype)) {
+ // Look in the object's own properties
+ JSC::JSObject *object = JSC::asObject(value);
+ JSC::PropertySlot slot(object);
+ if (object->getOwnPropertySlot(exec, id, slot))
+ result = slot.getValue(exec, id);
+ }
+ if (!result && (resolveMode & QScriptValue::ResolveScope)) {
+ // ### check if it's a function object and look in the scope chain
+ JSC::JSValue scope = property(exec, value, "__qt_scope__", QScriptValue::ResolveLocal);
+ if (isObject(scope))
+ result = property(exec, scope, id, resolveMode);
+ }
+ return result;
+}
+
+JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, quint32 index, int resolveMode)
+{
+ JSC::JSValue result;
+ if (!(resolveMode & QScriptValue::ResolvePrototype)) {
+ // Look in the object's own properties
+ JSC::JSObject *object = JSC::asObject(value);
+ JSC::PropertySlot slot(object);
+ if (object->getOwnPropertySlot(exec, index, slot))
+ result = slot.getValue(exec, index);
+ }
+ return result;
+}
+
+void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, const JSC::Identifier &id,
+ JSC::JSValue value, const QScriptValue::PropertyFlags &flags)
+{
+ JSC::JSObject *thisObject = JSC::asObject(objectValue);
+ JSC::JSValue setter = thisObject->lookupSetter(exec, id);
+ JSC::JSValue getter = thisObject->lookupGetter(exec, id);
+ if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
+ if (!value) {
+ // deleting getter/setter
+ if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) {
+ // deleting both: just delete the property
+ thisObject->deleteProperty(exec, id);
+ } else if (flags & QScriptValue::PropertyGetter) {
+ // preserve setter, if there is one
+ thisObject->deleteProperty(exec, id);
+ if (setter && setter.isObject())
+ thisObject->defineSetter(exec, id, JSC::asObject(setter));
+ } else { // flags & QScriptValue::PropertySetter
+ // preserve getter, if there is one
+ thisObject->deleteProperty(exec, id);
+ if (getter && getter.isObject())
+ thisObject->defineGetter(exec, id, JSC::asObject(getter));
+ }
+ } else {
+ if (value.isObject()) { // ### should check if it has callData()
+ // defining getter/setter
+ if (id == exec->propertyNames().underscoreProto) {
+ qWarning("QScriptValue::setProperty() failed: "
+ "cannot set getter or setter of native property `__proto__'");
+ } else {
+ if (flags & QScriptValue::PropertyGetter)
+ thisObject->defineGetter(exec, id, JSC::asObject(value));
+ if (flags & QScriptValue::PropertySetter)
+ thisObject->defineSetter(exec, id, JSC::asObject(value));
+ }
+ } else {
+ qWarning("QScriptValue::setProperty(): getter/setter must be a function");
+ }
+ }
+ } else {
+ // setting the value
+ if (getter && getter.isObject() && !(setter && setter.isObject())) {
+ qWarning("QScriptValue::setProperty() failed: "
+ "property '%s' has a getter but no setter",
+ qPrintable(QString(id.ustring())));
+ return;
+ }
+ if (!value) {
+ // ### check if it's a getter/setter property
+ thisObject->deleteProperty(exec, id);
+ } else if (flags != QScriptValue::KeepExistingFlags) {
+ if (thisObject->hasOwnProperty(exec, id))
+ thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes?
+ thisObject->putWithAttributes(exec, id, value, propertyFlagsToJSCAttributes(flags));
+ } else {
+ JSC::PutPropertySlot slot;
+ thisObject->put(exec, id, value, slot);
+ }
+ }
+}
+
+void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, quint32 index,
+ JSC::JSValue value, const QScriptValue::PropertyFlags &flags)
+{
+ if (!value) {
+ JSC::asObject(objectValue)->deleteProperty(exec, index);
+ } else {
+ if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
+ // fall back to string-based setProperty(), since there is no
+ // JSC::JSObject::defineGetter(unsigned)
+ setProperty(exec, objectValue, JSC::Identifier::from(exec, index), value, flags);
+ } else {
+ if (flags != QScriptValue::KeepExistingFlags) {
+ // if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, arrayIndex))
+ // JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex);
+ unsigned attribs = 0;
+ if (flags & QScriptValue::ReadOnly)
+ attribs |= JSC::ReadOnly;
+ if (flags & QScriptValue::SkipInEnumeration)
+ attribs |= JSC::DontEnum;
+ if (flags & QScriptValue::Undeletable)
+ attribs |= JSC::DontDelete;
+ attribs |= flags & QScriptValue::UserRange;
+ JSC::asObject(objectValue)->putWithAttributes(exec, index, value, attribs);
+ } else {
+ JSC::asObject(objectValue)->put(exec, index, value);
+ }
+ }
+ }
+}
+
+QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id,
+ const QScriptValue::ResolveFlags &mode)
+{
+ JSC::JSObject *object = JSC::asObject(value);
+ unsigned attribs = 0;
+ JSC::PropertyDescriptor descriptor;
+ if (object->getOwnPropertyDescriptor(exec, id, descriptor))
+ attribs = descriptor.attributes();
+ else {
+ if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) {
+ JSC::JSValue proto = object->prototype();
+ return propertyFlags(exec, proto, id, mode);
+ }
+ return 0;
+ }
+ QScriptValue::PropertyFlags result = 0;
+ if (attribs & JSC::ReadOnly)
+ result |= QScriptValue::ReadOnly;
+ if (attribs & JSC::DontEnum)
+ result |= QScriptValue::SkipInEnumeration;
+ if (attribs & JSC::DontDelete)
+ result |= QScriptValue::Undeletable;
+ //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?)
+ if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull())
+ result |= QScriptValue::PropertyGetter;
+ if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull())
+ result |= QScriptValue::PropertySetter;
+#ifndef QT_NO_QOBJECT
+ if (attribs & QScript::QObjectMemberAttribute)
+ result |= QScriptValue::QObjectMember;
+#endif
+ result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange);
+ return result;
+}
+
+QScriptString QScriptEnginePrivate::toStringHandle(const JSC::Identifier &name)
+{
+ QScriptString result;
+ QScriptStringPrivate *p = new QScriptStringPrivate(this, name, QScriptStringPrivate::HeapAllocated);
+ QScriptStringPrivate::init(result, p);
+ registerScriptString(p);
+ return result;
+}
+
+#ifdef QT_NO_QOBJECT
+
+QScriptEngine::QScriptEngine()
+ : d_ptr(new QScriptEnginePrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*! \internal
+*/
+QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
+ : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+}
+#else
+
+/*!
+ Constructs a QScriptEngine object.
+
+ The globalObject() is initialized to have properties as described in
+ \l{ECMA-262}, Section 15.1.
+*/
+QScriptEngine::QScriptEngine()
+ : QObject(*new QScriptEnginePrivate, 0)
+{
+}
+
+/*!
+ Constructs a QScriptEngine object with the given \a parent.
+
+ The globalObject() is initialized to have properties as described in
+ \l{ECMA-262}, Section 15.1.
+*/
+
+QScriptEngine::QScriptEngine(QObject *parent)
+ : QObject(*new QScriptEnginePrivate, parent)
+{
+}
+
+/*! \internal
+*/
+QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+#endif
+
+/*!
+ Destroys this QScriptEngine.
+*/
+QScriptEngine::~QScriptEngine()
+{
+#ifdef QT_NO_QOBJECT
+ delete d_ptr;
+ d_ptr = 0;
+#endif
+}
+
+/*!
+ Returns this engine's Global Object.
+
+ By default, the Global Object contains the built-in objects that are
+ part of \l{ECMA-262}, such as Math, Date and String. Additionally,
+ you can set properties of the Global Object to make your own
+ extensions available to all script code. Non-local variables in
+ script code will be created as properties of the Global Object, as
+ well as local variables in global code.
+*/
+QScriptValue QScriptEngine::globalObject() const
+{
+ Q_D(const QScriptEngine);
+ QScript::APIShim shim(const_cast<QScriptEnginePrivate*>(d));
+ JSC::JSObject *result = d->globalObject();
+ return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
+}
+
+/*!
+ \since 4.5
+
+ Sets this engine's Global Object to be the given \a object.
+ If \a object is not a valid script object, this function does
+ nothing.
+
+ When setting a custom global object, you may want to use
+ QScriptValueIterator to copy the properties of the standard Global
+ Object; alternatively, you can set the internal prototype of your
+ custom object to be the original Global Object.
+*/
+void QScriptEngine::setGlobalObject(const QScriptValue &object)
+{
+ Q_D(QScriptEngine);
+ if (!object.isObject())
+ return;
+ QScript::APIShim shim(d);
+ JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
+ d->setGlobalObject(jscObject);
+}
+
+/*!
+ Returns a QScriptValue of the primitive type Null.
+
+ \sa undefinedValue()
+*/
+QScriptValue QScriptEngine::nullValue()
+{
+ Q_D(QScriptEngine);
+ return d->scriptValueFromJSCValue(JSC::jsNull());
+}
+
+/*!
+ Returns a QScriptValue of the primitive type Undefined.
+
+ \sa nullValue()
+*/
+QScriptValue QScriptEngine::undefinedValue()
+{
+ Q_D(QScriptEngine);
+ return d->scriptValueFromJSCValue(JSC::jsUndefined());
+}
+
+/*!
+ Creates a constructor function from \a fun, with the given \a length.
+ The \c{prototype} property of the resulting function is set to be the
+ given \a prototype. The \c{constructor} property of \a prototype is
+ set to be the resulting function.
+
+ When a function is called as a constructor (e.g. \c{new Foo()}), the
+ `this' object associated with the function call is the new object
+ that the function is expected to initialize; the prototype of this
+ default constructed object will be the function's public
+ \c{prototype} property. If you always want the function to behave as
+ a constructor (e.g. \c{Foo()} should also create a new object), or
+ if you need to create your own object rather than using the default
+ `this' object, you should make sure that the prototype of your
+ object is set correctly; either by setting it manually, or, when
+ wrapping a custom type, by having registered the defaultPrototype()
+ of that type. Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
+
+ To wrap a custom type and provide a constructor for it, you'd typically
+ do something like this:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
+ const QScriptValue &prototype,
+ int length)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
+ QScriptValue result = d->scriptValueFromJSCValue(function);
+ result.setProperty(QLatin1String("prototype"), prototype,
+ QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ const_cast<QScriptValue&>(prototype)
+ .setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration);
+ return result;
+}
+
+#ifndef QT_NO_REGEXP
+
+/*!
+ Creates a QtScript object of class RegExp with the given
+ \a regexp.
+
+ \sa QScriptValue::toRegExp()
+*/
+QScriptValue QScriptEngine::newRegExp(const QRegExp &regexp)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, regexp));
+}
+
+#endif // QT_NO_REGEXP
+
+/*!
+ Creates a QtScript object holding the given variant \a value.
+
+ If a default prototype has been registered with the meta type id of
+ \a value, then the prototype of the created object will be that
+ prototype; otherwise, the prototype will be the Object prototype
+ object.
+
+ \sa setDefaultPrototype(), QScriptValue::toVariant(), reportAdditionalMemoryCost()
+*/
+QScriptValue QScriptEngine::newVariant(const QVariant &value)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newVariant(value));
+}
+
+/*!
+ \since 4.4
+ \overload
+
+ Initializes the given Qt Script \a object to hold the given variant
+ \a value, and returns the \a object.
+
+ This function enables you to "promote" a plain Qt Script object
+ (created by the newObject() function) to a variant, or to replace
+ the variant contained inside an object previously created by the
+ newVariant() function.
+
+ The prototype() of the \a object will remain unchanged.
+
+ If \a object is not an object, this function behaves like the normal
+ newVariant(), i.e. it creates a new script object and returns it.
+
+ This function is useful when you want to provide a script
+ constructor for a C++ type. If your constructor is invoked in a
+ \c{new} expression (QScriptContext::isCalledAsConstructor() returns
+ true), you can pass QScriptContext::thisObject() (the default
+ constructed script object) to this function to initialize the new
+ object.
+
+ \sa reportAdditionalMemoryCost()
+*/
+QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
+ const QVariant &value)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::JSValue jsObject = d->scriptValueToJSCValue(object);
+ return d->scriptValueFromJSCValue(d->newVariant(jsObject, value));
+}
+
+#ifndef QT_NO_QOBJECT
+/*!
+ Creates a QtScript object that wraps the given QObject \a
+ object, using the given \a ownership. The given \a options control
+ various aspects of the interaction with the resulting script object.
+
+ Signals and slots, properties and children of \a object are
+ available as properties of the created QScriptValue. For more
+ information, see the \l{QtScript} documentation.
+
+ If \a object is a null pointer, this function returns nullValue().
+
+ If a default prototype has been registered for the \a object's class
+ (or its superclass, recursively), the prototype of the new script
+ object will be set to be that default prototype.
+
+ If the given \a object is deleted outside of QtScript's control, any
+ attempt to access the deleted QObject's members through the QtScript
+ wrapper object (either by script code or C++) will result in a
+ script exception.
+
+ \sa QScriptValue::toQObject(), reportAdditionalMemoryCost()
+*/
+QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
+ const QObjectWrapOptions &options)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
+ return d->scriptValueFromJSCValue(jscQObject);
+}
+
+/*!
+ \since 4.4
+ \overload
+
+ Initializes the given \a scriptObject to hold the given \a qtObject,
+ and returns the \a scriptObject.
+
+ This function enables you to "promote" a plain Qt Script object
+ (created by the newObject() function) to a QObject proxy, or to
+ replace the QObject contained inside an object previously created by
+ the newQObject() function.
+
+ The prototype() of the \a scriptObject will remain unchanged.
+
+ If \a scriptObject is not an object, this function behaves like the
+ normal newQObject(), i.e. it creates a new script object and returns
+ it.
+
+ This function is useful when you want to provide a script
+ constructor for a QObject-based class. If your constructor is
+ invoked in a \c{new} expression
+ (QScriptContext::isCalledAsConstructor() returns true), you can pass
+ QScriptContext::thisObject() (the default constructed script object)
+ to this function to initialize the new object.
+
+ \sa reportAdditionalMemoryCost()
+*/
+QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
+ QObject *qtObject,
+ ValueOwnership ownership,
+ const QObjectWrapOptions &options)
+{
+ Q_D(QScriptEngine);
+ if (!scriptObject.isObject())
+ return newQObject(qtObject, ownership, options);
+ QScript::APIShim shim(d);
+ JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
+ if (!jscObject->inherits(&QScriptObject::info)) {
+ qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
+ return QScriptValue();
+ }
+ QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
+ if (!scriptObject.isQObject()) {
+ jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
+ } else {
+ QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
+ delegate->setValue(qtObject);
+ delegate->setOwnership(ownership);
+ delegate->setOptions(options);
+ }
+ return scriptObject;
+}
+
+#endif // QT_NO_QOBJECT
+
+/*!
+ Creates a QtScript object of class Object.
+
+ The prototype of the created object will be the Object
+ prototype object.
+
+ \sa newArray(), QScriptValue::setProperty()
+*/
+QScriptValue QScriptEngine::newObject()
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newObject());
+}
+
+/*!
+ \since 4.4
+ \overload
+
+ Creates a QtScript Object of the given class, \a scriptClass.
+
+ The prototype of the created object will be the Object
+ prototype object.
+
+ \a data, if specified, is set as the internal data of the
+ new object (using QScriptValue::setData()).
+
+ \sa QScriptValue::scriptClass(), reportAdditionalMemoryCost()
+*/
+QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
+ const QScriptValue &data)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
+ result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
+ QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
+ scriptObject.setData(data);
+ QScriptValue proto = scriptClass->prototype();
+ if (proto.isValid())
+ scriptObject.setPrototype(proto);
+ return scriptObject;
+}
+
+/*!
+ \internal
+*/
+QScriptValue QScriptEngine::newActivationObject()
+{
+ qWarning("QScriptEngine::newActivationObject() not implemented");
+ // ### JSActivation or JSVariableObject?
+ return QScriptValue();
+}
+
+/*!
+ Creates a QScriptValue that wraps a native (C++) function. \a fun
+ must be a C++ function with signature QScriptEngine::FunctionSignature. \a
+ length is the number of arguments that \a fun expects; this becomes
+ the \c{length} property of the created QScriptValue.
+
+ Note that \a length only gives an indication of the number of
+ arguments that the function expects; an actual invocation of a
+ function can include any number of arguments. You can check the
+ \l{QScriptContext::argumentCount()}{argumentCount()} of the
+ QScriptContext associated with the invocation to determine the
+ actual number of arguments passed.
+
+ A \c{prototype} property is automatically created for the resulting
+ function object, to provide for the possibility that the function
+ will be used as a constructor.
+
+ By combining newFunction() and the property flags
+ QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
+ can create script object properties that behave like normal
+ properties in script code, but are in fact accessed through
+ functions (analogous to how properties work in \l{Qt's Property
+ System}). Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
+
+ When the property \c{foo} of the script object is subsequently
+ accessed in script code, \c{getSetFoo()} will be invoked to handle
+ the access. In this particular case, we chose to store the "real"
+ value of \c{foo} as a property of the accessor function itself; you
+ are of course free to do whatever you like in this function.
+
+ In the above example, a single native function was used to handle
+ both reads and writes to the property; the argument count is used to
+ determine if we are handling a read or write. You can also use two
+ separate functions; just specify the relevant flag
+ (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
+ setting the property, e.g.:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
+
+ \sa QScriptValue::call()
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
+ QScriptValue result = d->scriptValueFromJSCValue(function);
+ QScriptValue proto = newObject();
+ result.setProperty(QLatin1String("prototype"), proto,
+ QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration);
+ return result;
+}
+
+/*!
+ \internal
+ \since 4.4
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
+ QScriptValue result = d->scriptValueFromJSCValue(function);
+ QScriptValue proto = newObject();
+ result.setProperty(QLatin1String("prototype"), proto,
+ QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration);
+ return result;
+}
+
+/*!
+ Creates a QtScript object of class Array with the given \a length.
+
+ \sa newObject()
+*/
+QScriptValue QScriptEngine::newArray(uint length)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newArray(d->currentFrame, length));
+}
+
+/*!
+ Creates a QtScript object of class RegExp with the given
+ \a pattern and \a flags.
+
+ The legal flags are 'g' (global), 'i' (ignore case), and 'm'
+ (multiline).
+*/
+QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, pattern, flags));
+}
+
+/*!
+ Creates a QtScript object of class Date with the given
+ \a value (the number of milliseconds since 01 January 1970,
+ UTC).
+*/
+QScriptValue QScriptEngine::newDate(qsreal value)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value));
+}
+
+/*!
+ Creates a QtScript object of class Date from the given \a value.
+
+ \sa QScriptValue::toDateTime()
+*/
+QScriptValue QScriptEngine::newDate(const QDateTime &value)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value));
+}
+
+#ifndef QT_NO_QOBJECT
+/*!
+ Creates a QtScript object that represents a QObject class, using the
+ the given \a metaObject and constructor \a ctor.
+
+ Enums of \a metaObject (declared with Q_ENUMS) are available as
+ properties of the created QScriptValue. When the class is called as
+ a function, \a ctor will be called to create a new instance of the
+ class.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27
+
+ \sa newQObject(), scriptValueFromQMetaObject()
+*/
+QScriptValue QScriptEngine::newQMetaObject(
+ const QMetaObject *metaObject, const QScriptValue &ctor)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor);
+ JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor);
+ return d->scriptValueFromJSCValue(jscQMetaObject);
+}
+
+/*!
+ \fn QScriptValue QScriptEngine::scriptValueFromQMetaObject()
+
+ Creates a QScriptValue that represents the Qt class \c{T}.
+
+ This function is used in combination with one of the
+ Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13
+
+ \sa QScriptEngine::newQMetaObject()
+*/
+
+/*!
+ \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine)
+ \since 4.3
+ \relates QScriptEngine
+ \obsolete
+
+ Uses \a engine to create a QScriptValue that represents the Qt class
+ \c{T}.
+
+ This function is equivalent to
+ QScriptEngine::scriptValueFromQMetaObject().
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QScriptEngine::newQMetaObject()
+*/
+#endif // QT_NO_QOBJECT
+
+/*!
+ \obsolete
+
+ Returns true if \a program can be evaluated; i.e. the code is
+ sufficient to determine whether it appears to be a syntactically
+ correct program, or contains a syntax error.
+
+ This function returns false if \a program is incomplete; i.e. the
+ input is syntactically correct up to the point where the input is
+ terminated.
+
+ Note that this function only does a static check of \a program;
+ e.g. it does not check whether references to variables are
+ valid, and so on.
+
+ A typical usage of canEvaluate() is to implement an interactive
+ interpreter for QtScript. The user is repeatedly queried for
+ individual lines of code; the lines are concatened internally, and
+ only when canEvaluate() returns true for the resulting program is it
+ passed to evaluate().
+
+ The following are some examples to illustrate the behavior of
+ canEvaluate(). (Note that all example inputs are assumed to have an
+ explicit newline as their last character, since otherwise the
+ QtScript parser would automatically insert a semi-colon character at
+ the end of the input, and this could cause canEvaluate() to produce
+ different results.)
+
+ Given the input
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14
+ canEvaluate() will return true, since the program appears to be complete.
+
+ Given the input
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15
+ canEvaluate() will return false, since the if-statement is not complete,
+ but is syntactically correct so far.
+
+ Given the input
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16
+ canEvaluate() will return true, but evaluate() will throw a
+ SyntaxError given the same input.
+
+ Given the input
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17
+ canEvaluate() will return true, even though the code is clearly not
+ syntactically valid QtScript code. evaluate() will throw a
+ SyntaxError when this code is evaluated.
+
+ Given the input
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18
+ canEvaluate() will return true, but evaluate() will throw a
+ ReferenceError if \c{foo} is not defined in the script
+ environment.
+
+ \sa evaluate(), checkSyntax()
+*/
+bool QScriptEngine::canEvaluate(const QString &program) const
+{
+ return QScriptEnginePrivate::canEvaluate(program);
+}
+
+
+bool QScriptEnginePrivate::canEvaluate(const QString &program)
+{
+ QScript::SyntaxChecker checker;
+ QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
+ return (result.state != QScript::SyntaxChecker::Intermediate);
+}
+
+/*!
+ \since 4.5
+
+ Checks the syntax of the given \a program. Returns a
+ QScriptSyntaxCheckResult object that contains the result of the check.
+*/
+QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
+{
+ return QScriptEnginePrivate::checkSyntax(program);
+}
+
+QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program)
+{
+ QScript::SyntaxChecker checker;
+ QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
+ QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate();
+ switch (result.state) {
+ case QScript::SyntaxChecker::Error:
+ p->state = QScriptSyntaxCheckResult::Error;
+ break;
+ case QScript::SyntaxChecker::Intermediate:
+ p->state = QScriptSyntaxCheckResult::Intermediate;
+ break;
+ case QScript::SyntaxChecker::Valid:
+ p->state = QScriptSyntaxCheckResult::Valid;
+ break;
+ }
+ p->errorLineNumber = result.errorLineNumber;
+ p->errorColumnNumber = result.errorColumnNumber;
+ p->errorMessage = result.errorMessage;
+ return QScriptSyntaxCheckResult(p);
+}
+
+
+
+/*!
+ Evaluates \a program, using \a lineNumber as the base line number,
+ and returns the result of the evaluation.
+
+ The script code will be evaluated in the current context.
+
+ The evaluation of \a program can cause an exception in the
+ engine; in this case the return value will be the exception
+ that was thrown (typically an \c{Error} object). You can call
+ hasUncaughtException() to determine if an exception occurred in
+ the last call to evaluate().
+
+ \a lineNumber is used to specify a starting line number for \a
+ program; line number information reported by the engine that pertain
+ to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
+ based on this argument. For example, if \a program consists of two
+ lines of code, and the statement on the second line causes a script
+ exception, uncaughtExceptionLineNumber() would return the given \a
+ lineNumber plus one. When no starting line number is specified, line
+ numbers will be 1-based.
+
+ \a fileName is used for error reporting. For example in error objects
+ the file name is accessible through the "fileName" property if it's
+ provided with this function.
+
+ \sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation()
+*/
+
+QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
+ = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d);
+ intptr_t sourceId = provider->asID();
+ JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null.
+
+ JSC::ExecState* exec = d->currentFrame;
+ WTF::RefPtr<JSC::EvalExecutable> executable = JSC::EvalExecutable::create(exec, source);
+ bool compile = true;
+ return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile));
+}
+
+/*!
+ \since 4.7
+
+ Evaluates the given \a program and returns the result of the
+ evaluation.
+*/
+QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
+{
+ Q_D(QScriptEngine);
+ QScriptProgramPrivate *program_d = QScriptProgramPrivate::get(program);
+ if (!program_d)
+ return QScriptValue();
+
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::EvalExecutable *executable = program_d->executable(exec, d);
+ bool compile = !program_d->isCompiled;
+ JSC::JSValue result = d->evaluateHelper(exec, program_d->sourceId,
+ executable, compile);
+ if (compile)
+ program_d->isCompiled = true;
+ return d->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Returns the current context.
+
+ The current context is typically accessed to retrieve the arguments
+ and `this' object in native functions; for convenience, it is
+ available as the first argument in QScriptEngine::FunctionSignature.
+*/
+QScriptContext *QScriptEngine::currentContext() const
+{
+ Q_D(const QScriptEngine);
+ return const_cast<QScriptEnginePrivate*>(d)->contextForFrame(d->currentFrame);
+}
+
+/*!
+ Enters a new execution context and returns the associated
+ QScriptContext object.
+
+ Once you are done with the context, you should call popContext() to
+ restore the old context.
+
+ By default, the `this' object of the new context is the Global Object.
+ The context's \l{QScriptContext::callee()}{callee}() will be invalid.
+
+ This function is useful when you want to evaluate script code
+ as if it were the body of a function. You can use the context's
+ \l{QScriptContext::activationObject()}{activationObject}() to initialize
+ local variables that will be available to scripts. Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19
+
+ In the above example, the new variable "tmp" defined in the script
+ will be local to the context; in other words, the script doesn't
+ have any effect on the global environment.
+
+ Returns 0 in case of stack overflow
+
+ \sa popContext()
+*/
+QScriptContext *QScriptEngine::pushContext()
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+
+ JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
+ JSC::ArgList(), /*callee = */0);
+
+ if (agent())
+ agent()->contextPush();
+
+ return d->contextForFrame(newFrame);
+}
+
+/*! \internal
+ push a context for a native function.
+ JSC native function doesn't have different stackframe or context. so we need to create one.
+
+ use popContext right after to go back to the previous context the context if no stack overflow has hapenned
+
+ exec is the current top frame.
+
+ return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
+*/
+JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
+ const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor,
+ bool clearScopeChain)
+{
+ JSC::JSValue thisObject = _thisObject;
+ if (!callee) {
+ // callee can't be zero, as this can cause JSC to crash during GC
+ // marking phase if the context's Arguments object has been created.
+ // Fake it by using the global object. Note that this is also handled
+ // in QScriptContext::callee(), as that function should still return
+ // an invalid value.
+ callee = originalGlobalObject();
+ }
+ if (calledAsConstructor) {
+ //JSC doesn't create default created object for native functions. so we do it
+ JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype);
+ JSC::Structure *structure = prototype.isObject() ? JSC::asObject(prototype)->inheritorID()
+ : originalGlobalObject()->emptyObjectStructure();
+ thisObject = new (exec) QScriptObject(structure);
+ }
+
+ int flags = NativeContext;
+ if (calledAsConstructor)
+ flags |= CalledAsConstructorContext;
+
+ //build a frame
+ JSC::CallFrame *newCallFrame = exec;
+ if (callee == 0 //called from public QScriptEngine::pushContext
+ || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
+ || (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us.
+ //We need to check if the Interpreter might have already created a frame for function called from JS.
+ JSC::Interpreter *interp = exec->interpreter();
+ JSC::Register *oldEnd = interp->registerFile().end();
+ int argc = args.size() + 1; //add "this"
+ JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize;
+ if (!interp->registerFile().grow(newEnd))
+ return 0; //### Stack overflow
+ newCallFrame = JSC::CallFrame::create(oldEnd);
+ newCallFrame[0] = thisObject;
+ int dst = 0;
+ JSC::ArgList::const_iterator it;
+ for (it = args.begin(); it != args.end(); ++it)
+ newCallFrame[++dst] = *it;
+ newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
+
+ if (!clearScopeChain) {
+ newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+ } else {
+ newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+ }
+ } else {
+ setContextFlags(newCallFrame, flags);
+#if ENABLE(JIT)
+ exec->registers()[JSC::RegisterFile::Callee] = JSC::JSValue(callee); //JIT let the callee set the 'callee'
+#endif
+ if (calledAsConstructor) {
+ //update the new created this
+ JSC::Register* thisRegister = thisRegisterForFrame(newCallFrame);
+ *thisRegister = thisObject;
+ }
+ }
+ currentFrame = newCallFrame;
+ return newCallFrame;
+}
+
+
+/*!
+ Pops the current execution context and restores the previous one.
+ This function must be used in conjunction with pushContext().
+
+ \sa pushContext()
+*/
+void QScriptEngine::popContext()
+{
+ if (agent())
+ agent()->contextPop();
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
+ || !currentContext()->parentContext()) {
+ qWarning("QScriptEngine::popContext() doesn't match with pushContext()");
+ return;
+ }
+
+ d->popContext();
+}
+
+/*! \internal
+ counter part of QScriptEnginePrivate::pushContext
+ */
+void QScriptEnginePrivate::popContext()
+{
+ uint flags = contextFlags(currentFrame);
+ bool hasScope = flags & HasScopeContext;
+ if (flags & ShouldRestoreCallFrame) { //normal case
+ JSC::RegisterFile &registerFile = currentFrame->interpreter()->registerFile();
+ JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
+ if (hasScope)
+ currentFrame->scopeChain()->pop()->deref();
+ registerFile.shrink(newEnd);
+ } else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it.
+ currentFrame->setScopeChain(currentFrame->scopeChain()->pop());
+ currentFrame->scopeChain()->deref();
+ }
+ currentFrame = currentFrame->callerFrame();
+}
+
+/*!
+ Returns true if the last script evaluation resulted in an uncaught
+ exception; otherwise returns false.
+
+ The exception state is cleared when evaluate() is called.
+
+ \sa uncaughtException(), uncaughtExceptionLineNumber()
+*/
+bool QScriptEngine::hasUncaughtException() const
+{
+ Q_D(const QScriptEngine);
+ JSC::ExecState* exec = d->globalExec();
+ return exec->hadException() || d->currentException().isValid();
+}
+
+/*!
+ Returns the current uncaught exception, or an invalid QScriptValue
+ if there is no uncaught exception.
+
+ The exception value is typically an \c{Error} object; in that case,
+ you can call toString() on the return value to obtain an error
+ message.
+
+ \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
+*/
+QScriptValue QScriptEngine::uncaughtException() const
+{
+ Q_D(const QScriptEngine);
+ QScriptValue result;
+ JSC::ExecState* exec = d->globalExec();
+ if (exec->hadException())
+ result = const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(exec->exception());
+ else
+ result = d->currentException();
+ return result;
+}
+
+/*!
+ Returns the line number where the last uncaught exception occurred.
+
+ Line numbers are 1-based, unless a different base was specified as
+ the second argument to evaluate().
+
+ \sa hasUncaughtException()
+*/
+int QScriptEngine::uncaughtExceptionLineNumber() const
+{
+ if (!hasUncaughtException())
+ return -1;
+ return uncaughtException().property(QLatin1String("lineNumber")).toInt32();
+}
+
+/*!
+ Returns a human-readable backtrace of the last uncaught exception.
+
+ It is in the form \c{<function-name>()@<file-name>:<line-number>}.
+
+ \sa uncaughtException()
+*/
+QStringList QScriptEngine::uncaughtExceptionBacktrace() const
+{
+ if (!hasUncaughtException())
+ return QStringList();
+// ### currently no way to get a full backtrace from JSC without installing a
+// debugger that reimplements exception() and store the backtrace there.
+ QScriptValue value = uncaughtException();
+ if (!value.isError())
+ return QStringList();
+ QStringList result;
+ result.append(QString::fromLatin1("<anonymous>()@%0:%1")
+ .arg(value.property(QLatin1String("fileName")).toString())
+ .arg(value.property(QLatin1String("lineNumber")).toInt32()));
+ return result;
+}
+
+/*!
+ \since 4.4
+
+ Clears any uncaught exceptions in this engine.
+
+ \sa hasUncaughtException()
+*/
+void QScriptEngine::clearExceptions()
+{
+ Q_D(QScriptEngine);
+ JSC::ExecState* exec = d->currentFrame;
+ exec->clearException();
+ d->clearCurrentException();
+}
+
+/*!
+ Returns the default prototype associated with the given \a metaTypeId,
+ or an invalid QScriptValue if no default prototype has been set.
+
+ \sa setDefaultPrototype()
+*/
+QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const
+{
+ Q_D(const QScriptEngine);
+ return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(d->defaultPrototype(metaTypeId));
+}
+
+/*!
+ Sets the default prototype of the C++ type identified by the given
+ \a metaTypeId to \a prototype.
+
+ The default prototype provides a script interface for values of
+ type \a metaTypeId when a value of that type is accessed from script
+ code. Whenever the script engine (implicitly or explicitly) creates
+ a QScriptValue from a value of type \a metaTypeId, the default
+ prototype will be set as the QScriptValue's prototype.
+
+ The \a prototype object itself may be constructed using one of two
+ principal techniques; the simplest is to subclass QScriptable, which
+ enables you to define the scripting API of the type through QObject
+ properties and slots. Another possibility is to create a script
+ object by calling newObject(), and populate the object with the
+ desired properties (e.g. native functions wrapped with
+ newFunction()).
+
+ \sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example}
+*/
+void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype)
+{
+ Q_D(QScriptEngine);
+ d->setDefaultPrototype(metaTypeId, d->scriptValueToJSCValue(prototype));
+}
+
+/*!
+ \typedef QScriptEngine::FunctionSignature
+ \relates QScriptEngine
+
+ The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
+
+ A function with such a signature can be passed to
+ QScriptEngine::newFunction() to wrap the function.
+*/
+
+/*!
+ \typedef QScriptEngine::FunctionWithArgSignature
+ \relates QScriptEngine
+
+ The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
+
+ A function with such a signature can be passed to
+ QScriptEngine::newFunction() to wrap the function.
+*/
+
+/*!
+ \typedef QScriptEngine::MarshalFunction
+ \internal
+*/
+
+/*!
+ \typedef QScriptEngine::DemarshalFunction
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QScriptValue QScriptEngine::create(int type, const void *ptr)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->scriptValueFromJSCValue(d->create(d->currentFrame, type, ptr));
+}
+
+JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const void *ptr)
+{
+ Q_ASSERT(ptr != 0);
+ JSC::JSValue result;
+ QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0;
+ QScriptTypeInfo *info = eng ? eng->m_typeInfos.value(type) : 0;
+ if (info && info->marshal) {
+ result = eng->scriptValueToJSCValue(info->marshal(eng->q_func(), ptr));
+ } else {
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Void:
+ return JSC::jsUndefined();
+ case QMetaType::Bool:
+ return JSC::jsBoolean(*reinterpret_cast<const bool*>(ptr));
+ case QMetaType::Int:
+ return JSC::jsNumber(exec, *reinterpret_cast<const int*>(ptr));
+ case QMetaType::UInt:
+ return JSC::jsNumber(exec, *reinterpret_cast<const uint*>(ptr));
+ case QMetaType::LongLong:
+ return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
+ case QMetaType::ULongLong:
+ return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
+ case QMetaType::Double:
+ return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr)));
+ case QMetaType::QString:
+ return JSC::jsString(exec, *reinterpret_cast<const QString*>(ptr));
+ case QMetaType::Float:
+ return JSC::jsNumber(exec, *reinterpret_cast<const float*>(ptr));
+ case QMetaType::Short:
+ return JSC::jsNumber(exec, *reinterpret_cast<const short*>(ptr));
+ case QMetaType::UShort:
+ return JSC::jsNumber(exec, *reinterpret_cast<const unsigned short*>(ptr));
+ case QMetaType::Char:
+ return JSC::jsNumber(exec, *reinterpret_cast<const char*>(ptr));
+ case QMetaType::UChar:
+ return JSC::jsNumber(exec, *reinterpret_cast<const unsigned char*>(ptr));
+ case QMetaType::QChar:
+ return JSC::jsNumber(exec, (*reinterpret_cast<const QChar*>(ptr)).unicode());
+ case QMetaType::QStringList:
+ result = arrayFromStringList(exec, *reinterpret_cast<const QStringList *>(ptr));
+ break;
+ case QMetaType::QVariantList:
+ result = arrayFromVariantList(exec, *reinterpret_cast<const QVariantList *>(ptr));
+ break;
+ case QMetaType::QVariantMap:
+ result = objectFromVariantMap(exec, *reinterpret_cast<const QVariantMap *>(ptr));
+ break;
+ case QMetaType::QDateTime:
+ result = newDate(exec, *reinterpret_cast<const QDateTime *>(ptr));
+ break;
+ case QMetaType::QDate:
+ result = newDate(exec, QDateTime(*reinterpret_cast<const QDate *>(ptr)));
+ break;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr));
+ break;
+#endif
+#ifndef QT_NO_QOBJECT
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ result = eng->newQObject(*reinterpret_cast<QObject* const *>(ptr));
+ break;
+#endif
+ case QMetaType::QVariant:
+ result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr));
+ break;
+ default:
+ if (type == qMetaTypeId<QScriptValue>()) {
+ result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr));
+ if (!result)
+ return JSC::jsUndefined();
+ }
+
+#ifndef QT_NO_QOBJECT
+ // lazy registration of some common list types
+ else if (type == qMetaTypeId<QObjectList>()) {
+ qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
+ return create(exec, type, ptr);
+ }
+#endif
+ else if (type == qMetaTypeId<QList<int> >()) {
+ qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
+ return create(exec, type, ptr);
+ }
+
+ else {
+ QByteArray typeName = QMetaType::typeName(type);
+ if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
+ return JSC::jsNull();
+ else
+ result = eng->newVariant(QVariant(type, ptr));
+ }
+ }
+ }
+ if (result && result.isObject() && info && info->prototype
+ && JSC::JSValue::strictEqual(exec, JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) {
+ JSC::asObject(result)->setPrototype(info->prototype);
+ }
+ return result;
+}
+
+bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value,
+ int type, void *ptr)
+{
+ QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0;
+ if (eng) {
+ QScriptTypeInfo *info = eng->m_typeInfos.value(type);
+ if (info && info->demarshal) {
+ info->demarshal(eng->scriptValueFromJSCValue(value), ptr);
+ return true;
+ }
+ }
+
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(ptr) = toBool(exec, value);
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = toInt32(exec, value);
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = toUInt32(exec, value);
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = qlonglong(toInteger(exec, value));
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = qulonglong(toInteger(exec, value));
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(ptr) = toNumber(exec, value);
+ return true;
+ case QMetaType::QString:
+ if (value.isUndefined() || value.isNull())
+ *reinterpret_cast<QString*>(ptr) = QString();
+ else
+ *reinterpret_cast<QString*>(ptr) = toString(exec, value);
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(ptr) = toNumber(exec, value);
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(ptr) = short(toInt32(exec, value));
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(toNumber(exec, value));
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = char(toInt32(exec, value));
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(toInt32(exec, value));
+ return true;
+ case QMetaType::QChar:
+ if (value.isString()) {
+ QString str = toString(exec, value);
+ *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
+ } else {
+ *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(toNumber(exec, value)));
+ }
+ return true;
+ case QMetaType::QDateTime:
+ if (isDate(value)) {
+ *reinterpret_cast<QDateTime *>(ptr) = toDateTime(exec, value);
+ return true;
+ } break;
+ case QMetaType::QDate:
+ if (isDate(value)) {
+ *reinterpret_cast<QDate *>(ptr) = toDateTime(exec, value).date();
+ return true;
+ } break;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ if (isRegExp(value)) {
+ *reinterpret_cast<QRegExp *>(ptr) = toRegExp(exec, value);
+ return true;
+ } break;
+#endif
+#ifndef QT_NO_QOBJECT
+ case QMetaType::QObjectStar:
+ if (isQObject(value) || value.isNull()) {
+ *reinterpret_cast<QObject* *>(ptr) = toQObject(exec, value);
+ return true;
+ } break;
+ case QMetaType::QWidgetStar:
+ if (isQObject(value) || value.isNull()) {
+ QObject *qo = toQObject(exec, value);
+ if (!qo || qo->isWidgetType()) {
+ *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
+ return true;
+ }
+ } break;
+#endif
+ case QMetaType::QStringList:
+ if (isArray(value)) {
+ *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value);
+ return true;
+ } break;
+ case QMetaType::QVariantList:
+ if (isArray(value)) {
+ *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, JSC::asArray(value));
+ return true;
+ } break;
+ case QMetaType::QVariantMap:
+ if (isObject(value)) {
+ *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, JSC::asObject(value));
+ return true;
+ } break;
+ case QMetaType::QVariant:
+ *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value);
+ return true;
+ default:
+ ;
+ }
+
+ QByteArray name = QMetaType::typeName(type);
+#ifndef QT_NO_QOBJECT
+ if (convertToNativeQObject(exec, value, name, reinterpret_cast<void* *>(ptr)))
+ return true;
+#endif
+ if (isVariant(value) && name.endsWith('*')) {
+ int valueType = QMetaType::type(name.left(name.size()-1));
+ QVariant &var = variantValue(value);
+ if (valueType == var.userType()) {
+ *reinterpret_cast<void* *>(ptr) = var.data();
+ return true;
+ } else {
+ // look in the prototype chain
+ JSC::JSValue proto = JSC::asObject(value)->prototype();
+ while (proto.isObject()) {
+ bool canCast = false;
+ if (isVariant(proto)) {
+ canCast = (type == variantValue(proto).userType())
+ || (valueType && (valueType == variantValue(proto).userType()));
+ }
+#ifndef QT_NO_QOBJECT
+ else if (isQObject(proto)) {
+ QByteArray className = name.left(name.size()-1);
+ if (QObject *qobject = toQObject(exec, proto))
+ canCast = qobject->qt_metacast(className) != 0;
+ }
+#endif
+ if (canCast) {
+ QByteArray varTypeName = QMetaType::typeName(var.userType());
+ if (varTypeName.endsWith('*'))
+ *reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data());
+ else
+ *reinterpret_cast<void* *>(ptr) = var.data();
+ return true;
+ }
+ proto = JSC::asObject(proto)->prototype();
+ }
+ }
+ } else if (value.isNull() && name.endsWith('*')) {
+ *reinterpret_cast<void* *>(ptr) = 0;
+ return true;
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ if (!eng)
+ return false;
+ *reinterpret_cast<QScriptValue*>(ptr) = eng->scriptValueFromJSCValue(value);
+ return true;
+ }
+
+ // lazy registration of some common list types
+#ifndef QT_NO_QOBJECT
+ else if (type == qMetaTypeId<QObjectList>()) {
+ if (!eng)
+ return false;
+ qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
+ return convertValue(exec, value, type, ptr);
+ }
+#endif
+ else if (type == qMetaTypeId<QList<int> >()) {
+ if (!eng)
+ return false;
+ qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
+ return convertValue(exec, value, type, ptr);
+ }
+
+#if 0
+ if (!name.isEmpty()) {
+ qWarning("QScriptEngine::convert: unable to convert value to type `%s'",
+ name.constData());
+ }
+#endif
+ return false;
+}
+
+bool QScriptEnginePrivate::convertNumber(qsreal value, int type, void *ptr)
+{
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value);
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value);
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value);
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value));
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value));
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(ptr) = value;
+ return true;
+ case QMetaType::QString:
+ *reinterpret_cast<QString*>(ptr) = QScript::ToString(value);
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(ptr) = value;
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value));
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value);
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value));
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value));
+ return true;
+ case QMetaType::QChar:
+ *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value));
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QScriptEnginePrivate::convertString(const QString &value, int type, void *ptr)
+{
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value);
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value);
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value);
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value));
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value));
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(ptr) = QScript::ToNumber(value);
+ return true;
+ case QMetaType::QString:
+ *reinterpret_cast<QString*>(ptr) = value;
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(ptr) = QScript::ToNumber(value);
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value));
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value);
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value));
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value));
+ return true;
+ case QMetaType::QChar:
+ *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value));
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
+{
+ QScriptTypeInfo *info = m_typeInfos.value(type);
+ return info && (info->demarshal != 0);
+}
+
+JSC::UString QScriptEnginePrivate::translationContextFromUrl(const JSC::UString &url)
+{
+ if (url != cachedTranslationUrl) {
+ cachedTranslationContext = QFileInfo(url).baseName();
+ cachedTranslationUrl = url;
+ }
+ return cachedTranslationContext;
+}
+
+/*!
+ \internal
+*/
+bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr);
+}
+
+/*!
+ \internal
+*/
+bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
+{
+ QScriptValuePrivate *vp = QScriptValuePrivate::get(value);
+ if (vp) {
+ switch (vp->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (vp->engine) {
+ QScript::APIShim shim(vp->engine);
+ return QScriptEnginePrivate::convertValue(vp->engine->currentFrame, vp->jscValue, type, ptr);
+ } else {
+ return QScriptEnginePrivate::convertValue(0, vp->jscValue, type, ptr);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr);
+ case QScriptValuePrivate::String:
+ return QScriptEnginePrivate::convertString(vp->stringValue, type, ptr);
+ }
+ }
+ return false;
+}
+
+/*!
+ \internal
+*/
+void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
+ DemarshalFunction df,
+ const QScriptValue &prototype)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ QScriptTypeInfo *info = d->m_typeInfos.value(type);
+ if (!info) {
+ info = new QScriptTypeInfo();
+ d->m_typeInfos.insert(type, info);
+ }
+ info->marshal = mf;
+ info->demarshal = df;
+ info->prototype = d->scriptValueToJSCValue(prototype);
+}
+
+/*!
+ \since 4.5
+
+ Installs translator functions on the given \a object, or on the Global
+ Object if no object is specified.
+
+ The relation between Qt Script translator functions and C++ translator
+ functions is described in the following table:
+
+ \table
+ \header \o Script Function \o Corresponding C++ Function
+ \row \o qsTr() \o QObject::tr()
+ \row \o QT_TR_NOOP() \o QT_TR_NOOP()
+ \row \o qsTranslate() \o QCoreApplication::translate()
+ \row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
+ \row \o qsTrId() (since 4.7) \o qtTrId()
+ \row \o QT_TRID_NOOP() (since 4.7) \o QT_TRID_NOOP()
+ \endtable
+
+ \sa {Internationalization with Qt}
+*/
+void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
+ JSC::JSGlobalObject *glob = d->originalGlobalObject();
+ if (!jscObject || !jscObject.isObject())
+ jscObject = d->globalObject();
+// unsigned attribs = JSC::DontEnum;
+
+#ifndef QT_NO_TRANSLATION
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "qsTrId"), QScript::functionQsTrId));
+ JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TRID_NOOP"), QScript::functionQsTrIdNoOp));
+#endif
+
+ glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
+}
+
+/*!
+ Imports the given \a extension into this QScriptEngine. Returns
+ undefinedValue() if the extension was successfully imported. You
+ can call hasUncaughtException() to check if an error occurred; in
+ that case, the return value is the value that was thrown by the
+ exception (usually an \c{Error} object).
+
+ QScriptEngine ensures that a particular extension is only imported
+ once; subsequent calls to importExtension() with the same extension
+ name will do nothing and return undefinedValue().
+
+ \sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions}
+*/
+QScriptValue QScriptEngine::importExtension(const QString &extension)
+{
+#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ Q_UNUSED(extension);
+#else
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ if (d->importedExtensions.contains(extension))
+ return undefinedValue(); // already imported
+
+ QScriptContext *context = currentContext();
+ QCoreApplication *app = QCoreApplication::instance();
+ if (!app)
+ return context->throwError(QLatin1String("No application object"));
+
+ QObjectList staticPlugins = QPluginLoader::staticInstances();
+ QStringList libraryPaths = app->libraryPaths();
+ QString dot = QLatin1String(".");
+ QStringList pathComponents = extension.split(dot);
+ QString initDotJs = QLatin1String("__init__.js");
+
+ QString ext;
+ for (int i = 0; i < pathComponents.count(); ++i) {
+ if (!ext.isEmpty())
+ ext.append(dot);
+ ext.append(pathComponents.at(i));
+ if (d->importedExtensions.contains(ext))
+ continue; // already imported
+
+ if (d->extensionsBeingImported.contains(ext)) {
+ return context->throwError(QString::fromLatin1("recursive import of %0")
+ .arg(extension));
+ }
+ d->extensionsBeingImported.insert(ext);
+
+ QScriptExtensionInterface *iface = 0;
+ QString initjsContents;
+ QString initjsFileName;
+
+ // look for the extension in static plugins
+ for (int j = 0; j < staticPlugins.size(); ++j) {
+ iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j));
+ if (!iface)
+ continue;
+ if (iface->keys().contains(ext))
+ break; // use this one
+ else
+ iface = 0; // keep looking
+ }
+
+ {
+ // look for __init__.js resource
+ QString path = QString::fromLatin1(":/qtscriptextension");
+ for (int j = 0; j <= i; ++j) {
+ path.append(QLatin1Char('/'));
+ path.append(pathComponents.at(j));
+ }
+ path.append(QLatin1Char('/'));
+ path.append(initDotJs);
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream ts(&file);
+ initjsContents = ts.readAll();
+ initjsFileName = path;
+ file.close();
+ }
+ }
+
+ if (!iface && initjsContents.isEmpty()) {
+ // look for the extension in library paths
+ for (int j = 0; j < libraryPaths.count(); ++j) {
+ QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script");
+ QDir dir(libPath);
+ if (!dir.exists(dot))
+ continue;
+
+ // look for C++ plugin
+ QFileInfoList files = dir.entryInfoList(QDir::Files);
+ for (int k = 0; k < files.count(); ++k) {
+ QFileInfo entry = files.at(k);
+ QString filePath = entry.canonicalFilePath();
+ QPluginLoader loader(filePath);
+ iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
+ if (iface) {
+ if (iface->keys().contains(ext))
+ break; // use this one
+ else
+ iface = 0; // keep looking
+ }
+ }
+
+ // look for __init__.js in the corresponding dir
+ QDir dirdir(libPath);
+ bool dirExists = dirdir.exists();
+ for (int k = 0; dirExists && (k <= i); ++k)
+ dirExists = dirdir.cd(pathComponents.at(k));
+ if (dirExists && dirdir.exists(initDotJs)) {
+ QFile file(dirdir.canonicalPath()
+ + QDir::separator() + initDotJs);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream ts(&file);
+ initjsContents = ts.readAll();
+ initjsFileName = file.fileName();
+ file.close();
+ }
+ }
+
+ if (iface || !initjsContents.isEmpty())
+ break;
+ }
+ }
+
+ if (!iface && initjsContents.isEmpty()) {
+ d->extensionsBeingImported.remove(ext);
+ return context->throwError(
+ QString::fromLatin1("Unable to import %0: no such extension")
+ .arg(extension));
+ }
+
+ // initialize the extension in a new context
+ QScriptContext *ctx = pushContext();
+ ctx->setThisObject(globalObject());
+ ctx->activationObject().setProperty(QLatin1String("__extension__"), ext,
+ QScriptValue::ReadOnly | QScriptValue::Undeletable);
+ ctx->activationObject().setProperty(QLatin1String("__setupPackage__"),
+ newFunction(QScript::__setupPackage__));
+ ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue));
+
+ // the script is evaluated first
+ if (!initjsContents.isEmpty()) {
+ QScriptValue ret = evaluate(initjsContents, initjsFileName);
+ if (hasUncaughtException()) {
+ popContext();
+ d->extensionsBeingImported.remove(ext);
+ return ret;
+ }
+ }
+
+ // next, the C++ plugin is called
+ if (iface) {
+ iface->initialize(ext, this);
+ if (hasUncaughtException()) {
+ QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
+ popContext();
+ d->extensionsBeingImported.remove(ext);
+ return ret;
+ }
+ }
+
+ // if the __postInit__ function has been set, we call it
+ QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__"));
+ if (postInit.isFunction()) {
+ postInit.call(globalObject());
+ if (hasUncaughtException()) {
+ QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
+ popContext();
+ d->extensionsBeingImported.remove(ext);
+ return ret;
+ }
+ }
+
+ popContext();
+
+ d->importedExtensions.insert(ext);
+ d->extensionsBeingImported.remove(ext);
+ } // for (i)
+#endif // QT_NO_QOBJECT
+ return undefinedValue();
+}
+
+/*!
+ \since 4.4
+
+ Returns a list naming the available extensions that can be
+ imported using the importExtension() function. This list includes
+ extensions that have been imported.
+
+ \sa importExtension(), importedExtensions()
+*/
+QStringList QScriptEngine::availableExtensions() const
+{
+#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ return QStringList();
+#else
+ QCoreApplication *app = QCoreApplication::instance();
+ if (!app)
+ return QStringList();
+
+ QSet<QString> result;
+
+ QObjectList staticPlugins = QPluginLoader::staticInstances();
+ for (int i = 0; i < staticPlugins.size(); ++i) {
+ QScriptExtensionInterface *iface;
+ iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i));
+ if (iface) {
+ QStringList keys = iface->keys();
+ for (int j = 0; j < keys.count(); ++j)
+ result << keys.at(j);
+ }
+ }
+
+ QStringList libraryPaths = app->libraryPaths();
+ for (int i = 0; i < libraryPaths.count(); ++i) {
+ QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script");
+ QDir dir(libPath);
+ if (!dir.exists())
+ continue;
+
+ // look for C++ plugins
+ QFileInfoList files = dir.entryInfoList(QDir::Files);
+ for (int j = 0; j < files.count(); ++j) {
+ QFileInfo entry = files.at(j);
+ QString filePath = entry.canonicalFilePath();
+ QPluginLoader loader(filePath);
+ QScriptExtensionInterface *iface;
+ iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
+ if (iface) {
+ QStringList keys = iface->keys();
+ for (int k = 0; k < keys.count(); ++k)
+ result << keys.at(k);
+ }
+ }
+
+ // look for scripts
+ QString initDotJs = QLatin1String("__init__.js");
+ QList<QFileInfo> stack;
+ stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ while (!stack.isEmpty()) {
+ QFileInfo entry = stack.takeLast();
+ QDir dd(entry.canonicalFilePath());
+ if (dd.exists(initDotJs)) {
+ QString rpath = dir.relativeFilePath(dd.canonicalPath());
+ QStringList components = rpath.split(QLatin1Char('/'));
+ result << components.join(QLatin1String("."));
+ stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ }
+ }
+ }
+
+ QStringList lst = result.toList();
+ qSort(lst);
+ return lst;
+#endif
+}
+
+/*!
+ \since 4.4
+
+ Returns a list naming the extensions that have been imported
+ using the importExtension() function.
+
+ \sa availableExtensions()
+*/
+QStringList QScriptEngine::importedExtensions() const
+{
+ Q_D(const QScriptEngine);
+ QStringList lst = d->importedExtensions.toList();
+ qSort(lst);
+ return lst;
+}
+
+/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value)
+
+ Creates a QScriptValue with the given \a value.
+
+ Note that the template type \c{T} must be known to QMetaType.
+
+ See \l{Conversion Between QtScript and C++ Types} for a
+ description of the built-in type conversion provided by
+ QtScript. By default, the types that are not specially handled by
+ QtScript are represented as QVariants (e.g. the \a value is passed
+ to newVariant()); you can change this behavior by installing your
+ own type conversion functions with qScriptRegisterMetaType().
+
+ \sa fromScriptValue(), qScriptRegisterMetaType()
+*/
+
+/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ Note that \c{T} must be known to QMetaType.
+
+ See \l{Conversion Between QtScript and C++ Types} for a
+ description of the built-in type conversion provided by
+ QtScript.
+
+ \sa toScriptValue(), qScriptRegisterMetaType()
+*/
+
+/*!
+ \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value)
+ \since 4.3
+ \relates QScriptEngine
+ \obsolete
+
+ Creates a QScriptValue using the given \a engine with the given \a
+ value of template type \c{T}.
+
+ This function is equivalent to QScriptEngine::toScriptValue().
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QScriptEngine::toScriptValue(), qscriptvalue_cast
+*/
+
+/*!
+ \fn T qScriptValueToValue(const QScriptValue &value)
+ \since 4.3
+ \relates QScriptEngine
+ \obsolete
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ This function is equivalent to QScriptEngine::fromScriptValue().
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QScriptEngine::fromScriptValue()
+*/
+
+/*!
+ \fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container)
+ \since 4.3
+ \relates QScriptEngine
+
+ Creates an array in the form of a QScriptValue using the given \a engine
+ with the given \a container of template type \c{Container}.
+
+ The \c Container type must provide a \c const_iterator class to enable the
+ contents of the container to be copied into the array.
+
+ Additionally, the type of each element in the sequence should be
+ suitable for conversion to a QScriptValue. See
+ \l{Conversion Between QtScript and C++ Types} for more information
+ about the restrictions on types that can be used with QScriptValue.
+
+ \sa QScriptEngine::fromScriptValue()
+*/
+
+/*!
+ \fn void qScriptValueToSequence(const QScriptValue &value, Container &container)
+ \since 4.3
+ \relates QScriptEngine
+
+ Copies the elements in the sequence specified by \a value to the given
+ \a container of template type \c{Container}.
+
+ The \a value used is typically an array, but any container can be copied
+ as long as it provides a \c length property describing how many elements
+ it contains.
+
+ Additionally, the type of each element in the sequence must be
+ suitable for conversion to a C++ type from a QScriptValue. See
+ \l{Conversion Between QtScript and C++ Types} for more information
+ about the restrictions on types that can be used with
+ QScriptValue.
+
+ \sa qscriptvalue_cast()
+*/
+
+/*!
+ \fn T qscriptvalue_cast(const QScriptValue &value)
+ \since 4.3
+ \relates QScriptValue
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ \sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue()
+*/
+
+/*! \fn int qScriptRegisterMetaType(
+ QScriptEngine *engine,
+ QScriptValue (*toScriptValue)(QScriptEngine *, const T &t),
+ void (*fromScriptValue)(const QScriptValue &, T &t),
+ const QScriptValue &prototype = QScriptValue())
+ \relates QScriptEngine
+
+ Registers the type \c{T} in the given \a engine. \a toScriptValue must
+ be a function that will convert from a value of type \c{T} to a
+ QScriptValue, and \a fromScriptValue a function that does the
+ opposite. \a prototype, if valid, is the prototype that's set on
+ QScriptValues returned by \a toScriptValue.
+
+ Returns the internal ID used by QMetaType.
+
+ You only need to call this function if you want to provide custom
+ conversion of values of type \c{T}, i.e. if the default
+ QVariant-based representation and conversion is not
+ appropriate. (Note that custom QObject-derived types also fall in
+ this category; e.g. for a QObject-derived class called MyObject,
+ you probably want to define conversion functions for MyObject*
+ that utilize QScriptEngine::newQObject() and
+ QScriptValue::toQObject().)
+
+ If you only want to define a common script interface for values of
+ type \c{T}, and don't care how those values are represented
+ (i.e. storing them in QVariants is fine), use
+ \l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}()
+ instead; this will minimize conversion costs.
+
+ You need to declare the custom type first with
+ Q_DECLARE_METATYPE().
+
+ After a type has been registered, you can convert from a
+ QScriptValue to that type using
+ \l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and
+ create a QScriptValue from a value of that type using
+ \l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine
+ will take care of calling the proper conversion function when
+ calling C++ slots, and when getting or setting a C++ property;
+ i.e. the custom type may be used seamlessly on both the C++ side
+ and the script side.
+
+ The following is an example of how to use this function. We will
+ specify custom conversion of our type \c{MyStruct}. Here's the C++
+ type:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20
+
+ We must declare it so that the type will be known to QMetaType:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21
+
+ Next, the \c{MyStruct} conversion functions. We represent the
+ \c{MyStruct} value as a script object and just copy the properties:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22
+
+ Now we can register \c{MyStruct} with the engine:
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23
+
+ Working with \c{MyStruct} values is now easy:
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24
+
+ If you want to be able to construct values of your custom type
+ from script code, you have to register a constructor function for
+ the type. For example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25
+
+ \sa qScriptRegisterSequenceMetaType(), qRegisterMetaType()
+*/
+
+/*!
+ \macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType)
+ \since 4.3
+ \relates QScriptEngine
+
+ Declares the given \a QMetaObject. Used in combination with
+ QScriptEngine::scriptValueFromQMetaObject() to make enums and
+ instantiation of \a QMetaObject available to script code. The
+ constructor generated by this macro takes a single argument of
+ type \a ArgType; typically the argument is the parent type of the
+ new instance, in which case \a ArgType is \c{QWidget*} or
+ \c{QObject*}. Objects created by the constructor will have
+ QScriptEngine::AutoOwnership ownership.
+*/
+
+/*! \fn int qScriptRegisterSequenceMetaType(
+ QScriptEngine *engine,
+ const QScriptValue &prototype = QScriptValue())
+ \relates QScriptEngine
+
+ Registers the sequence type \c{T} in the given \a engine. This
+ function provides conversion functions that convert between \c{T}
+ and Qt Script \c{Array} objects. \c{T} must provide a
+ const_iterator class and begin(), end() and push_back()
+ functions. If \a prototype is valid, it will be set as the
+ prototype of \c{Array} objects due to conversion from \c{T};
+ otherwise, the standard \c{Array} prototype will be used.
+
+ Returns the internal ID used by QMetaType.
+
+ You need to declare the container type first with
+ Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++
+ type, it must be declared using Q_DECLARE_METATYPE() as well.
+ Example:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26
+
+ \sa qScriptRegisterMetaType()
+*/
+
+/*!
+ Runs the garbage collector.
+
+ The garbage collector will attempt to reclaim memory by locating and
+ disposing of objects that are no longer reachable in the script
+ environment.
+
+ Normally you don't need to call this function; the garbage collector
+ will automatically be invoked when the QScriptEngine decides that
+ it's wise to do so (i.e. when a certain number of new objects have
+ been created). However, you can call this function to explicitly
+ request that garbage collection should be performed as soon as
+ possible.
+
+ \sa reportAdditionalMemoryCost()
+*/
+void QScriptEngine::collectGarbage()
+{
+ Q_D(QScriptEngine);
+ d->collectGarbage();
+}
+
+/*!
+ \since 4.7
+
+ Reports an additional memory cost of the given \a size, measured in
+ bytes, to the garbage collector.
+
+ This function can be called to indicate that a Qt Script object has
+ memory associated with it that isn't managed by Qt Script itself.
+ Reporting the additional cost makes it more likely that the garbage
+ collector will be triggered.
+
+ Note that if the additional memory is shared with objects outside
+ the scripting environment, the cost should not be reported, since
+ collecting the Qt Script object would not cause the memory to be
+ freed anyway.
+
+ Negative \a size values are ignored, i.e. this function can't be
+ used to report that the additional memory has been deallocated.
+
+ \sa collectGarbage()
+*/
+void QScriptEngine::reportAdditionalMemoryCost(int size)
+{
+ Q_D(QScriptEngine);
+ d->reportAdditionalMemoryCost(size);
+}
+
+/*!
+
+ Sets the interval between calls to QCoreApplication::processEvents
+ to \a interval milliseconds.
+
+ While the interpreter is running, all event processing is by default
+ blocked. This means for instance that the gui will not be updated
+ and timers will not be fired. To allow event processing during
+ interpreter execution one can specify the processing interval to be
+ a positive value, indicating the number of milliseconds between each
+ time QCoreApplication::processEvents() is called.
+
+ The default value is -1, which disables event processing during
+ interpreter execution.
+
+ You can use QCoreApplication::postEvent() to post an event that
+ performs custom processing at the next interval. For example, you
+ could keep track of the total running time of the script and call
+ abortEvaluation() when you detect that the script has been running
+ for a long time without completing.
+
+ \sa processEventsInterval()
+*/
+void QScriptEngine::setProcessEventsInterval(int interval)
+{
+ Q_D(QScriptEngine);
+ d->processEventsInterval = interval;
+
+ if (interval > 0)
+ d->globalData->timeoutChecker->setCheckInterval(interval);
+
+ d->timeoutChecker()->setShouldProcessEvents(interval > 0);
+}
+
+/*!
+
+ Returns the interval in milliseconds between calls to
+ QCoreApplication::processEvents() while the interpreter is running.
+
+ \sa setProcessEventsInterval()
+*/
+int QScriptEngine::processEventsInterval() const
+{
+ Q_D(const QScriptEngine);
+ return d->processEventsInterval;
+}
+
+/*!
+ \since 4.4
+
+ Returns true if this engine is currently evaluating a script,
+ otherwise returns false.
+
+ \sa evaluate(), abortEvaluation()
+*/
+bool QScriptEngine::isEvaluating() const
+{
+ Q_D(const QScriptEngine);
+ return (d->currentFrame != d->globalExec()) || d->inEval;
+}
+
+/*!
+ \since 4.4
+
+ Aborts any script evaluation currently taking place in this engine.
+ The given \a result is passed back as the result of the evaluation
+ (i.e. it is returned from the call to evaluate() being aborted).
+
+ If the engine isn't evaluating a script (i.e. isEvaluating() returns
+ false), this function does nothing.
+
+ Call this function if you need to abort a running script for some
+ reason, e.g. when you have detected that the script has been
+ running for several seconds without completing.
+
+ \sa evaluate(), isEvaluating(), setProcessEventsInterval()
+*/
+void QScriptEngine::abortEvaluation(const QScriptValue &result)
+{
+ Q_D(QScriptEngine);
+ if (!isEvaluating())
+ return;
+ d->abortResult = result;
+ d->timeoutChecker()->setShouldAbort(true);
+ JSC::throwError(d->currentFrame, JSC::createInterruptedExecutionException(&d->currentFrame->globalData()).toObject(d->currentFrame));
+}
+
+#ifndef QT_NO_QOBJECT
+
+/*!
+ \since 4.4
+ \relates QScriptEngine
+
+ Creates a connection from the \a signal in the \a sender to the
+ given \a function. If \a receiver is an object, it will act as the
+ `this' object when the signal handler function is invoked. Returns
+ true if the connection succeeds; otherwise returns false.
+
+ \sa qScriptDisconnect(), QScriptEngine::signalHandlerException()
+*/
+bool qScriptConnect(QObject *sender, const char *signal,
+ const QScriptValue &receiver, const QScriptValue &function)
+{
+ if (!sender || !signal)
+ return false;
+ if (!function.isFunction())
+ return false;
+ if (receiver.isObject() && (receiver.engine() != function.engine()))
+ return false;
+ QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
+ QScript::APIShim shim(engine);
+ JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
+ JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
+ return engine->scriptConnect(sender, signal, jscReceiver, jscFunction,
+ Qt::AutoConnection);
+}
+
+/*!
+ \since 4.4
+ \relates QScriptEngine
+
+ Disconnects the \a signal in the \a sender from the given (\a
+ receiver, \a function) pair. Returns true if the connection is
+ successfully broken; otherwise returns false.
+
+ \sa qScriptConnect()
+*/
+bool qScriptDisconnect(QObject *sender, const char *signal,
+ const QScriptValue &receiver, const QScriptValue &function)
+{
+ if (!sender || !signal)
+ return false;
+ if (!function.isFunction())
+ return false;
+ if (receiver.isObject() && (receiver.engine() != function.engine()))
+ return false;
+ QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
+ QScript::APIShim shim(engine);
+ JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
+ JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
+ return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction);
+}
+
+/*!
+ \since 4.4
+ \fn void QScriptEngine::signalHandlerException(const QScriptValue &exception)
+
+ This signal is emitted when a script function connected to a signal causes
+ an \a exception.
+
+ \sa qScriptConnect()
+*/
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "moc_qscriptengine.cpp"
+QT_END_INCLUDE_NAMESPACE
+
+#endif // QT_NO_QOBJECT
+
+/*!
+ \since 4.4
+
+ Installs the given \a agent on this engine. The agent will be
+ notified of various events pertaining to script execution. This is
+ useful when you want to find out exactly what the engine is doing,
+ e.g. when evaluate() is called. The agent interface is the basis of
+ tools like debuggers and profilers.
+
+ The engine maintains ownership of the \a agent.
+
+ Calling this function will replace the existing agent, if any.
+
+ \sa agent()
+*/
+void QScriptEngine::setAgent(QScriptEngineAgent *agent)
+{
+ Q_D(QScriptEngine);
+ if (agent && (agent->engine() != this)) {
+ qWarning("QScriptEngine::setAgent(): "
+ "cannot set agent belonging to different engine");
+ return;
+ }
+ QScript::APIShim shim(d);
+ if (d->activeAgent)
+ QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
+ d->activeAgent = agent;
+ if (agent) {
+ QScriptEngineAgentPrivate::get(agent)->attach();
+ }
+}
+
+/*!
+ \since 4.4
+
+ Returns the agent currently installed on this engine, or 0 if no
+ agent is installed.
+
+ \sa setAgent()
+*/
+QScriptEngineAgent *QScriptEngine::agent() const
+{
+ Q_D(const QScriptEngine);
+ return d->activeAgent;
+}
+
+/*!
+ \since 4.4
+
+ Returns a handle that represents the given string, \a str.
+
+ QScriptString can be used to quickly look up properties, and
+ compare property names, of script objects.
+
+ \sa QScriptValue::property()
+*/
+QScriptString QScriptEngine::toStringHandle(const QString &str)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ return d->toStringHandle(JSC::Identifier(d->currentFrame, str));
+}
+
+/*!
+ \since 4.5
+
+ Converts the given \a value to an object, if such a conversion is
+ possible; otherwise returns an invalid QScriptValue. The conversion
+ is performed according to the following table:
+
+ \table
+ \header \o Input Type \o Result
+ \row \o Undefined \o An invalid QScriptValue.
+ \row \o Null \o An invalid QScriptValue.
+ \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
+ \row \o Number \o A new Number object whose internal value is set to the value of the number.
+ \row \o String \o A new String object whose internal value is set to the value of the string.
+ \row \o Object \o The result is the object itself (no conversion).
+ \endtable
+
+ \sa newObject()
+*/
+QScriptValue QScriptEngine::toObject(const QScriptValue &value)
+{
+ Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
+ JSC::JSValue jscValue = d->scriptValueToJSCValue(value);
+ if (!jscValue || jscValue.isUndefined() || jscValue.isNull())
+ return QScriptValue();
+ JSC::ExecState* exec = d->currentFrame;
+ JSC::JSValue result = jscValue.toObject(exec);
+ return d->scriptValueFromJSCValue(result);
+}
+
+/*!
+ \internal
+
+ Returns the object with the given \a id, or an invalid
+ QScriptValue if there is no object with that id.
+
+ \sa QScriptValue::objectId()
+*/
+QScriptValue QScriptEngine::objectById(qint64 id) const
+{
+ Q_D(const QScriptEngine);
+ // Assumes that the cell was not been garbage collected
+ return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
+}
+
+/*!
+ \since 4.5
+ \class QScriptSyntaxCheckResult
+
+ \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check.
+
+ \ingroup script
+ \mainclass
+
+ QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to
+ provide information about the syntactical (in)correctness of a script.
+*/
+
+/*!
+ \enum QScriptSyntaxCheckResult::State
+
+ This enum specifies the state of a syntax check.
+
+ \value Error The program contains a syntax error.
+ \value Intermediate The program is incomplete.
+ \value Valid The program is a syntactically correct Qt Script program.
+*/
+
+/*!
+ Constructs a new QScriptSyntaxCheckResult from the \a other result.
+*/
+QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ \internal
+*/
+QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d)
+ : d_ptr(d)
+{
+}
+
+/*!
+ \internal
+*/
+QScriptSyntaxCheckResult::QScriptSyntaxCheckResult()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Destroys this QScriptSyntaxCheckResult.
+*/
+QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult()
+{
+}
+
+/*!
+ Returns the state of this QScriptSyntaxCheckResult.
+*/
+QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const
+{
+ Q_D(const QScriptSyntaxCheckResult);
+ if (!d)
+ return Valid;
+ return d->state;
+}
+
+/*!
+ Returns the error line number of this QScriptSyntaxCheckResult, or -1 if
+ there is no error.
+
+ \sa state(), errorMessage()
+*/
+int QScriptSyntaxCheckResult::errorLineNumber() const
+{
+ Q_D(const QScriptSyntaxCheckResult);
+ if (!d)
+ return -1;
+ return d->errorLineNumber;
+}
+
+/*!
+ Returns the error column number of this QScriptSyntaxCheckResult, or -1 if
+ there is no error.
+
+ \sa state(), errorLineNumber()
+*/
+int QScriptSyntaxCheckResult::errorColumnNumber() const
+{
+ Q_D(const QScriptSyntaxCheckResult);
+ if (!d)
+ return -1;
+ return d->errorColumnNumber;
+}
+
+/*!
+ Returns the error message of this QScriptSyntaxCheckResult, or an empty
+ string if there is no error.
+
+ \sa state(), errorLineNumber()
+*/
+QString QScriptSyntaxCheckResult::errorMessage() const
+{
+ Q_D(const QScriptSyntaxCheckResult);
+ if (!d)
+ return QString();
+ return d->errorMessage;
+}
+
+/*!
+ Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a
+ reference to this QScriptSyntaxCheckResult.
+*/
+QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+#ifdef QT_BUILD_INTERNAL
+Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()
+{
+#if ENABLE(JIT)
+ return true;
+#else
+ return false;
+#endif
+}
+#endif
+
+#ifdef Q_CC_MSVC
+// Try to prevent compiler from crashing.
+#pragma optimize("", off)
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h
new file mode 100644
index 0000000..6d2616f
--- /dev/null
+++ b/src/script/api/qscriptengine.h
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTENGINE_H
+#define QSCRIPTENGINE_H
+
+#include <QtCore/qmetatype.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qsharedpointer.h>
+
+#ifndef QT_NO_QOBJECT
+#include <QtCore/qobject.h>
+#else
+#include <QtCore/qobjectdefs.h>
+#endif
+
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptprogram.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QDateTime;
+class QScriptClass;
+class QScriptEngineAgent;
+class QScriptEnginePrivate;
+
+#ifndef QT_NO_QOBJECT
+
+template <class T>
+inline QScriptValue qscriptQMetaObjectConstructor(QScriptContext *, QScriptEngine *, T *)
+{
+ return QScriptValue();
+}
+
+#endif // QT_NO_QOBJECT
+
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+
+template <typename T>
+inline QScriptValue qScriptValueFromValue(QScriptEngine *, const T &);
+
+template <typename T>
+inline T qscriptvalue_cast(const QScriptValue &);
+
+class QScriptSyntaxCheckResultPrivate;
+class Q_SCRIPT_EXPORT QScriptSyntaxCheckResult
+{
+public:
+ enum State {
+ Error,
+ Intermediate,
+ Valid
+ };
+
+ QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other);
+ ~QScriptSyntaxCheckResult();
+
+ State state() const;
+ int errorLineNumber() const;
+ int errorColumnNumber() const;
+ QString errorMessage() const;
+
+ QScriptSyntaxCheckResult &operator=(const QScriptSyntaxCheckResult &other);
+
+private:
+ QScriptSyntaxCheckResult();
+ QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d);
+ QExplicitlySharedDataPointer<QScriptSyntaxCheckResultPrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QScriptSyntaxCheckResult)
+ friend class QScriptEngine;
+ friend class QScriptEnginePrivate;
+};
+
+class Q_SCRIPT_EXPORT QScriptEngine
+#ifndef QT_NO_QOBJECT
+ : public QObject
+#endif
+{
+#ifndef QT_NO_QOBJECT
+ Q_OBJECT
+#endif
+public:
+ enum ValueOwnership {
+ QtOwnership,
+ ScriptOwnership,
+ AutoOwnership
+ };
+
+ enum QObjectWrapOption {
+ ExcludeChildObjects = 0x0001,
+ ExcludeSuperClassMethods = 0x0002,
+ ExcludeSuperClassProperties = 0x0004,
+ ExcludeSuperClassContents = 0x0006,
+ SkipMethodsInEnumeration = 0x0008,
+ ExcludeDeleteLater = 0x0010,
+ ExcludeSlots = 0x0020,
+
+ AutoCreateDynamicProperties = 0x0100,
+ PreferExistingWrapperObject = 0x0200
+ };
+ Q_DECLARE_FLAGS(QObjectWrapOptions, QObjectWrapOption)
+
+ QScriptEngine();
+#ifndef QT_NO_QOBJECT
+ explicit QScriptEngine(QObject *parent);
+#endif
+ virtual ~QScriptEngine();
+
+ QScriptValue globalObject() const;
+ void setGlobalObject(const QScriptValue &object);
+
+ QScriptContext *currentContext() const;
+ QScriptContext *pushContext();
+ void popContext();
+
+ bool canEvaluate(const QString &program) const;
+ static QScriptSyntaxCheckResult checkSyntax(const QString &program);
+
+ QScriptValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+
+ QScriptValue evaluate(const QScriptProgram &program);
+
+ bool isEvaluating() const;
+ void abortEvaluation(const QScriptValue &result = QScriptValue());
+
+ bool hasUncaughtException() const;
+ QScriptValue uncaughtException() const;
+ int uncaughtExceptionLineNumber() const;
+ QStringList uncaughtExceptionBacktrace() const;
+ void clearExceptions();
+
+ QScriptValue nullValue();
+ QScriptValue undefinedValue();
+
+ typedef QScriptValue (*FunctionSignature)(QScriptContext *, QScriptEngine *);
+ typedef QScriptValue (*FunctionWithArgSignature)(QScriptContext *, QScriptEngine *, void *);
+
+ QScriptValue newFunction(FunctionSignature signature, int length = 0);
+ QScriptValue newFunction(FunctionSignature signature, const QScriptValue &prototype, int length = 0);
+
+ QScriptValue newFunction(FunctionWithArgSignature signature, void *arg);
+
+ QScriptValue newVariant(const QVariant &value);
+ QScriptValue newVariant(const QScriptValue &object, const QVariant &value);
+
+#ifndef QT_NO_REGEXP
+ QScriptValue newRegExp(const QRegExp &regexp);
+#endif
+
+ QScriptValue newObject();
+ QScriptValue newObject(QScriptClass *scriptClass, const QScriptValue &data = QScriptValue());
+ QScriptValue newArray(uint length = 0);
+ QScriptValue newRegExp(const QString &pattern, const QString &flags);
+ QScriptValue newDate(qsreal value);
+ QScriptValue newDate(const QDateTime &value);
+ QScriptValue newActivationObject();
+
+#ifndef QT_NO_QOBJECT
+ QScriptValue newQObject(QObject *object, ValueOwnership ownership = QtOwnership,
+ const QObjectWrapOptions &options = 0);
+ QScriptValue newQObject(const QScriptValue &scriptObject, QObject *qtObject,
+ ValueOwnership ownership = QtOwnership,
+ const QObjectWrapOptions &options = 0);
+
+ QScriptValue newQMetaObject(const QMetaObject *metaObject, const QScriptValue &ctor = QScriptValue());
+
+ template <class T> QScriptValue scriptValueFromQMetaObject();
+
+#endif // QT_NO_QOBJECT
+
+
+
+ QScriptValue defaultPrototype(int metaTypeId) const;
+ void setDefaultPrototype(int metaTypeId, const QScriptValue &prototype);
+
+
+ typedef QScriptValue (*MarshalFunction)(QScriptEngine *, const void *);
+ typedef void (*DemarshalFunction)(const QScriptValue &, void *);
+
+
+
+ template <typename T>
+ inline QScriptValue toScriptValue(const T &value)
+ {
+ return qScriptValueFromValue(this, value);
+ }
+ template <typename T>
+ inline T fromScriptValue(const QScriptValue &value)
+ {
+ return qscriptvalue_cast<T>(value);
+ }
+
+ void installTranslatorFunctions(const QScriptValue &object = QScriptValue());
+
+ QScriptValue importExtension(const QString &extension);
+ QStringList availableExtensions() const;
+ QStringList importedExtensions() const;
+
+ void collectGarbage();
+ void reportAdditionalMemoryCost(int size);
+
+ void setProcessEventsInterval(int interval);
+ int processEventsInterval() const;
+
+ void setAgent(QScriptEngineAgent *agent);
+ QScriptEngineAgent *agent() const;
+
+ QScriptString toStringHandle(const QString &str);
+ QScriptValue toObject(const QScriptValue &value);
+
+ QScriptValue objectById(qint64 id) const;
+
+#ifndef QT_NO_QOBJECT
+Q_SIGNALS:
+ void signalHandlerException(const QScriptValue &exception);
+#endif
+
+private:
+ QScriptValue create(int type, const void *ptr);
+
+ bool convert(const QScriptValue &value, int type, void *ptr);
+ static bool convertV2(const QScriptValue &value, int type, void *ptr);
+
+ void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df,
+ const QScriptValue &prototype);
+
+ friend inline void qScriptRegisterMetaType_helper(QScriptEngine *,
+ int, MarshalFunction, DemarshalFunction, const QScriptValue &);
+
+ friend inline QScriptValue qScriptValueFromValue_helper(QScriptEngine *, int, const void *);
+
+ friend inline bool qscriptvalue_cast_helper(const QScriptValue &, int, void *);
+
+protected:
+#ifdef QT_NO_QOBJECT
+ QScopedPointer<QScriptEnginePrivate> d_ptr;
+
+ QScriptEngine(QScriptEnginePrivate &dd);
+#else
+ QScriptEngine(QScriptEnginePrivate &dd, QObject *parent = 0);
+#endif
+
+private:
+ Q_DECLARE_PRIVATE(QScriptEngine)
+ Q_DISABLE_COPY(QScriptEngine)
+#ifndef QT_NO_QOBJECT
+ Q_PRIVATE_SLOT(d_func(), void _q_objectDestroyed(QObject *))
+#endif
+};
+
+#ifndef QT_NO_QOBJECT
+
+#define Q_SCRIPT_DECLARE_QMETAOBJECT(T, _Arg1) \
+template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext *ctx, QScriptEngine *eng, T *) \
+{ \
+ _Arg1 arg1 = qscriptvalue_cast<_Arg1> (ctx->argument(0)); \
+ T* t = new T(arg1); \
+ if (ctx->isCalledAsConstructor()) \
+ return eng->newQObject(ctx->thisObject(), t, QScriptEngine::AutoOwnership); \
+ QScriptValue o = eng->newQObject(t, QScriptEngine::AutoOwnership); \
+ o.setPrototype(ctx->callee().property(QString::fromLatin1("prototype"))); \
+ return o; \
+}
+
+template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject()
+{
+ typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *);
+ ConstructPtr cptr = qscriptQMetaObjectConstructor<T>;
+ return newQMetaObject(&T::staticMetaObject,
+ newFunction(reinterpret_cast<FunctionWithArgSignature>(cptr), 0));
+}
+
+#ifdef QT_DEPRECATED
+template <class T>
+inline QT_DEPRECATED QScriptValue qScriptValueFromQMetaObject(
+ QScriptEngine *engine
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+ )
+{
+ return engine->scriptValueFromQMetaObject<T>();
+}
+#endif
+
+#endif // QT_NO_QOBJECT
+
+inline QScriptValue qScriptValueFromValue_helper(QScriptEngine *engine, int type, const void *ptr)
+{
+ if (!engine)
+ return QScriptValue();
+
+ return engine->create(type, ptr);
+}
+
+template <typename T>
+inline QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &t)
+{
+ return qScriptValueFromValue_helper(engine, qMetaTypeId<T>(), &t);
+}
+
+template <>
+inline QScriptValue qScriptValueFromValue<QVariant>(QScriptEngine *engine, const QVariant &v)
+{
+ return qScriptValueFromValue_helper(engine, v.userType(), v.data());
+}
+
+inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void *ptr)
+{
+ return QScriptEngine::convertV2(value, type, ptr);
+}
+
+template<typename T>
+T qscriptvalue_cast(const QScriptValue &value)
+{
+ T t;
+ const int id = qMetaTypeId<T>();
+
+ if (qscriptvalue_cast_helper(value, id, &t))
+ return t;
+ else if (value.isVariant())
+ return qvariant_cast<T>(value.toVariant());
+
+ return T();
+}
+
+template <>
+inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value)
+{
+ return value.toVariant();
+}
+
+#ifdef QT_DEPRECATED
+template <typename T>
+inline QT_DEPRECATED T qScriptValueToValue(const QScriptValue &value)
+{
+ return qscriptvalue_cast<T>(value);
+}
+#endif
+
+inline void qScriptRegisterMetaType_helper(QScriptEngine *eng, int type,
+ QScriptEngine::MarshalFunction mf,
+ QScriptEngine::DemarshalFunction df,
+ const QScriptValue &prototype)
+{
+ eng->registerCustomType(type, mf, df, prototype);
+}
+
+template<typename T>
+int qScriptRegisterMetaType(
+ QScriptEngine *eng,
+ QScriptValue (*toScriptValue)(QScriptEngine *, const T &t),
+ void (*fromScriptValue)(const QScriptValue &, T &t),
+ const QScriptValue &prototype = QScriptValue()
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+)
+{
+ const int id = qRegisterMetaType<T>(); // make sure it's registered
+
+ qScriptRegisterMetaType_helper(
+ eng, id, reinterpret_cast<QScriptEngine::MarshalFunction>(toScriptValue),
+ reinterpret_cast<QScriptEngine::DemarshalFunction>(fromScriptValue),
+ prototype);
+
+ return id;
+}
+
+template <class Container>
+QScriptValue qScriptValueFromSequence(QScriptEngine *eng, const Container &cont)
+{
+ QScriptValue a = eng->newArray();
+ typename Container::const_iterator begin = cont.begin();
+ typename Container::const_iterator end = cont.end();
+ typename Container::const_iterator it;
+ quint32 i;
+ for (it = begin, i = 0; it != end; ++it, ++i)
+ a.setProperty(i, eng->toScriptValue(*it));
+ return a;
+}
+
+template <class Container>
+void qScriptValueToSequence(const QScriptValue &value, Container &cont)
+{
+ quint32 len = value.property(QLatin1String("length")).toUInt32();
+ for (quint32 i = 0; i < len; ++i) {
+ QScriptValue item = value.property(i);
+ cont.push_back(qscriptvalue_cast<typename Container::value_type>(item));
+ }
+}
+
+template<typename T>
+int qScriptRegisterSequenceMetaType(
+ QScriptEngine *engine,
+ const QScriptValue &prototype = QScriptValue()
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+)
+{
+ return qScriptRegisterMetaType<T>(engine, qScriptValueFromSequence,
+ qScriptValueToSequence, prototype);
+}
+
+#ifndef QT_NO_QOBJECT
+Q_SCRIPT_EXPORT bool qScriptConnect(QObject *sender, const char *signal,
+ const QScriptValue &receiver,
+ const QScriptValue &function);
+Q_SCRIPT_EXPORT bool qScriptDisconnect(QObject *sender, const char *signal,
+ const QScriptValue &receiver,
+ const QScriptValue &function);
+#endif // QT_NO_QOBJECT
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QScriptEngine::QObjectWrapOptions)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTENGINE_H
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
new file mode 100644
index 0000000..94d195e
--- /dev/null
+++ b/src/script/api/qscriptengine_p.h
@@ -0,0 +1,1115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTENGINE_P_H
+#define QSCRIPTENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qregexp.h>
+#include <QtCore/qset.h>
+#include "qscriptvalue_p.h"
+#include "qscriptstring_p.h"
+#include "bridge/qscriptclassobject_p.h"
+#include "bridge/qscriptdeclarativeclass_p.h"
+#include "bridge/qscriptdeclarativeobject_p.h"
+#include "bridge/qscriptobject_p.h"
+#include "bridge/qscriptqobject_p.h"
+#include "bridge/qscriptvariant_p.h"
+
+#include "DateConstructor.h"
+#include "DateInstance.h"
+#include "Debugger.h"
+#include "ErrorInstance.h"
+#include "JSArray.h"
+#include "Executable.h"
+#include "Lexer.h"
+#include "RefPtr.h"
+#include "RegExpConstructor.h"
+#include "RegExpObject.h"
+#include "SourceProvider.h"
+#include "Structure.h"
+#include "UString.h"
+#include "JSGlobalObject.h"
+#include "JSValue.h"
+
+namespace JSC
+{
+ class EvalExecutable;
+ class ExecState;
+ typedef ExecState CallFrame;
+ class JSCell;
+ class JSGlobalObject;
+}
+
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QStringList;
+class QScriptContext;
+class QScriptValue;
+class QScriptTypeInfo;
+class QScriptEngineAgent;
+class QScriptEnginePrivate;
+class QScriptSyntaxCheckResult;
+class QScriptEngine;
+class QScriptProgramPrivate;
+
+namespace QScript
+{
+ class QObjectPrototype;
+ class QMetaObjectPrototype;
+ class QVariantPrototype;
+#ifndef QT_NO_QOBJECT
+ class QObjectData;
+#endif
+ class TimeoutCheckerProxy;
+
+ qint32 ToInt32(qsreal);
+ quint32 ToUInt32(qsreal);
+ quint16 ToUInt16(qsreal);
+ qsreal ToInteger(qsreal);
+
+ inline bool ToBool(qsreal);
+ inline bool ToBool(const QString &);
+ inline qint32 ToInt32(const QString &);
+ inline quint32 ToUInt32(const QString &);
+ inline quint16 ToUInt16(const QString &);
+ inline qsreal ToInteger(const QString &);
+#ifdef Q_CC_MSVC
+ // MSVC2008 crashes if these are inlined.
+ qsreal ToNumber(const QString &);
+ QString ToString(qsreal);
+#else
+ inline qsreal ToNumber(const QString &);
+ inline QString ToString(qsreal);
+#endif
+
+ QDateTime MsToDateTime(JSC::ExecState *, qsreal);
+ qsreal DateTimeToMs(JSC::ExecState *, const QDateTime &);
+
+ //some conversion helper functions
+ inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec);
+ bool isFunction(JSC::JSValue value);
+
+ inline void convertToLatin1_helper(const UChar *i, int length, char *s);
+ inline QByteArray convertToLatin1(const JSC::UString &str);
+
+ class UStringSourceProviderWithFeedback;
+
+struct GlobalClientData : public JSC::JSGlobalData::ClientData
+{
+ GlobalClientData(QScriptEnginePrivate *e)
+ : engine(e) {}
+ virtual ~GlobalClientData() {}
+ virtual void mark(JSC::MarkStack& markStack);
+
+ QScriptEnginePrivate *engine;
+};
+
+} // namespace QScript
+
+class QScriptEnginePrivate
+#ifndef QT_NO_QOBJECT
+ : public QObjectPrivate
+#endif
+{
+ Q_DECLARE_PUBLIC(QScriptEngine)
+public:
+ QScriptEnginePrivate();
+ virtual ~QScriptEnginePrivate();
+
+ static QScriptEnginePrivate *get(QScriptEngine *q) { return q ? q->d_func() : 0; }
+ static QScriptEngine *get(QScriptEnginePrivate *d) { return d ? d->q_func() : 0; }
+
+ static inline bool isArray(JSC::JSValue);
+ static inline bool isDate(JSC::JSValue);
+ static inline bool isError(JSC::JSValue);
+ static inline bool isObject(JSC::JSValue);
+ static inline bool isRegExp(JSC::JSValue);
+ static inline bool isVariant(JSC::JSValue);
+ static inline bool isQObject(JSC::JSValue);
+ static inline bool isQMetaObject(JSC::JSValue);
+
+ static inline bool toBool(JSC::ExecState *, JSC::JSValue);
+ static inline qsreal toInteger(JSC::ExecState *, JSC::JSValue);
+ static inline qsreal toNumber(JSC::ExecState *, JSC::JSValue);
+ static inline qint32 toInt32(JSC::ExecState *, JSC::JSValue);
+ static inline quint32 toUInt32(JSC::ExecState *, JSC::JSValue);
+ static inline quint16 toUInt16(JSC::ExecState *, JSC::JSValue);
+ static inline JSC::UString toString(JSC::ExecState *, JSC::JSValue);
+
+ static inline QDateTime toDateTime(JSC::ExecState *, JSC::JSValue);
+#ifndef QT_NO_REGEXP
+ static QRegExp toRegExp(JSC::ExecState*, JSC::JSValue);
+#endif
+ static QVariant toVariant(JSC::ExecState *, JSC::JSValue);
+ static inline QObject *toQObject(JSC::ExecState *, JSC::JSValue);
+ static inline const QMetaObject *toQMetaObject(JSC::ExecState *, JSC::JSValue);
+
+ static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, const JSC::Identifier &id,
+ int resolveMode = QScriptValue::ResolvePrototype);
+ static JSC::JSValue propertyHelper(JSC::ExecState*, JSC::JSValue, const JSC::Identifier &id, int resolveMode);
+ static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, quint32 index,
+ int resolveMode = QScriptValue::ResolvePrototype);
+ static JSC::JSValue propertyHelper(JSC::ExecState*, JSC::JSValue, quint32, int resolveMode);
+ static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, const JSC::UString &, int resolveMode);
+ static inline void setProperty(JSC::ExecState*, JSC::JSValue object, const JSC::UString &name, JSC::JSValue,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ static void setProperty(JSC::ExecState*, JSC::JSValue object, const JSC::Identifier &id, JSC::JSValue,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ static void setProperty(JSC::ExecState*, JSC::JSValue object, quint32 index, JSC::JSValue,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ static QScriptValue::PropertyFlags propertyFlags(JSC::ExecState*, JSC::JSValue value,
+ const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode);
+ static inline QScriptValue::PropertyFlags propertyFlags(JSC::ExecState*, JSC::JSValue value,
+ const JSC::UString &name, const QScriptValue::ResolveFlags &mode);
+
+ static bool convertValue(JSC::ExecState*, JSC::JSValue value,
+ int type, void *ptr);
+ static bool convertNumber(qsreal, int type, void *ptr);
+ static bool convertString(const QString &, int type, void *ptr);
+ static JSC::JSValue create(JSC::ExecState*, int type, const void *ptr);
+ bool hasDemarshalFunction(int type) const;
+
+ inline QScriptValue scriptValueFromJSCValue(JSC::JSValue value);
+ inline JSC::JSValue scriptValueToJSCValue(const QScriptValue &value);
+ static inline unsigned propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags);
+
+ static inline JSC::JSValue jscValueFromVariant(JSC::ExecState*, const QVariant &value);
+ static QVariant jscValueToVariant(JSC::ExecState*, JSC::JSValue value, int targetType);
+ static inline QVariant &variantValue(JSC::JSValue value);
+ static inline void setVariantValue(JSC::JSValue objectValue, const QVariant &value);
+
+ static JSC::JSValue arrayFromStringList(JSC::ExecState*, const QStringList &lst);
+ static QStringList stringListFromArray(JSC::ExecState*, JSC::JSValue arr);
+
+ static JSC::JSValue arrayFromVariantList(JSC::ExecState*, const QVariantList &lst);
+ static QVariantList variantListFromArray(JSC::ExecState*, JSC::JSArray *arr);
+
+ static JSC::JSValue objectFromVariantMap(JSC::ExecState*, const QVariantMap &vmap);
+ static QVariantMap variantMapFromObject(JSC::ExecState*, JSC::JSObject *obj);
+
+ JSC::JSValue defaultPrototype(int metaTypeId) const;
+ void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype);
+
+ static inline QScriptContext *contextForFrame(JSC::ExecState *frame);
+ static inline JSC::ExecState *frameForContext(QScriptContext *context);
+ static inline const JSC::ExecState *frameForContext(const QScriptContext *context);
+
+ static inline bool hasValidCodeBlockRegister(JSC::ExecState *frame);
+
+ JSC::JSGlobalObject *originalGlobalObject() const;
+ JSC::JSObject *getOriginalGlobalObjectProxy();
+ JSC::JSObject *customGlobalObject() const;
+ JSC::JSObject *globalObject() const;
+ void setGlobalObject(JSC::JSObject *object);
+ inline JSC::ExecState *globalExec() const;
+ JSC::JSValue toUsableValue(JSC::JSValue value);
+ static JSC::JSValue thisForContext(JSC::ExecState *frame);
+ static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame);
+
+ JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args,
+ JSC::JSObject *callee, bool calledAsConstructor = false, bool clearScopeChain = false);
+ void popContext();
+
+ void mark(JSC::MarkStack& markStack);
+ bool isCollecting() const;
+ void collectGarbage();
+ void reportAdditionalMemoryCost(int size);
+
+ //flags that we set on the return value register for native function. (ie when codeBlock is 0)
+ enum ContextFlags {
+ NativeContext = 1,
+ CalledAsConstructorContext = 2,
+ HasScopeContext = 4, // Specifies that the is a QScriptActivationObject
+ ShouldRestoreCallFrame = 8
+ };
+ static uint contextFlags(JSC::ExecState *);
+ static void setContextFlags(JSC::ExecState *, uint);
+
+ QScript::TimeoutCheckerProxy *timeoutChecker() const;
+
+ void agentDeleted(QScriptEngineAgent *agent);
+
+ static inline void saveException(JSC::ExecState *, JSC::JSValue *);
+ static inline void restoreException(JSC::ExecState *, JSC::JSValue);
+
+ void setCurrentException(QScriptValue exception) { m_currentException = exception; }
+ QScriptValue currentException() const { return m_currentException; }
+ void clearCurrentException() { m_currentException.d_ptr.reset(); }
+
+ static QScriptSyntaxCheckResult checkSyntax(const QString &program);
+ static bool canEvaluate(const QString &program);
+
+ inline void registerScriptProgram(QScriptProgramPrivate *program);
+ inline void unregisterScriptProgram(QScriptProgramPrivate *program);
+ void detachAllRegisteredScriptPrograms();
+
+ inline QScriptValuePrivate *allocateScriptValuePrivate(size_t);
+ inline void freeScriptValuePrivate(QScriptValuePrivate *p);
+
+ inline void registerScriptValue(QScriptValuePrivate *value);
+ inline void unregisterScriptValue(QScriptValuePrivate *value);
+ void detachAllRegisteredScriptValues();
+
+ inline void registerScriptString(QScriptStringPrivate *value);
+ inline void unregisterScriptString(QScriptStringPrivate *value);
+ void detachAllRegisteredScriptStrings();
+ QScriptString toStringHandle(const JSC::Identifier &name);
+
+ static inline JSC::JSValue newArray(JSC::ExecState *, uint length);
+ static inline JSC::JSValue newDate(JSC::ExecState *, qsreal value);
+ static inline JSC::JSValue newDate(JSC::ExecState *, const QDateTime &);
+ inline JSC::JSValue newObject();
+
+#ifndef QT_NO_REGEXP
+ static JSC::JSValue newRegExp(JSC::ExecState *, const QRegExp &);
+#endif
+
+ static JSC::JSValue newRegExp(JSC::ExecState *, const QString &pattern, const QString &flags);
+ JSC::JSValue newVariant(const QVariant &);
+ JSC::JSValue newVariant(JSC::JSValue objectValue, const QVariant &);
+
+ static inline QScriptDeclarativeClass *declarativeClass(JSC::JSValue);
+ static inline QScriptDeclarativeClass::Object *declarativeObject(JSC::JSValue);
+
+ JSC::UString translationContextFromUrl(const JSC::UString &);
+
+#ifndef QT_NO_QOBJECT
+ JSC::JSValue newQObject(QObject *object,
+ QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership,
+ const QScriptEngine:: QObjectWrapOptions &options = 0);
+ JSC::JSValue newQMetaObject(const QMetaObject *metaObject,
+ JSC::JSValue ctor);
+
+ static bool convertToNativeQObject(JSC::ExecState*, JSC::JSValue,
+ const QByteArray &targetType,
+ void **result);
+
+ JSC::JSValue evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
+ JSC::EvalExecutable *executable,
+ bool &compile);
+
+ QScript::QObjectData *qobjectData(QObject *object);
+ void disposeQObject(QObject *object);
+ void emitSignalHandlerException();
+
+ bool scriptConnect(QObject *sender, const char *signal,
+ JSC::JSValue receiver, JSC::JSValue function,
+ Qt::ConnectionType type);
+ bool scriptDisconnect(QObject *sender, const char *signal,
+ JSC::JSValue receiver, JSC::JSValue function);
+
+ bool scriptConnect(QObject *sender, int index,
+ JSC::JSValue receiver, JSC::JSValue function,
+ JSC::JSValue senderWrapper,
+ Qt::ConnectionType type);
+ bool scriptDisconnect(QObject *sender, int index,
+ JSC::JSValue receiver, JSC::JSValue function);
+
+ bool scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
+ JSC::JSValue function, Qt::ConnectionType type);
+ bool scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
+ JSC::JSValue function);
+
+ // private slots
+ void _q_objectDestroyed(QObject *);
+#endif
+
+ JSC::JSGlobalData *globalData;
+ JSC::JSObject *originalGlobalObjectProxy;
+ JSC::ExecState *currentFrame;
+
+ WTF::RefPtr<JSC::Structure> scriptObjectStructure;
+ WTF::RefPtr<JSC::Structure> staticScopeObjectStructure;
+
+ QScript::QObjectPrototype *qobjectPrototype;
+ WTF::RefPtr<JSC::Structure> qobjectWrapperObjectStructure;
+
+ QScript::QMetaObjectPrototype *qmetaobjectPrototype;
+ WTF::RefPtr<JSC::Structure> qmetaobjectWrapperObjectStructure;
+
+ QScript::QVariantPrototype *variantPrototype;
+ WTF::RefPtr<JSC::Structure> variantWrapperObjectStructure;
+
+ QList<QScriptEngineAgent*> ownedAgents;
+ QScriptEngineAgent *activeAgent;
+ int agentLineNumber;
+ QScriptValuePrivate *registeredScriptValues;
+ QScriptValuePrivate *freeScriptValues;
+ static const int maxFreeScriptValues = 256;
+ int freeScriptValuesCount;
+ QScriptStringPrivate *registeredScriptStrings;
+ QSet<QScriptProgramPrivate*> registeredScriptPrograms;
+ QHash<int, QScriptTypeInfo*> m_typeInfos;
+ int processEventsInterval;
+ QScriptValue abortResult;
+ bool inEval;
+
+ JSC::UString cachedTranslationUrl;
+ JSC::UString cachedTranslationContext;
+
+ QSet<QString> importedExtensions;
+ QSet<QString> extensionsBeingImported;
+
+ QHash<intptr_t, QScript::UStringSourceProviderWithFeedback*> loadedScripts;
+ QScriptValue m_currentException;
+
+ QSet<JSC::JSObject*> visitedConversionObjects;
+
+#ifndef QT_NO_QOBJECT
+ QHash<QObject*, QScript::QObjectData*> m_qobjectData;
+#endif
+
+#ifdef QT_NO_QOBJECT
+ QScriptEngine *q_ptr;
+#endif
+};
+
+namespace QScript
+{
+
+class APIShim
+{
+public:
+ APIShim(QScriptEnginePrivate *engine)
+ : m_engine(engine), m_oldTable(JSC::setCurrentIdentifierTable(engine->globalData->identifierTable))
+ {
+ }
+ ~APIShim()
+ {
+ JSC::setCurrentIdentifierTable(m_oldTable);
+ }
+
+private:
+ QScriptEnginePrivate *m_engine;
+ JSC::IdentifierTable *m_oldTable;
+};
+
+/*Helper class. Main purpose is to give debugger feedback about unloading and loading scripts.
+ It keeps pointer to JSGlobalObject assuming that it is always the same - there is no way to update
+ this data. Class is internal and used as an implementation detail in and only in QScriptEngine::evaluate.*/
+class UStringSourceProviderWithFeedback: public JSC::UStringSourceProvider
+{
+public:
+ static PassRefPtr<UStringSourceProviderWithFeedback> create(
+ const JSC::UString& source, const JSC::UString& url,
+ int lineNumber, QScriptEnginePrivate* engine)
+ {
+ return adoptRef(new UStringSourceProviderWithFeedback(source, url, lineNumber, engine));
+ }
+
+ /* Destruction means that there is no more copies of script so create scriptUnload event
+ and unregister script in QScriptEnginePrivate::loadedScripts */
+ virtual ~UStringSourceProviderWithFeedback()
+ {
+ if (m_ptr) {
+ if (JSC::Debugger* debugger = this->debugger())
+ debugger->scriptUnload(asID());
+ m_ptr->loadedScripts.remove(asID());
+ }
+ }
+
+ /* set internal QScriptEnginePrivate pointer to null and create unloadScript event, should be called
+ only if QScriptEnginePrivate is about to be destroyed.*/
+ void disconnectFromEngine()
+ {
+ if (JSC::Debugger* debugger = this->debugger())
+ debugger->scriptUnload(asID());
+ m_ptr = 0;
+ }
+
+ int columnNumberFromOffset(int offset) const
+ {
+ for (const UChar *c = m_source.data() + offset; c >= m_source.data(); --c) {
+ if (JSC::Lexer::isLineTerminator(*c))
+ return offset - static_cast<int>(c - data());
+ }
+ return offset + 1;
+ }
+
+protected:
+ UStringSourceProviderWithFeedback(const JSC::UString& source, const JSC::UString& url,
+ int lineNumber, QScriptEnginePrivate* engine)
+ : UStringSourceProvider(source, url),
+ m_ptr(engine)
+ {
+ if (JSC::Debugger* debugger = this->debugger())
+ debugger->scriptLoad(asID(), source, url, lineNumber);
+ if (m_ptr)
+ m_ptr->loadedScripts.insert(asID(), this);
+ }
+
+ JSC::Debugger* debugger()
+ {
+ //if m_ptr is null it mean that QScriptEnginePrivate was destroyed and scriptUnload was called
+ //else m_ptr is stable and we can use it as normal pointer without hesitation
+ if(!m_ptr)
+ return 0; //we are in ~QScriptEnginePrivate
+ else
+ return m_ptr->originalGlobalObject()->debugger(); //QScriptEnginePrivate is still alive
+ }
+
+ //trace global object and debugger instance
+ QScriptEnginePrivate* m_ptr;
+};
+
+class SaveFrameHelper
+{
+public:
+ SaveFrameHelper(QScriptEnginePrivate *eng,
+ JSC::ExecState *newFrame)
+ : engine(eng), oldFrame(eng->currentFrame)
+ {
+ eng->currentFrame = newFrame;
+ }
+ ~SaveFrameHelper()
+ {
+ engine->currentFrame = oldFrame;
+ }
+private:
+ QScriptEnginePrivate *engine;
+ JSC::ExecState *oldFrame;
+};
+
+inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec)
+{
+ return static_cast<GlobalClientData*>(exec->globalData().clientData)->engine;
+}
+
+#ifndef Q_CC_MSVC
+// MSVC2008 crashes if these are inlined.
+
+inline QString ToString(qsreal value)
+{
+ return JSC::UString::from(value);
+}
+
+inline qsreal ToNumber(const QString &value)
+{
+ return ((JSC::UString)value).toDouble();
+}
+
+#endif
+
+inline qint32 ToInt32(const QString &value)
+{
+ return ToInt32(ToNumber(value));
+}
+
+inline quint32 ToUInt32(const QString &value)
+{
+ return ToUInt32(ToNumber(value));
+}
+
+inline quint16 ToUInt16(const QString &value)
+{
+ return ToUInt16(ToNumber(value));
+}
+
+inline qsreal ToInteger(const QString &value)
+{
+ return ToInteger(ToNumber(value));
+}
+
+inline bool ToBool(qsreal value)
+{
+ return (value != 0) && !qIsNaN(value);
+}
+
+inline bool ToBool(const QString &value)
+{
+ return !value.isEmpty();
+}
+
+inline void convertToLatin1_helper(const UChar *i, int length, char *s)
+{
+ const UChar *e = i + length;
+ while (i != e)
+ *(s++) = (uchar) *(i++);
+ *s = '\0';
+}
+
+inline QByteArray convertToLatin1(const JSC::UString &str)
+{
+ QByteArray ba(str.size(), Qt::Uninitialized);
+ convertToLatin1_helper(str.data(), str.size(), ba.data());
+ return ba;
+}
+
+} // namespace QScript
+
+inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program)
+{
+ Q_ASSERT(!registeredScriptPrograms.contains(program));
+ registeredScriptPrograms.insert(program);
+}
+
+inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program)
+{
+ Q_ASSERT(registeredScriptPrograms.contains(program));
+ registeredScriptPrograms.remove(program);
+}
+
+inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size)
+{
+ if (freeScriptValues) {
+ QScriptValuePrivate *p = freeScriptValues;
+ freeScriptValues = p->next;
+ --freeScriptValuesCount;
+ return p;
+ }
+ return reinterpret_cast<QScriptValuePrivate*>(qMalloc(size));
+}
+
+inline void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p)
+{
+ if (freeScriptValuesCount < maxFreeScriptValues) {
+ p->next = freeScriptValues;
+ freeScriptValues = p;
+ ++freeScriptValuesCount;
+ } else {
+ qFree(p);
+ }
+}
+
+inline void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value)
+{
+ value->prev = 0;
+ value->next = registeredScriptValues;
+ if (registeredScriptValues)
+ registeredScriptValues->prev = value;
+ registeredScriptValues = value;
+}
+
+inline void QScriptEnginePrivate::unregisterScriptValue(QScriptValuePrivate *value)
+{
+ if (value->prev)
+ value->prev->next = value->next;
+ if (value->next)
+ value->next->prev = value->prev;
+ if (value == registeredScriptValues)
+ registeredScriptValues = value->next;
+ value->prev = 0;
+ value->next = 0;
+}
+
+inline JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(JSC::ExecState *exec, const QVariant &v)
+{
+ JSC::JSValue result = create(exec, v.userType(), v.data());
+ Q_ASSERT(result);
+ return result;
+}
+
+inline QScriptValue QScriptEnginePrivate::scriptValueFromJSCValue(JSC::JSValue value)
+{
+ if (!value)
+ return QScriptValue();
+
+ QScriptValuePrivate *p_value = new (this)QScriptValuePrivate(this);
+ p_value->initFrom(value);
+ return QScriptValuePrivate::toPublic(p_value);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::scriptValueToJSCValue(const QScriptValue &value)
+{
+ QScriptValuePrivate *vv = QScriptValuePrivate::get(value);
+ if (!vv)
+ return JSC::JSValue();
+ if (vv->type != QScriptValuePrivate::JavaScriptCore) {
+ Q_ASSERT(!vv->engine || vv->engine == this);
+ vv->engine = this;
+ if (vv->type == QScriptValuePrivate::Number) {
+ vv->initFrom(JSC::jsNumber(currentFrame, vv->numberValue));
+ } else { //QScriptValuePrivate::String
+ vv->initFrom(JSC::jsString(currentFrame, vv->stringValue));
+ }
+ }
+ return vv->jscValue;
+}
+
+inline unsigned QScriptEnginePrivate::propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags)
+{
+ unsigned attribs = 0;
+ if (flags & QScriptValue::ReadOnly)
+ attribs |= JSC::ReadOnly;
+ if (flags & QScriptValue::SkipInEnumeration)
+ attribs |= JSC::DontEnum;
+ if (flags & QScriptValue::Undeletable)
+ attribs |= JSC::DontDelete;
+ attribs |= flags & QScriptValue::UserRange;
+ return attribs;
+}
+
+inline QScriptValuePrivate::~QScriptValuePrivate()
+{
+ if (engine)
+ engine->unregisterScriptValue(this);
+}
+
+inline void QScriptValuePrivate::initFrom(JSC::JSValue value)
+{
+ if (value.isCell()) {
+ Q_ASSERT(engine != 0);
+ value = engine->toUsableValue(value);
+ }
+ type = JavaScriptCore;
+ jscValue = value;
+ if (engine)
+ engine->registerScriptValue(this);
+}
+
+inline void QScriptValuePrivate::initFrom(qsreal value)
+{
+ type = Number;
+ numberValue = value;
+ if (engine)
+ engine->registerScriptValue(this);
+}
+
+inline void QScriptValuePrivate::initFrom(const QString &value)
+{
+ type = String;
+ stringValue = value;
+ if (engine)
+ engine->registerScriptValue(this);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, const JSC::UString &name, int resolveMode)
+{
+ return property(exec, value, JSC::Identifier(exec, name), resolveMode);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode)
+{
+ Q_ASSERT(isObject(value));
+ JSC::JSObject *object = JSC::asObject(value);
+ JSC::PropertySlot slot(object);
+ if ((resolveMode & QScriptValue::ResolvePrototype) && object->getPropertySlot(exec, id, slot))
+ return slot.getValue(exec, id);
+ return propertyHelper(exec, value, id, resolveMode);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, quint32 index, int resolveMode)
+{
+ Q_ASSERT(isObject(value));
+ JSC::JSObject *object = JSC::asObject(value);
+ JSC::PropertySlot slot(object);
+ if ((resolveMode & QScriptValue::ResolvePrototype) && object->getPropertySlot(exec, index, slot))
+ return slot.getValue(exec, index);
+ return propertyHelper(exec, value, index, resolveMode);
+}
+
+inline QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState *exec, JSC::JSValue value,
+ const JSC::UString &name,
+ const QScriptValue::ResolveFlags &mode)
+{
+ return propertyFlags(exec, value, JSC::Identifier(exec, name), mode);
+}
+
+inline void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, const JSC::UString &name,
+ JSC::JSValue value, const QScriptValue::PropertyFlags &flags)
+{
+ setProperty(exec, objectValue, JSC::Identifier(exec, name), value, flags);
+}
+
+inline JSC::JSValue QScriptValuePrivate::property(const JSC::Identifier &id, const QScriptValue::ResolveFlags &resolveMode) const
+{
+ return QScriptEnginePrivate::property(engine->currentFrame, jscValue, id, resolveMode);
+}
+
+inline JSC::JSValue QScriptValuePrivate::property(quint32 index, const QScriptValue::ResolveFlags &resolveMode) const
+{
+ return QScriptEnginePrivate::property(engine->currentFrame, jscValue, index, resolveMode);
+}
+
+inline JSC::JSValue QScriptValuePrivate::property(const JSC::UString &name, const QScriptValue::ResolveFlags &resolveMode) const
+{
+ JSC::ExecState *exec = engine->currentFrame;
+ return QScriptEnginePrivate::property(exec, jscValue, JSC::Identifier(exec, name), resolveMode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(
+ const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode) const
+{
+ return QScriptEnginePrivate::propertyFlags(engine->currentFrame, jscValue, id, mode);
+}
+
+inline void QScriptValuePrivate::setProperty(const JSC::Identifier &id, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags)
+{
+ QScriptEnginePrivate::setProperty(engine->currentFrame, jscValue, id, value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(quint32 index, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags)
+{
+ QScriptEnginePrivate::setProperty(engine->currentFrame, jscValue, index, value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(const JSC::UString &name, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags)
+{
+ JSC::ExecState *exec = engine->currentFrame;
+ QScriptEnginePrivate::setProperty(exec, jscValue, JSC::Identifier(exec, name), value, flags);
+}
+
+inline void* QScriptValuePrivate::operator new(size_t size, QScriptEnginePrivate *engine)
+{
+ if (engine)
+ return engine->allocateScriptValuePrivate(size);
+ return qMalloc(size);
+}
+
+inline void QScriptValuePrivate::operator delete(void *ptr)
+{
+ QScriptValuePrivate *d = reinterpret_cast<QScriptValuePrivate*>(ptr);
+ if (d->engine)
+ d->engine->freeScriptValuePrivate(d);
+ else
+ qFree(d);
+}
+
+inline void QScriptEnginePrivate::saveException(JSC::ExecState *exec, JSC::JSValue *val)
+{
+ if (exec) {
+ *val = exec->exception();
+ exec->clearException();
+ } else {
+ *val = JSC::JSValue();
+ }
+}
+
+inline void QScriptEnginePrivate::restoreException(JSC::ExecState *exec, JSC::JSValue val)
+{
+ if (exec && val)
+ exec->setException(val);
+}
+
+inline void QScriptEnginePrivate::registerScriptString(QScriptStringPrivate *value)
+{
+ Q_ASSERT(value->type == QScriptStringPrivate::HeapAllocated);
+ value->prev = 0;
+ value->next = registeredScriptStrings;
+ if (registeredScriptStrings)
+ registeredScriptStrings->prev = value;
+ registeredScriptStrings = value;
+}
+
+inline void QScriptEnginePrivate::unregisterScriptString(QScriptStringPrivate *value)
+{
+ Q_ASSERT(value->type == QScriptStringPrivate::HeapAllocated);
+ if (value->prev)
+ value->prev->next = value->next;
+ if (value->next)
+ value->next->prev = value->prev;
+ if (value == registeredScriptStrings)
+ registeredScriptStrings = value->next;
+ value->prev = 0;
+ value->next = 0;
+}
+
+inline QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame)
+{
+ if (frame && frame->callerFrame()->hasHostCallFrameFlag() && !frame->callee()
+ && frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) {
+ //skip the "fake" context created in Interpreter::execute.
+ frame = frame->callerFrame()->removeHostCallFrameFlag();
+ }
+ return reinterpret_cast<QScriptContext *>(frame);
+}
+
+inline JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context)
+{
+ return reinterpret_cast<JSC::ExecState*>(context);
+}
+
+inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context)
+{
+ return reinterpret_cast<const JSC::ExecState*>(context);
+}
+
+inline bool QScriptEnginePrivate::hasValidCodeBlockRegister(JSC::ExecState *frame)
+{
+#if ENABLE(JIT)
+ // Frames created by the VM don't have their CodeBlock register
+ // initialized. We can detect such frames by checking if the
+ // callee is a host JSFunction.
+ JSC::JSObject *callee = frame->callee();
+ return !(callee && callee->inherits(&JSC::JSFunction::info)
+ && JSC::asFunction(callee)->isHostFunction());
+#else
+ Q_UNUSED(frame);
+ return true;
+#endif
+}
+
+inline JSC::ExecState *QScriptEnginePrivate::globalExec() const
+{
+ return originalGlobalObject()->globalExec();
+}
+
+inline JSC::JSValue QScriptEnginePrivate::newArray(JSC::ExecState *exec, uint length)
+{
+ return JSC::constructEmptyArray(exec, length);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, qsreal value)
+{
+ JSC::JSValue val = JSC::jsNumber(exec, value);
+ JSC::ArgList args(&val, 1);
+ return JSC::constructDate(exec, args);
+}
+
+inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, const QDateTime &value)
+{
+ return newDate(exec, QScript::DateTimeToMs(exec, value));
+}
+
+inline JSC::JSValue QScriptEnginePrivate::newObject()
+{
+ return new (currentFrame)QScriptObject(scriptObjectStructure);
+}
+
+inline bool QScriptEnginePrivate::isObject(JSC::JSValue value)
+{
+ return value && value.isObject();
+}
+
+inline bool QScriptEnginePrivate::isArray(JSC::JSValue value)
+{
+ return isObject(value) && value.inherits(&JSC::JSArray::info);
+}
+
+inline bool QScriptEnginePrivate::isDate(JSC::JSValue value)
+{
+ return isObject(value) && value.inherits(&JSC::DateInstance::info);
+}
+
+inline bool QScriptEnginePrivate::isError(JSC::JSValue value)
+{
+ return isObject(value) && value.inherits(&JSC::ErrorInstance::info);
+}
+
+inline bool QScriptEnginePrivate::isRegExp(JSC::JSValue value)
+{
+ return isObject(value) && value.inherits(&JSC::RegExpObject::info);
+}
+
+inline bool QScriptEnginePrivate::isVariant(JSC::JSValue value)
+{
+ if (!isObject(value) || !value.inherits(&QScriptObject::info))
+ return false;
+ QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value));
+ QScriptObjectDelegate *delegate = object->delegate();
+ return (delegate && (delegate->type() == QScriptObjectDelegate::Variant));
+}
+
+inline bool QScriptEnginePrivate::isQObject(JSC::JSValue value)
+{
+#ifndef QT_NO_QOBJECT
+ if (!isObject(value) || !value.inherits(&QScriptObject::info))
+ return false;
+ QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value));
+ QScriptObjectDelegate *delegate = object->delegate();
+ return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject ||
+ (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject &&
+ static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->isQObject())));
+#else
+ return false;
+#endif
+}
+
+inline bool QScriptEnginePrivate::isQMetaObject(JSC::JSValue value)
+{
+#ifndef QT_NO_QOBJECT
+ return isObject(value) && JSC::asObject(value)->inherits(&QScript::QMetaObjectWrapperObject::info);
+#else
+ return false;
+#endif
+}
+
+inline bool QScriptEnginePrivate::toBool(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ bool result = value.toBoolean(exec);
+ restoreException(exec, savedException);
+ return result;
+}
+
+inline qsreal QScriptEnginePrivate::toInteger(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ qsreal result = value.toInteger(exec);
+ restoreException(exec, savedException);
+ return result;
+}
+
+inline qsreal QScriptEnginePrivate::toNumber(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ qsreal result = value.toNumber(exec);
+ restoreException(exec, savedException);
+ return result;
+}
+
+inline qint32 QScriptEnginePrivate::toInt32(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ qint32 result = value.toInt32(exec);
+ restoreException(exec, savedException);
+ return result;
+}
+
+inline quint32 QScriptEnginePrivate::toUInt32(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ quint32 result = value.toUInt32(exec);
+ restoreException(exec, savedException);
+ return result;
+}
+
+inline quint16 QScriptEnginePrivate::toUInt16(JSC::ExecState *exec, JSC::JSValue value)
+{
+ // ### no equivalent function in JSC
+ return QScript::ToUInt16(toNumber(exec, value));
+}
+
+inline JSC::UString QScriptEnginePrivate::toString(JSC::ExecState *exec, JSC::JSValue value)
+{
+ JSC::JSValue savedException;
+ saveException(exec, &savedException);
+ JSC::UString str = value.toString(exec);
+ if (exec && exec->hadException() && !str.size()) {
+ JSC::JSValue savedException2;
+ saveException(exec, &savedException2);
+ str = savedException2.toString(exec);
+ restoreException(exec, savedException2);
+ }
+ if (savedException)
+ restoreException(exec, savedException);
+ return str;
+}
+
+inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *exec, JSC::JSValue value)
+{
+ if (!isDate(value))
+ return QDateTime();
+ qsreal t = static_cast<JSC::DateInstance*>(JSC::asObject(value))->internalNumber();
+ return QScript::MsToDateTime(exec, t);
+}
+
+inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value)
+{
+#ifndef QT_NO_QOBJECT
+ if (isObject(value) && value.inherits(&QScriptObject::info)) {
+ QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value));
+ QScriptObjectDelegate *delegate = object->delegate();
+ if (!delegate)
+ return 0;
+ if (delegate->type() == QScriptObjectDelegate::QtObject)
+ return static_cast<QScript::QObjectDelegate*>(delegate)->value();
+ if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject)
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->toQObject(declarativeObject(value));
+ if (delegate->type() == QScriptObjectDelegate::Variant) {
+ QVariant var = variantValue(value);
+ int type = var.userType();
+ if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar))
+ return *reinterpret_cast<QObject* const *>(var.constData());
+ }
+ }
+#endif
+ return 0;
+}
+
+inline const QMetaObject *QScriptEnginePrivate::toQMetaObject(JSC::ExecState*, JSC::JSValue value)
+{
+#ifndef QT_NO_QOBJECT
+ if (isQMetaObject(value))
+ return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(value))->value();
+#endif
+ return 0;
+}
+
+inline QVariant &QScriptEnginePrivate::variantValue(JSC::JSValue value)
+{
+ Q_ASSERT(value.inherits(&QScriptObject::info));
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(value))->delegate();
+ Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant));
+ return static_cast<QScript::QVariantDelegate*>(delegate)->value();
+}
+
+inline void QScriptEnginePrivate::setVariantValue(JSC::JSValue objectValue, const QVariant &value)
+{
+ Q_ASSERT(objectValue.inherits(&QScriptObject::info));
+ QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(objectValue))->delegate();
+ Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant));
+ static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value);
+}
+
+inline QScriptDeclarativeClass *QScriptEnginePrivate::declarativeClass(JSC::JSValue v)
+{
+ if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(v));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass();
+}
+
+inline QScriptDeclarativeClass::Object *QScriptEnginePrivate::declarativeObject(JSC::JSValue v)
+{
+ if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(v));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object();
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp
new file mode 100644
index 0000000..1eb3933
--- /dev/null
+++ b/src/script/api/qscriptengineagent.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptengineagent.h"
+#include "qscriptengineagent_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+
+#include "CodeBlock.h"
+#include "Instruction.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.4
+ \class QScriptEngineAgent
+
+ \brief The QScriptEngineAgent class provides an interface to report events pertaining to QScriptEngine execution.
+
+ \ingroup script
+
+
+ The QScriptEngineAgent class is the basis of tools that monitor and/or control the execution of a
+ QScriptEngine, such as debuggers and profilers.
+
+ To process script loading and unloading events, reimplement the
+ scriptLoad() and scriptUnload() functions. scriptLoad() is called
+ after the input to QScriptEngine::evaluate() has been parsed, right
+ before the given script is executed. The engine assigns each
+ script an ID, which is available as one of the arguments to
+ scriptLoad(); subsequently, other event handlers can use the ID to
+ identify a particular script. One common usage of scriptLoad() is
+ to retain the script text, filename and base line number (the
+ original input to QScriptEngine::evaluate()), so that other event
+ handlers can e.g. map a line number to the corresponding line of
+ text.
+
+ scriptUnload() is called when the QScriptEngine has no further use
+ for a script; the QScriptEngineAgent may at this point safely
+ discard any resources associated with the script (such as the
+ script text). Note that after scriptUnload() has been called, the
+ QScriptEngine may reuse the relevant script ID for new scripts
+ (i.e. as argument to a subsequent call to scriptLoad()).
+
+ Evaluating the following script will result in scriptUnload()
+ being called immediately after evaluation has completed:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengineagent.cpp 0
+
+ Evaluating the following script will \b{not} result in a call to
+ scriptUnload() when evaluation has completed:
+
+ \snippet doc/src/snippets/code/src_script_qscriptengineagent.cpp 1
+
+ The script isn't unloaded because it defines a function (\c{cube})
+ that remains in the script environment after evaluation has
+ completed. If a subsequent script removed the \c{cube} function
+ (e.g. by setting it to \c{null}), scriptUnload() would be called
+ when the function is garbage collected. In general terms, a script
+ isn't unloaded until the engine has determined that none of its
+ contents is referenced.
+
+ To process script function calls and returns, reimplement the
+ functionEntry() and functionExit() functions. functionEntry() is
+ called when a script function is about to be executed;
+ functionExit() is called when a script function is about to return,
+ either normally or due to an exception.
+
+ To process individual script statements, reimplement
+ positionChange(). positionChange() is called each time the engine is
+ about to execute a new statement of a script, and thus offers the
+ finest level of script monitoring.
+
+ To process exceptions, reimplement exceptionThrow() and
+ exceptionCatch(). exceptionThrow() is called when a script exception
+ is thrown, before it has been handled. exceptionCatch() is called
+ when an exception handler is present, and execution is about to be
+ resumed at the handler code.
+
+ \sa QScriptEngine::setAgent(), QScriptContextInfo
+*/
+
+/*!
+ \enum QScriptEngineAgent::Extension
+
+ This enum specifies the possible extensions to a QScriptEngineAgent.
+
+ \value DebuggerInvocationRequest The agent handles \c{debugger} script statements.
+
+ \sa extension()
+*/
+
+
+void QScriptEngineAgentPrivate::attach()
+{
+ if (engine->originalGlobalObject()->debugger())
+ engine->originalGlobalObject()->setDebugger(0);
+ JSC::Debugger::attach(engine->originalGlobalObject());
+ if (!QScriptEnginePrivate::get(engine)->isEvaluating())
+ JSC::Debugger::recompileAllJSFunctions(engine->globalData);
+}
+
+void QScriptEngineAgentPrivate::detach()
+{
+ JSC::Debugger::detach(engine->originalGlobalObject());
+}
+
+void QScriptEngineAgentPrivate::returnEvent(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno)
+{
+ Q_UNUSED(frame);
+ Q_UNUSED(lineno);
+ Q_UNUSED(sourceID);
+}
+
+void QScriptEngineAgentPrivate::exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler)
+{
+ JSC::CallFrame *oldFrame = engine->currentFrame;
+ int oldAgentLineNumber = engine->agentLineNumber;
+ engine->currentFrame = frame.callFrame();
+ QScriptValue value(engine->scriptValueFromJSCValue(frame.exception()));
+ engine->agentLineNumber = value.property(QLatin1String("lineNumber")).toInt32();
+ q_ptr->exceptionThrow(sourceID, value, hasHandler);
+ engine->agentLineNumber = oldAgentLineNumber;
+ engine->currentFrame = oldFrame;
+ engine->setCurrentException(value);
+};
+
+void QScriptEngineAgentPrivate::exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID)
+{
+ JSC::CallFrame *oldFrame = engine->currentFrame;
+ engine->currentFrame = frame.callFrame();
+ QScriptValue value(engine->scriptValueFromJSCValue(frame.exception()));
+ q_ptr->exceptionCatch(sourceID, value);
+ engine->currentFrame = oldFrame;
+ engine->clearCurrentException();
+}
+
+void QScriptEngineAgentPrivate::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno/*, int column*/)
+{
+ QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID);
+ if (!source) {
+ // QTBUG-6108: We don't have the source for this script, so ignore.
+ return;
+ }
+// column = source->columnNumberFromOffset(column);
+ int column = 1;
+ JSC::CallFrame *oldFrame = engine->currentFrame;
+ int oldAgentLineNumber = engine->agentLineNumber;
+ engine->currentFrame = frame.callFrame();
+ engine->agentLineNumber = lineno;
+ q_ptr->positionChange(sourceID, lineno, column);
+ engine->currentFrame = oldFrame;
+ engine->agentLineNumber = oldAgentLineNumber;
+}
+
+void QScriptEngineAgentPrivate::functionExit(const JSC::JSValue& returnValue, intptr_t sourceID)
+{
+ QScriptValue result = engine->scriptValueFromJSCValue(returnValue);
+ q_ptr->functionExit(sourceID, result);
+ q_ptr->contextPop();
+}
+
+void QScriptEngineAgentPrivate::evaluateStop(const JSC::JSValue& returnValue, intptr_t sourceID)
+{
+ QScriptValue result = engine->scriptValueFromJSCValue(returnValue);
+ q_ptr->functionExit(sourceID, result);
+}
+
+void QScriptEngineAgentPrivate::didReachBreakpoint(const JSC::DebuggerCallFrame& frame,
+ intptr_t sourceID, int lineno/*, int column*/)
+{
+ if (q_ptr->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) {
+ QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID);
+ if (!source) {
+ // QTBUG-6108: We don't have the source for this script, so ignore.
+ return;
+ }
+// column = source->columnNumberFromOffset(column);
+ int column = 1;
+ JSC::CallFrame *oldFrame = engine->currentFrame;
+ int oldAgentLineNumber = engine->agentLineNumber;
+ engine->currentFrame = frame.callFrame();
+ engine->agentLineNumber = lineno;
+ QList<QVariant> args;
+ args << qint64(sourceID) << lineno << column;
+ q_ptr->extension(QScriptEngineAgent::DebuggerInvocationRequest, args);
+ engine->currentFrame = oldFrame;
+ engine->agentLineNumber = oldAgentLineNumber;
+ }
+};
+
+/*!
+ Constructs a QScriptEngineAgent object for the given \a engine.
+
+ The engine takes ownership of the agent.
+
+ Call QScriptEngine::setAgent() to make this agent the active
+ agent.
+*/
+QScriptEngineAgent::QScriptEngineAgent(QScriptEngine *engine)
+ : d_ptr(new QScriptEngineAgentPrivate())
+{
+ d_ptr->q_ptr = this;
+ d_ptr->engine = QScriptEnginePrivate::get(engine);
+ d_ptr->engine->ownedAgents.append(this);
+}
+
+/*!
+ \internal
+*/
+QScriptEngineAgent::QScriptEngineAgent(QScriptEngineAgentPrivate &dd, QScriptEngine *engine)
+ : d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->engine = QScriptEnginePrivate::get(engine);
+}
+
+/*!
+ Destroys this QScriptEngineAgent.
+*/
+QScriptEngineAgent::~QScriptEngineAgent()
+{
+ d_ptr->engine->agentDeleted(this); //### TODO: Can this throw?
+}
+
+/*!
+
+ This function is called when the engine has parsed a script and has
+ associated it with the given \a id. The id can be used to identify
+ this particular script in subsequent event notifications.
+
+ \a program, \a fileName and \a baseLineNumber are the original
+ arguments to the QScriptEngine::evaluate() call that triggered this
+ event.
+
+ This function is called just before the script is about to be
+ evaluated.
+
+ You can reimplement this function to record information about the
+ script; for example, by retaining the script text, you can obtain
+ the line of text corresponding to a line number in a subsequent
+ call to positionChange().
+
+ The default implementation does nothing.
+
+ \sa scriptUnload()
+*/
+void QScriptEngineAgent::scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int baseLineNumber)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(program);
+ Q_UNUSED(fileName);
+ Q_UNUSED(baseLineNumber);
+}
+
+/*!
+ This function is called when the engine has discarded the script
+ identified by the given \a id.
+
+ You can reimplement this function to clean up any resources you have
+ associated with the script.
+
+ The default implementation does nothing.
+
+ \sa scriptLoad()
+*/
+void QScriptEngineAgent::scriptUnload(qint64 id)
+{
+ Q_UNUSED(id);
+}
+
+/*!
+ This function is called when a new script context has been pushed.
+
+ The default implementation does nothing.
+
+ \sa contextPop(), functionEntry()
+*/
+void QScriptEngineAgent::contextPush()
+{
+}
+
+/*!
+ This function is called when the current script context is about to
+ be popped.
+
+ The default implementation does nothing.
+
+ \sa contextPush(), functionExit()
+*/
+void QScriptEngineAgent::contextPop()
+{
+}
+
+/*!
+ This function is called when a script function is called in the
+ engine. If the script function is not a native Qt Script function,
+ it resides in the script identified by \a scriptId; otherwise, \a
+ scriptId is -1.
+
+ This function is called just before execution of the script function
+ begins. You can obtain the QScriptContext associated with the
+ function call with QScriptEngine::currentContext(). The arguments
+ passed to the function are available.
+
+ Reimplement this function to handle this event. For example, a
+ debugger implementation could reimplement this function (and
+ functionExit()) to keep track of the call stack and provide
+ step-over functionality.
+
+ The default implementation does nothing.
+
+ \sa functionExit(), positionChange(), QScriptEngine::currentContext()
+*/
+void QScriptEngineAgent::functionEntry(qint64 scriptId)
+{
+ Q_UNUSED(scriptId);
+}
+
+/*!
+ This function is called when the currently executing script function
+ is about to return. If the script function is not a native Qt Script
+ function, it resides in the script identified by \a scriptId;
+ otherwise, \a scriptId is -1. The \a returnValue is the value that
+ the script function will return.
+
+ This function is called just before the script function returns.
+ You can still access the QScriptContext associated with the
+ script function call with QScriptEngine::currentContext().
+
+ If the engine's
+ \l{QScriptEngine::hasUncaughtException()}{hasUncaughtException}()
+ function returns true, the script function is exiting due to an
+ exception; otherwise, the script function is returning normally.
+
+ Reimplement this function to handle this event; typically you will
+ then also want to reimplement functionEntry().
+
+ The default implementation does nothing.
+
+ \sa functionEntry(), QScriptEngine::hasUncaughtException()
+*/
+void QScriptEngineAgent::functionExit(qint64 scriptId,
+ const QScriptValue &returnValue)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(returnValue);
+}
+
+/*!
+ This function is called when the engine is about to execute a new
+ statement in the script identified by \a scriptId. The statement
+ begins on the line and column specified by \a lineNumber
+ This event is not generated for native Qt Script functions.
+
+ Reimplement this function to handle this event. For example, a
+ debugger implementation could reimplement this function to provide
+ line-by-line stepping, and a profiler implementation could use it to
+ count the number of times each statement is executed.
+
+ The default implementation does nothing.
+
+ \note \a columnNumber is undefined
+
+ \sa scriptLoad(), functionEntry()
+*/
+void QScriptEngineAgent::positionChange(qint64 scriptId,
+ int lineNumber, int columnNumber)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(lineNumber);
+ Q_UNUSED(columnNumber);
+}
+
+/*!
+ This function is called when the given \a exception has occurred in
+ the engine, in the script identified by \a scriptId. If the
+ exception was thrown by a native Qt Script function, \a scriptId is
+ -1.
+
+ If \a hasHandler is true, there is a \c{catch} or \c{finally} block
+ that will handle the exception. If \a hasHandler is false, there is
+ no handler for the exception.
+
+ Reimplement this function if you want to handle this event. For
+ example, a debugger can notify the user when an uncaught exception
+ occurs (i.e. \a hasHandler is false).
+
+ The default implementation does nothing.
+
+ \sa exceptionCatch()
+*/
+void QScriptEngineAgent::exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+ Q_UNUSED(hasHandler);
+}
+
+/*!
+ This function is called when the given \a exception is about to be
+ caught, in the script identified by \a scriptId.
+
+ Reimplement this function if you want to handle this event.
+
+ The default implementation does nothing.
+
+ \sa exceptionThrow()
+*/
+void QScriptEngineAgent::exceptionCatch(qint64 scriptId,
+ const QScriptValue &exception)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+}
+
+#if 0
+/*!
+ This function is called when a property of the given \a object has
+ been added, changed or removed.
+
+ Reimplement this function if you want to handle this event.
+
+ The default implementation does nothing.
+*/
+void QScriptEngineAgent::propertyChange(qint64 scriptId,
+ const QScriptValue &object,
+ const QString &propertyName,
+ PropertyChange change)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(object);
+ Q_UNUSED(propertyName);
+ Q_UNUSED(change);
+}
+#endif
+
+/*!
+ Returns true if the QScriptEngineAgent supports the given \a
+ extension; otherwise, false is returned. By default, no extensions
+ are supported.
+
+ \sa extension()
+*/
+bool QScriptEngineAgent::supportsExtension(Extension extension) const
+{
+ Q_UNUSED(extension);
+ return false;
+}
+
+/*!
+ This virtual function can be reimplemented in a QScriptEngineAgent
+ subclass to provide support for extensions. The optional \a argument
+ can be provided as input to the \a extension; the result must be
+ returned in the form of a QVariant. You can call supportsExtension()
+ to check if an extension is supported by the QScriptEngineAgent. By
+ default, no extensions are supported, and this function returns an
+ invalid QVariant.
+
+ If you implement the DebuggerInvocationRequest extension, Qt Script
+ will call this function when a \c{debugger} statement is encountered
+ in a script. The \a argument is a QVariantList containing three
+ items: The first item is the scriptId (a qint64), the second item is
+ the line number (an int), and the third item is the column number
+ (an int).
+
+ \sa supportsExtension()
+*/
+QVariant QScriptEngineAgent::extension(Extension extension,
+ const QVariant &argument)
+{
+ Q_UNUSED(extension);
+ Q_UNUSED(argument);
+ return QVariant();
+}
+
+/*!
+ Returns the QScriptEngine that this agent is associated with.
+*/
+QScriptEngine *QScriptEngineAgent::engine() const
+{
+ Q_D(const QScriptEngineAgent);
+ return QScriptEnginePrivate::get(d->engine);
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptengineagent.h b/src/script/api/qscriptengineagent.h
new file mode 100644
index 0000000..0750313
--- /dev/null
+++ b/src/script/api/qscriptengineagent.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTENGINEAGENT_H
+#define QSCRIPTENGINEAGENT_H
+
+#include <QtCore/qobjectdefs.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptEngine;
+class QScriptValue;
+
+class QScriptEngineAgentPrivate;
+class Q_SCRIPT_EXPORT QScriptEngineAgent
+{
+public:
+ enum Extension {
+ DebuggerInvocationRequest
+ };
+
+ QScriptEngineAgent(QScriptEngine *engine);
+ virtual ~QScriptEngineAgent();
+
+ virtual void scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int baseLineNumber);
+ virtual void scriptUnload(qint64 id);
+
+ virtual void contextPush();
+ virtual void contextPop();
+
+ virtual void functionEntry(qint64 scriptId);
+ virtual void functionExit(qint64 scriptId,
+ const QScriptValue &returnValue);
+
+ virtual void positionChange(qint64 scriptId,
+ int lineNumber, int columnNumber);
+
+ virtual void exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler);
+ virtual void exceptionCatch(qint64 scriptId,
+ const QScriptValue &exception);
+
+ virtual bool supportsExtension(Extension extension) const;
+ virtual QVariant extension(Extension extension,
+ const QVariant &argument = QVariant());
+
+ QScriptEngine *engine() const;
+
+protected:
+ QScriptEngineAgent(QScriptEngineAgentPrivate &dd, QScriptEngine *engine);
+ QScopedPointer<QScriptEngineAgentPrivate> d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QScriptEngineAgent)
+ Q_DISABLE_COPY(QScriptEngineAgent)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptengineagent_p.h b/src/script/api/qscriptengineagent_p.h
new file mode 100644
index 0000000..abe4e9e
--- /dev/null
+++ b/src/script/api/qscriptengineagent_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTENGINEAGENT_P_H
+#define QSCRIPTENGINEAGENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+#include "Debugger.h"
+#include "qscriptengineagent.h"
+
+#include "CallFrame.h"
+#include "SourceCode.h"
+#include "UString.h"
+#include "DebuggerCallFrame.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEnginePrivate;
+
+class QScriptEngineAgent;
+class Q_SCRIPT_EXPORT QScriptEngineAgentPrivate : public JSC::Debugger
+{
+ Q_DECLARE_PUBLIC(QScriptEngineAgent)
+public:
+ static QScriptEngineAgent* get(QScriptEngineAgentPrivate* p) {return p->q_func();}
+ static QScriptEngineAgentPrivate* get(QScriptEngineAgent* p) {return p->d_func();}
+
+ QScriptEngineAgentPrivate(){}
+ virtual ~QScriptEngineAgentPrivate(){};
+
+ void attach();
+ void detach();
+
+ //scripts
+ virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int /*errorLine*/, const JSC::UString& /*errorMsg*/) {};
+ virtual void scriptUnload(qint64 id)
+ {
+ q_ptr->scriptUnload(id);
+ };
+ virtual void scriptLoad(qint64 id, const JSC::UString &program,
+ const JSC::UString &fileName, int baseLineNumber)
+ {
+ q_ptr->scriptLoad(id,program, fileName, baseLineNumber);
+ };
+
+ //exceptions
+ virtual void exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, bool hasHandler)
+ {
+ Q_UNUSED(frame);
+ Q_UNUSED(sourceID);
+ Q_UNUSED(lineno);
+ Q_UNUSED(hasHandler);
+ };
+ virtual void exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler);
+ virtual void exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID);
+
+ //statements
+ virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno/*, int column*/);
+ virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno)
+ {
+ Q_UNUSED(lineno);
+ q_ptr->contextPush();
+ q_ptr->functionEntry(sourceID);
+ };
+ virtual void returnEvent(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno);
+ virtual void willExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno)
+ {
+ Q_UNUSED(frame);
+ Q_UNUSED(sourceID);
+ Q_UNUSED(lineno);
+ };
+ virtual void didExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno)
+ {
+ Q_UNUSED(frame);
+ Q_UNUSED(sourceID);
+ Q_UNUSED(lineno);
+ };
+ virtual void functionExit(const JSC::JSValue& returnValue, intptr_t sourceID);
+ //others
+ virtual void didReachBreakpoint(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno/*, int column*/);
+
+ virtual void evaluateStart(intptr_t sourceID)
+ {
+ q_ptr->functionEntry(sourceID);
+ }
+ virtual void evaluateStop(const JSC::JSValue& returnValue, intptr_t sourceID);
+
+ QScriptEnginePrivate *engine;
+ QScriptEngineAgent *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptextensioninterface.h b/src/script/api/qscriptextensioninterface.h
new file mode 100644
index 0000000..4e983b3
--- /dev/null
+++ b/src/script/api/qscriptextensioninterface.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTEXTENSIONINTERFACE_H
+#define QSCRIPTEXTENSIONINTERFACE_H
+
+#include <QtCore/qfactoryinterface.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptEngine;
+
+struct Q_SCRIPT_EXPORT QScriptExtensionInterface
+ : public QFactoryInterface
+{
+ virtual void initialize(const QString &key, QScriptEngine *engine) = 0;
+};
+
+Q_DECLARE_INTERFACE(QScriptExtensionInterface,
+ "com.trolltech.Qt.QScriptExtensionInterface/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTEXTENSIONINTERFACE_H
diff --git a/src/script/api/qscriptextensionplugin.cpp b/src/script/api/qscriptextensionplugin.cpp
new file mode 100644
index 0000000..3c0de1a
--- /dev/null
+++ b/src/script/api/qscriptextensionplugin.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptextensionplugin.h"
+
+#include "qscriptvalue.h"
+#include "qscriptengine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.3
+ \class QScriptExtensionPlugin
+ \brief The QScriptExtensionPlugin class provides an abstract base for custom QScript extension plugins.
+
+ \ingroup plugins
+
+ QScriptExtensionPlugin is a plugin interface that makes it
+ possible to offer extensions that can be loaded dynamically into
+ applications using the QScriptEngine class.
+
+ Writing a script extension plugin is achieved by subclassing this
+ base class, reimplementing the pure virtual keys() and initialize()
+ functions, and exporting the class using the Q_EXPORT_PLUGIN2()
+ macro. See \l {How to Create Qt Plugins} for details.
+
+ \sa QScriptEngine::importExtension(), {Creating QtScript Extensions}
+*/
+
+/*!
+ \fn QStringList QScriptExtensionPlugin::keys() const
+
+ Returns the list of keys this plugin supports.
+
+ These keys are usually the names of the "modules" or "packages"
+ that are implemented in the plugin (e.g. \c{com.mycompany.MyProduct}).
+
+ \sa initialize()
+*/
+
+/*!
+ \fn void QScriptExtensionPlugin::initialize(const QString& key, QScriptEngine *engine)
+
+ Initializes the extension specified by \a key in the given \a engine.
+ The key must come from the set of keys().
+
+ \sa keys()
+*/
+
+/*!
+ Constructs a script extension plugin with the given \a parent.
+
+ Note that this constructor is invoked automatically by the
+ Q_EXPORT_PLUGIN2() macro, so there is no need for calling it
+ explicitly.
+*/
+QScriptExtensionPlugin::QScriptExtensionPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the script extension plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QScriptExtensionPlugin::~QScriptExtensionPlugin()
+{
+}
+
+/*!
+
+ This function is provided for convenience when reimplementing
+ initialize(). It splits the given \a key on \c{'.'} (dot), and
+ ensures that there's a corresponding path of objects in the
+ environment of the given \a engine, creating new objects to complete
+ the path if necessary. E.g. if the key is "com.trolltech", after
+ the call to setupPackage() the script expression \c{com.trolltech}
+ will evaluate to an object. More specifically, the engine's Global
+ Object will have a property called "com", which in turn has a
+ property called "trolltech".
+
+ Use this function to avoid global namespace pollution when installing
+ your extensions in the engine.
+
+ \sa initialize()
+*/
+QScriptValue QScriptExtensionPlugin::setupPackage(
+ const QString &key, QScriptEngine *engine) const
+{
+ QStringList components = key.split(QLatin1Char('.'));
+ QScriptValue o = engine->globalObject();
+ for (int i = 0; i < components.count(); ++i) {
+ QScriptValue oo = o.property(components.at(i));
+ if (!oo.isValid()) {
+ oo = engine->newObject();
+ o.setProperty(components.at(i), oo);
+ }
+ o = oo;
+ }
+ return o;
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptextensionplugin.h b/src/script/api/qscriptextensionplugin.h
new file mode 100644
index 0000000..c5f37ab
--- /dev/null
+++ b/src/script/api/qscriptextensionplugin.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTEXTENSIONPLUGIN_H
+#define QSCRIPTEXTENSIONPLUGIN_H
+
+#include <QtCore/qplugin.h>
+
+#include <QtScript/qscriptextensioninterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptValue;
+
+class Q_SCRIPT_EXPORT QScriptExtensionPlugin : public QObject,
+ public QScriptExtensionInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QScriptExtensionInterface:QFactoryInterface)
+public:
+ explicit QScriptExtensionPlugin(QObject *parent = 0);
+ ~QScriptExtensionPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual void initialize(const QString &key, QScriptEngine *engine) = 0;
+
+ QScriptValue setupPackage(const QString &key, QScriptEngine *engine) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTEXTENSIONPLUGIN_H
diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp
new file mode 100644
index 0000000..c0e2656
--- /dev/null
+++ b/src/script/api/qscriptprogram.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptprogram.h"
+#include "qscriptprogram_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+
+#include "SamplingTool.h"
+#include "Executable.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.7
+ \class QScriptProgram
+
+ \brief The QScriptProgram class encapsulates a Qt Script program.
+
+ \ingroup script
+
+ QScriptProgram retains the compiled representation of the script if
+ possible. Thus, QScriptProgram can be used to evaluate the same
+ script multiple times more efficiently.
+
+ \code
+ QScriptEngine engine;
+ QScriptProgram program("1 + 2");
+ QScriptValue result = engine.evaluate(program);
+ \endcode
+*/
+
+QScriptProgramPrivate::QScriptProgramPrivate(const QString &src,
+ const QString &fn,
+ int ln)
+ : sourceCode(src), fileName(fn), firstLineNumber(ln),
+ engine(0), _executable(0), sourceId(-1), isCompiled(false)
+{
+ ref = 0;
+}
+
+QScriptProgramPrivate::~QScriptProgramPrivate()
+{
+ if (engine) {
+ QScript::APIShim shim(engine);
+ _executable.clear();
+ engine->unregisterScriptProgram(this);
+ }
+}
+
+QScriptProgramPrivate *QScriptProgramPrivate::get(const QScriptProgram &q)
+{
+ return const_cast<QScriptProgramPrivate*>(q.d_func());
+}
+
+JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec,
+ QScriptEnginePrivate *eng)
+{
+ if (_executable) {
+ if (eng == engine)
+ return _executable.get();
+ // "Migrating" to another engine; clean up old state
+ QScript::APIShim shim(engine);
+ _executable.clear();
+ engine->unregisterScriptProgram(this);
+ }
+ WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
+ = QScript::UStringSourceProviderWithFeedback::create(sourceCode, fileName, firstLineNumber, eng);
+ sourceId = provider->asID();
+ JSC::SourceCode source(provider, firstLineNumber); //after construction of SourceCode provider variable will be null.
+ _executable = JSC::EvalExecutable::create(exec, source);
+ engine = eng;
+ engine->registerScriptProgram(this);
+ isCompiled = false;
+ return _executable.get();
+}
+
+void QScriptProgramPrivate::detachFromEngine()
+{
+ _executable.clear();
+ sourceId = -1;
+ isCompiled = false;
+ engine = 0;
+}
+
+/*!
+ Constructs a null QScriptProgram.
+*/
+QScriptProgram::QScriptProgram()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Constructs a new QScriptProgram with the given \a sourceCode, \a
+ fileName and \a firstLineNumber.
+*/
+QScriptProgram::QScriptProgram(const QString &sourceCode,
+ const QString fileName,
+ int firstLineNumber)
+ : d_ptr(new QScriptProgramPrivate(sourceCode, fileName, firstLineNumber))
+{
+}
+
+/*!
+ Constructs a new QScriptProgram that is a copy of \a other.
+*/
+QScriptProgram::QScriptProgram(const QScriptProgram &other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ Destroys this QScriptProgram.
+*/
+QScriptProgram::~QScriptProgram()
+{
+}
+
+/*!
+ Assigns the \a other value to this QScriptProgram.
+*/
+QScriptProgram &QScriptProgram::operator=(const QScriptProgram &other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns true if this QScriptProgram is null; otherwise
+ returns false.
+*/
+bool QScriptProgram::isNull() const
+{
+ Q_D(const QScriptProgram);
+ return (d == 0);
+}
+
+/*!
+ Returns the source code of this program.
+*/
+QString QScriptProgram::sourceCode() const
+{
+ Q_D(const QScriptProgram);
+ if (!d)
+ return QString();
+ return d->sourceCode;
+}
+
+/*!
+ Returns the filename associated with this program.
+*/
+QString QScriptProgram::fileName() const
+{
+ Q_D(const QScriptProgram);
+ if (!d)
+ return QString();
+ return d->fileName;
+}
+
+/*!
+ Returns the line number associated with this program.
+*/
+int QScriptProgram::firstLineNumber() const
+{
+ Q_D(const QScriptProgram);
+ if (!d)
+ return -1;
+ return d->firstLineNumber;
+}
+
+/*!
+ Returns true if this QScriptProgram is equal to \a other;
+ otherwise returns false.
+*/
+bool QScriptProgram::operator==(const QScriptProgram &other) const
+{
+ Q_D(const QScriptProgram);
+ if (d == other.d_func())
+ return true;
+ return (sourceCode() == other.sourceCode())
+ && (fileName() == other.fileName())
+ && (firstLineNumber() == other.firstLineNumber());
+}
+
+/*!
+ Returns true if this QScriptProgram is not equal to \a other;
+ otherwise returns false.
+*/
+bool QScriptProgram::operator!=(const QScriptProgram &other) const
+{
+ return !operator==(other);
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptprogram.h b/src/script/api/qscriptprogram.h
new file mode 100644
index 0000000..b31c528
--- /dev/null
+++ b/src/script/api/qscriptprogram.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTPROGRAM_H
+#define QSCRIPTPROGRAM_H
+
+#include <QtCore/qsharedpointer.h>
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptProgramPrivate;
+class Q_SCRIPT_EXPORT QScriptProgram
+{
+public:
+ QScriptProgram();
+ QScriptProgram(const QString &sourceCode,
+ const QString fileName = QString(),
+ int firstLineNumber = 1);
+ QScriptProgram(const QScriptProgram &other);
+ ~QScriptProgram();
+
+ QScriptProgram &operator=(const QScriptProgram &other);
+
+ bool isNull() const;
+
+ QString sourceCode() const;
+ QString fileName() const;
+ int firstLineNumber() const;
+
+ bool operator==(const QScriptProgram &other) const;
+ bool operator!=(const QScriptProgram &other) const;
+
+private:
+ QExplicitlySharedDataPointer<QScriptProgramPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QScriptProgram)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTPROGRAM_H
diff --git a/src/script/api/qscriptprogram_p.h b/src/script/api/qscriptprogram_p.h
new file mode 100644
index 0000000..e7809ab
--- /dev/null
+++ b/src/script/api/qscriptprogram_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTPROGRAM_P_H
+#define QSCRIPTPROGRAM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+#include "RefPtr.h"
+
+namespace JSC
+{
+ class EvalExecutable;
+ class ExecState;
+}
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEnginePrivate;
+
+class QScriptProgramPrivate
+{
+public:
+ QScriptProgramPrivate(const QString &sourceCode,
+ const QString &fileName,
+ int firstLineNumber);
+ ~QScriptProgramPrivate();
+
+ static QScriptProgramPrivate *get(const QScriptProgram &q);
+
+ JSC::EvalExecutable *executable(JSC::ExecState *exec,
+ QScriptEnginePrivate *engine);
+ void detachFromEngine();
+
+ QBasicAtomicInt ref;
+
+ QString sourceCode;
+ QString fileName;
+ int firstLineNumber;
+
+ QScriptEnginePrivate *engine;
+ WTF::RefPtr<JSC::EvalExecutable> _executable;
+ intptr_t sourceId;
+ bool isCompiled;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptstring.cpp b/src/script/api/qscriptstring.cpp
new file mode 100644
index 0000000..2930c9e
--- /dev/null
+++ b/src/script/api/qscriptstring.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h" // compile on Windows
+#include "qscriptstring.h"
+#include "qscriptstring_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.4
+ \class QScriptString
+
+ \brief The QScriptString class acts as a handle to "interned" strings in a QScriptEngine.
+
+ \ingroup script
+
+
+ QScriptString can be used to achieve faster (repeated)
+ property getting/setting, and comparison of property names, of
+ script objects.
+
+ To get a QScriptString representation of a string, pass the string
+ to QScriptEngine::toStringHandle(). The typical usage pattern is to
+ register one or more pre-defined strings when setting up your script
+ environment, then subsequently use the relevant QScriptString as
+ argument to e.g. QScriptValue::property().
+
+ Call the toString() function to obtain the string that a
+ QScriptString represents.
+
+ Call the toArrayIndex() function to convert a QScriptString to an
+ array index. This is useful when using QScriptClass to implement
+ array-like objects.
+*/
+
+/*!
+ Constructs an invalid QScriptString.
+*/
+QScriptString::QScriptString()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Constructs a new QScriptString that is a copy of \a other.
+*/
+QScriptString::QScriptString(const QScriptString &other)
+ : d_ptr(other.d_ptr)
+{
+ if (d_func() && (d_func()->type == QScriptStringPrivate::StackAllocated)) {
+ Q_ASSERT(d_func()->ref != 1);
+ d_ptr.detach();
+ d_func()->ref = 1;
+ d_func()->type = QScriptStringPrivate::HeapAllocated;
+ d_func()->engine->registerScriptString(d_func());
+ }
+}
+
+/*!
+ Destroys this QScriptString.
+*/
+QScriptString::~QScriptString()
+{
+ Q_D(QScriptString);
+ if (d) {
+ switch (d->type) {
+ case QScriptStringPrivate::StackAllocated:
+ Q_ASSERT(d->ref == 1);
+ d->ref.ref(); // avoid deletion
+ break;
+ case QScriptStringPrivate::HeapAllocated:
+ if (d->engine && (d->ref == 1)) {
+ // Make sure the identifier is removed from the correct engine.
+ QScript::APIShim shim(d->engine);
+ d->identifier = JSC::Identifier();
+ d->engine->unregisterScriptString(d);
+ }
+ break;
+ }
+ }
+}
+
+/*!
+ Assigns the \a other value to this QScriptString.
+*/
+QScriptString &QScriptString::operator=(const QScriptString &other)
+{
+ if (d_func() && d_func()->engine && (d_func()->ref == 1) && (d_func()->type == QScriptStringPrivate::HeapAllocated)) {
+ // current d_ptr will be deleted at the assignment below, so unregister it first
+ d_func()->engine->unregisterScriptString(d_func());
+ }
+ d_ptr = other.d_ptr;
+ if (d_func() && (d_func()->type == QScriptStringPrivate::StackAllocated)) {
+ Q_ASSERT(d_func()->ref != 1);
+ d_ptr.detach();
+ d_func()->ref = 1;
+ d_func()->type = QScriptStringPrivate::HeapAllocated;
+ d_func()->engine->registerScriptString(d_func());
+ }
+ return *this;
+}
+
+/*!
+ Returns true if this QScriptString is valid; otherwise
+ returns false.
+*/
+bool QScriptString::isValid() const
+{
+ return QScriptStringPrivate::isValid(*this);
+}
+
+/*!
+ Returns true if this QScriptString is equal to \a other;
+ otherwise returns false.
+*/
+bool QScriptString::operator==(const QScriptString &other) const
+{
+ Q_D(const QScriptString);
+ if (!d || !other.d_func())
+ return d == other.d_func();
+ return d->identifier == other.d_func()->identifier;
+}
+
+/*!
+ Returns true if this QScriptString is not equal to \a other;
+ otherwise returns false.
+*/
+bool QScriptString::operator!=(const QScriptString &other) const
+{
+ return !operator==(other);
+}
+
+/*!
+ \since 4.6
+
+ Attempts to convert this QScriptString to a QtScript array index,
+ and returns the result.
+
+ If a conversion error occurs, *\a{ok} is set to false; otherwise
+ *\a{ok} is set to true.
+*/
+quint32 QScriptString::toArrayIndex(bool *ok) const
+{
+ Q_D(const QScriptString);
+ if (!d) {
+ if (ok)
+ *ok = false;
+ return -1;
+ }
+ bool tmp;
+ bool *okok = ok ? ok : &tmp;
+ quint32 result = d->identifier.toArrayIndex(okok);
+ if (!*okok)
+ result = -1;
+ return result;
+}
+
+/*!
+ Returns the string that this QScriptString represents, or a
+ null string if this QScriptString is not valid.
+
+ \sa isValid()
+*/
+QString QScriptString::toString() const
+{
+ Q_D(const QScriptString);
+ if (!d || !d->engine)
+ return QString();
+ return d->identifier.ustring();
+}
+
+/*!
+ Returns the string that this QScriptString represents, or a
+ null string if this QScriptString is not valid.
+
+ \sa toString()
+*/
+QScriptString::operator QString() const
+{
+ return toString();
+}
+
+uint qHash(const QScriptString &key)
+{
+ QScriptStringPrivate *d = QScriptStringPrivate::get(key);
+ if (!d)
+ return 0;
+ return qHash(d->identifier.ustring().rep());
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptstring.h b/src/script/api/qscriptstring.h
new file mode 100644
index 0000000..a556fc5
--- /dev/null
+++ b/src/script/api/qscriptstring.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTSTRING_H
+#define QSCRIPTSTRING_H
+
+#include <QtCore/qstring.h>
+
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptStringPrivate;
+class Q_SCRIPT_EXPORT QScriptString
+{
+public:
+ QScriptString();
+ QScriptString(const QScriptString &other);
+ ~QScriptString();
+
+ QScriptString &operator=(const QScriptString &other);
+
+ bool isValid() const;
+
+ bool operator==(const QScriptString &other) const;
+ bool operator!=(const QScriptString &other) const;
+
+ quint32 toArrayIndex(bool *ok = 0) const;
+
+ QString toString() const;
+ operator QString() const;
+
+private:
+ QExplicitlySharedDataPointer<QScriptStringPrivate> d_ptr;
+ friend class QScriptValue;
+ Q_DECLARE_PRIVATE(QScriptString)
+};
+
+Q_SCRIPT_EXPORT uint qHash(const QScriptString &key);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTSTRING_H
diff --git a/src/script/api/qscriptstring_p.h b/src/script/api/qscriptstring_p.h
new file mode 100644
index 0000000..b632140
--- /dev/null
+++ b/src/script/api/qscriptstring_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTSTRING_P_H
+#define QSCRIPTSTRING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+#include "Identifier.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEnginePrivate;
+class QScriptStringPrivate
+{
+public:
+ enum AllocationType {
+ StackAllocated,
+ HeapAllocated
+ };
+
+ inline QScriptStringPrivate(QScriptEnginePrivate *engine, const JSC::Identifier &id,
+ AllocationType type);
+ inline ~QScriptStringPrivate();
+ static inline void init(QScriptString &q, QScriptStringPrivate *d);
+
+ static inline QScriptStringPrivate *get(const QScriptString &q);
+
+ inline void detachFromEngine();
+
+ static inline bool isValid(const QScriptString &q);
+
+ QBasicAtomicInt ref;
+ QScriptEnginePrivate *engine;
+ JSC::Identifier identifier;
+ AllocationType type;
+
+ // linked list of engine's script values
+ QScriptStringPrivate *prev;
+ QScriptStringPrivate *next;
+};
+
+inline QScriptStringPrivate::QScriptStringPrivate(QScriptEnginePrivate *e, const JSC::Identifier &id,
+ AllocationType tp)
+ : engine(e), identifier(id), type(tp), prev(0), next(0)
+{
+ ref = 0;
+}
+
+inline QScriptStringPrivate::~QScriptStringPrivate()
+{
+}
+
+inline void QScriptStringPrivate::init(QScriptString &q, QScriptStringPrivate *d)
+{
+ q.d_ptr = d;
+}
+
+inline QScriptStringPrivate *QScriptStringPrivate::get(const QScriptString &q)
+{
+ return const_cast<QScriptStringPrivate*>(q.d_func());
+}
+
+inline void QScriptStringPrivate::detachFromEngine()
+{
+ engine = 0;
+ identifier = JSC::Identifier();
+}
+
+inline bool QScriptStringPrivate::isValid(const QScriptString &q)
+{
+ return (q.d_ptr && q.d_ptr->engine);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp
new file mode 100644
index 0000000..91ce9c8
--- /dev/null
+++ b/src/script/api/qscriptvalue.cpp
@@ -0,0 +1,2136 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptvalue.h"
+
+#include "qscriptvalue_p.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "qscriptstring_p.h"
+
+#include "JSGlobalObject.h"
+#include "JSImmediate.h"
+#include "JSObject.h"
+#include "JSValue.h"
+#include "JSFunction.h"
+#include "Identifier.h"
+#include "Operations.h"
+#include "Arguments.h"
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qnumeric.h>
+
+/*!
+ \since 4.3
+ \class QScriptValue
+
+ \brief The QScriptValue class acts as a container for the Qt Script data types.
+
+ \ingroup script
+ \mainclass
+
+ QScriptValue supports the types defined in the \l{ECMA-262}
+ standard: The primitive types, which are Undefined, Null, Boolean,
+ Number, and String; and the Object type. Additionally, Qt Script
+ has built-in support for QVariant, QObject and QMetaObject.
+
+ For the object-based types (including Date and RegExp), use the
+ newT() functions in QScriptEngine (e.g. QScriptEngine::newObject())
+ to create a QScriptValue of the desired type. For the primitive types,
+ use one of the QScriptValue constructor overloads.
+
+ The methods named isT() (e.g. isBool(), isUndefined()) can be
+ used to test if a value is of a certain type. The methods named
+ toT() (e.g. toBool(), toString()) can be used to convert a
+ QScriptValue to another type. You can also use the generic
+ qscriptvalue_cast() function.
+
+ Object values have zero or more properties which are themselves
+ QScriptValues. Use setProperty() to set a property of an object, and
+ call property() to retrieve the value of a property.
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0
+
+ Each property can have a set of attributes; these are specified as
+ the third (optional) argument to setProperty(). The attributes of a
+ property can be queried by calling the propertyFlags() function. The
+ following code snippet creates a property that cannot be modified by
+ script code:
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1
+
+ If you want to iterate over the properties of a script object, use
+ the QScriptValueIterator class.
+
+ Object values have an internal \c{prototype} property, which can be
+ accessed with prototype() and setPrototype(). Properties added to a
+ prototype are shared by all objects having that prototype; this is
+ referred to as prototype-based inheritance. In practice, it means
+ that (by default) the property() function will automatically attempt
+ to look up look the property in the prototype() (and in the
+ prototype of the prototype(), and so on), if the object itself does
+ not have the requested property. Note that this prototype-based
+ lookup is not performed by setProperty(); setProperty() will always
+ create the property in the script object itself. For more
+ information, see the \l{QtScript} documentation.
+
+ Function objects (objects for which isFunction() returns true) can
+ be invoked by calling call(). Constructor functions can be used to
+ construct new objects by calling construct().
+
+ Use equals(), strictlyEquals() and lessThan() to compare a QScriptValue
+ to another.
+
+ Object values can have custom data associated with them; see the
+ setData() and data() functions. By default, this data is not
+ accessible to scripts; it can be used to store any data you want to
+ associate with the script object. Typically this is used by custom
+ class objects (see QScriptClass) to store a C++ type that contains
+ the "native" object data.
+
+ Note that a QScriptValue for which isObject() is true only carries a
+ reference to an actual object; copying the QScriptValue will only
+ copy the object reference, not the object itself. If you want to
+ clone an object (i.e. copy an object's properties to another
+ object), you can do so with the help of a \c{for-in} statement in
+ script code, or QScriptValueIterator in C++.
+
+ \sa QScriptEngine, QScriptValueIterator
+*/
+
+/*!
+ \enum QScriptValue::SpecialValue
+
+ This enum is used to specify a single-valued type.
+
+ \value UndefinedValue An undefined value.
+
+ \value NullValue A null value.
+*/
+
+/*!
+ \enum QScriptValue::PropertyFlag
+
+ This enum describes the attributes of a property.
+
+ \value ReadOnly The property is read-only. Attempts by Qt Script code to write to the property will be ignored.
+
+ \value Undeletable Attempts by Qt Script code to \c{delete} the property will be ignored.
+
+ \value SkipInEnumeration The property is not to be enumerated by a \c{for-in} enumeration.
+
+ \value PropertyGetter The property is defined by a function which will be called to get the property value.
+
+ \value PropertySetter The property is defined by a function which will be called to set the property value.
+
+ \omitvalue QObjectMember This flag is used to indicate that an existing property is a QObject member (a property or method).
+
+ \value KeepExistingFlags This value is used to indicate to setProperty() that the property's flags should be left unchanged. If the property doesn't exist, the default flags (0) will be used.
+
+ \omitvalue UserRange Flags in this range are not used by Qt Script, and can be used for custom purposes.
+*/
+
+/*!
+ \enum QScriptValue::ResolveFlag
+
+ This enum specifies how to look up a property of an object.
+
+ \value ResolveLocal Only check the object's own properties.
+
+ \value ResolvePrototype Check the object's own properties first, then search the prototype chain. This is the default.
+
+ \omitvalue ResolveScope Check the object's own properties first, then search the scope chain.
+
+ \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain.
+*/
+
+QT_BEGIN_NAMESPACE
+
+void QScriptValuePrivate::detachFromEngine()
+{
+ if (isJSC())
+ jscValue = JSC::JSValue();
+ engine = 0;
+}
+
+/*!
+ \internal
+*/
+QScriptValue::QScriptValue(QScriptValuePrivate *d)
+ : d_ptr(d)
+{
+}
+
+/*!
+ Constructs an invalid QScriptValue.
+*/
+QScriptValue::QScriptValue()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Destroys this QScriptValue.
+*/
+QScriptValue::~QScriptValue()
+{
+}
+
+/*!
+ Constructs a new QScriptValue that is a copy of \a other.
+
+ Note that if \a other is an object (i.e., isObject() would return
+ true), then only a reference to the underlying object is copied into
+ the new script value (i.e., the object itself is not copied).
+*/
+QScriptValue::QScriptValue(const QScriptValue &other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QScriptValue with the special \a value and
+ registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ switch (value) {
+ case NullValue:
+ d_ptr->initFrom(JSC::jsNull());
+ break;
+ case UndefinedValue:
+ d_ptr->initFrom(JSC::jsUndefined());
+ break;
+ }
+}
+
+/*!
+ \obsolete
+
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, bool value)
+
+ Constructs a new QScriptValue with the boolean \a value and
+ registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine *engine, bool val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ d_ptr->initFrom(JSC::jsBoolean(val));
+}
+
+/*!
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, int value)
+ \obsolete
+
+ Constructs a new QScriptValue with the integer \a value and
+ registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine *engine, int val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ if (engine) {
+ QScript::APIShim shim(d_ptr->engine);
+ JSC::ExecState *exec = d_ptr->engine->currentFrame;
+ d_ptr->initFrom(JSC::jsNumber(exec, val));
+ } else
+ d_ptr->initFrom(val);
+}
+
+/*!
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, uint value)
+ \obsolete
+
+ Constructs a new QScriptValue with the unsigned integer \a value and
+ registers it with the script \a engine.
+ */
+QScriptValue::QScriptValue(QScriptEngine *engine, uint val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ if (engine) {
+ QScript::APIShim shim(d_ptr->engine);
+ JSC::ExecState *exec = d_ptr->engine->currentFrame;
+ d_ptr->initFrom(JSC::jsNumber(exec, val));
+ } else
+ d_ptr->initFrom(val);
+}
+
+/*!
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, qsreal value)
+ \obsolete
+
+ Constructs a new QScriptValue with the qsreal \a value and
+ registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ if (engine) {
+ QScript::APIShim shim(d_ptr->engine);
+ JSC::ExecState *exec = d_ptr->engine->currentFrame;
+ d_ptr->initFrom(JSC::jsNumber(exec, val));
+ } else
+ d_ptr->initFrom(val);
+}
+
+/*!
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, const QString &value)
+ \obsolete
+
+ Constructs a new QScriptValue with the string \a value and
+ registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ if (engine) {
+ QScript::APIShim shim(d_ptr->engine);
+ JSC::ExecState *exec = d_ptr->engine->currentFrame;
+ d_ptr->initFrom(JSC::jsString(exec, val));
+ } else {
+ d_ptr->initFrom(val);
+ }
+}
+
+/*!
+ \fn QScriptValue::QScriptValue(QScriptEngine *engine, const char *value)
+ \obsolete
+
+ Constructs a new QScriptValue with the string \a value and
+ registers it with the script \a engine.
+*/
+
+#ifndef QT_NO_CAST_FROM_ASCII
+QScriptValue::QScriptValue(QScriptEngine *engine, const char *val)
+ : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
+{
+ if (engine) {
+ QScript::APIShim shim(d_ptr->engine);
+ JSC::ExecState *exec = d_ptr->engine->currentFrame;
+ d_ptr->initFrom(JSC::jsString(exec, val));
+ } else {
+ d_ptr->initFrom(QString::fromAscii(val));
+ }
+}
+#endif
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a special \a value.
+*/
+QScriptValue::QScriptValue(SpecialValue value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ switch (value) {
+ case NullValue:
+ d_ptr->initFrom(JSC::jsNull());
+ break;
+ case UndefinedValue:
+ d_ptr->initFrom(JSC::jsUndefined());
+ break;
+ }
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a boolean \a value.
+*/
+QScriptValue::QScriptValue(bool value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(JSC::jsBoolean(value));
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(int value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(value);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(uint value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(value);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(qsreal value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(value);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a string \a value.
+*/
+QScriptValue::QScriptValue(const QString &value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(value);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a string \a value.
+*/
+QScriptValue::QScriptValue(const QLatin1String &value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(value);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a new QScriptValue with a string \a value.
+*/
+
+#ifndef QT_NO_CAST_FROM_ASCII
+QScriptValue::QScriptValue(const char *value)
+ : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
+{
+ d_ptr->initFrom(QString::fromAscii(value));
+}
+#endif
+
+/*!
+ Assigns the \a other value to this QScriptValue.
+
+ Note that if \a other is an object (isObject() returns true),
+ only a reference to the underlying object will be assigned;
+ the object itself will not be copied.
+*/
+QScriptValue &QScriptValue::operator=(const QScriptValue &other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns true if this QScriptValue is an object of the Error class;
+ otherwise returns false.
+
+ \sa QScriptContext::throwError()
+*/
+bool QScriptValue::isError() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isError(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is an object of the Array class;
+ otherwise returns false.
+
+ \sa QScriptEngine::newArray()
+*/
+bool QScriptValue::isArray() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isArray(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is an object of the Date class;
+ otherwise returns false.
+
+ \sa QScriptEngine::newDate()
+*/
+bool QScriptValue::isDate() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isDate(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is an object of the RegExp class;
+ otherwise returns false.
+
+ \sa QScriptEngine::newRegExp()
+*/
+bool QScriptValue::isRegExp() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isRegExp(d->jscValue);
+}
+
+/*!
+ If this QScriptValue is an object, returns the internal prototype
+ (\c{__proto__} property) of this object; otherwise returns an
+ invalid QScriptValue.
+
+ \sa setPrototype(), isObject()
+*/
+QScriptValue QScriptValue::prototype() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ return d->engine->scriptValueFromJSCValue(JSC::asObject(d->jscValue)->prototype());
+}
+
+/*!
+ If this QScriptValue is an object, sets the internal prototype
+ (\c{__proto__} property) of this object to be \a prototype;
+ otherwise does nothing.
+
+ The internal prototype should not be confused with the public
+ property with name "prototype"; the public prototype is usually
+ only set on functions that act as constructors.
+
+ \sa prototype(), isObject()
+*/
+void QScriptValue::setPrototype(const QScriptValue &prototype)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+
+ JSC::JSValue other = d->engine->scriptValueToJSCValue(prototype);
+ if (!other || !(other.isObject() || other.isNull()))
+ return;
+
+ if (QScriptValuePrivate::getEngine(prototype)
+ && (QScriptValuePrivate::getEngine(prototype) != d->engine)) {
+ qWarning("QScriptValue::setPrototype() failed: "
+ "cannot set a prototype created in "
+ "a different engine");
+ return;
+ }
+ JSC::JSObject *thisObject = JSC::asObject(d->jscValue);
+
+ // check for cycle
+ JSC::JSValue nextPrototypeValue = other;
+ while (nextPrototypeValue && nextPrototypeValue.isObject()) {
+ JSC::JSObject *nextPrototype = JSC::asObject(nextPrototypeValue);
+ if (nextPrototype == thisObject) {
+ qWarning("QScriptValue::setPrototype() failed: cyclic prototype value");
+ return;
+ }
+ nextPrototypeValue = nextPrototype->prototype();
+ }
+
+ thisObject->setPrototype(other);
+
+ // Sync the internal Global Object prototype if appropriate.
+ if (((thisObject == d->engine->originalGlobalObjectProxy)
+ && !d->engine->customGlobalObject())
+ || (thisObject == d->engine->customGlobalObject())) {
+ d->engine->originalGlobalObject()->setPrototype(other);
+ }
+}
+
+/*!
+ \internal
+*/
+QScriptValue QScriptValue::scope() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ // ### make hidden property
+ JSC::JSValue result = d->property("__qt_scope__", QScriptValue::ResolveLocal);
+ return d->engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ \internal
+*/
+void QScriptValue::setScope(const QScriptValue &scope)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+ if (scope.isValid() && QScriptValuePrivate::getEngine(scope)
+ && (QScriptValuePrivate::getEngine(scope) != d->engine)) {
+ qWarning("QScriptValue::setScope() failed: "
+ "cannot set a scope object created in "
+ "a different engine");
+ return;
+ }
+ JSC::JSValue other = d->engine->scriptValueToJSCValue(scope);
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::Identifier id = JSC::Identifier(exec, "__qt_scope__");
+ if (!scope.isValid()) {
+ JSC::asObject(d->jscValue)->removeDirect(id);
+ } else {
+ // ### make hidden property
+ JSC::asObject(d->jscValue)->putDirect(id, other);
+ }
+}
+
+/*!
+ Returns true if this QScriptValue is an instance of
+ \a other; otherwise returns false.
+
+ This QScriptValue is considered to be an instance of \a other if
+ \a other is a function and the value of the \c{prototype}
+ property of \a other is in the prototype chain of this
+ QScriptValue.
+*/
+bool QScriptValue::instanceOf(const QScriptValue &other) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject() || !other.isObject())
+ return false;
+ if (QScriptValuePrivate::getEngine(other) != d->engine) {
+ qWarning("QScriptValue::instanceof: "
+ "cannot perform operation on a value created in "
+ "a different engine");
+ return false;
+ }
+ JSC::JSValue jscProto = d->engine->scriptValueToJSCValue(other.property(QLatin1String("prototype")));
+ if (!jscProto)
+ jscProto = JSC::jsUndefined();
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSValue jscOther = d->engine->scriptValueToJSCValue(other);
+ return JSC::asObject(jscOther)->hasInstance(exec, d->jscValue, jscProto);
+}
+
+// ### move
+
+namespace QScript
+{
+
+enum Type {
+ Undefined,
+ Null,
+ Boolean,
+ String,
+ Number,
+ Object
+};
+
+static Type type(const QScriptValue &v)
+{
+ if (v.isUndefined())
+ return Undefined;
+ else if (v.isNull())
+ return Null;
+ else if (v.isBoolean())
+ return Boolean;
+ else if (v.isString())
+ return String;
+ else if (v.isNumber())
+ return Number;
+ Q_ASSERT(v.isObject());
+ return Object;
+}
+
+static QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
+{
+ Q_ASSERT(object.isObject());
+ QScriptValuePrivate *pp = QScriptValuePrivate::get(object);
+ Q_ASSERT(pp->engine != 0);
+ QScript::APIShim shim(pp->engine);
+ JSC::ExecState *exec = pp->engine->currentFrame;
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint);
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ return pp->engine->scriptValueFromJSCValue(result);
+}
+
+static bool IsNumerical(const QScriptValue &value)
+{
+ return value.isNumber() || value.isBool();
+}
+
+static bool LessThan(QScriptValue lhs, QScriptValue rhs)
+{
+ if (type(lhs) == type(rhs)) {
+ switch (type(lhs)) {
+ case Undefined:
+ case Null:
+ return false;
+
+ case Number:
+ return lhs.toNumber() < rhs.toNumber();
+
+ case Boolean:
+ return lhs.toBool() < rhs.toBool();
+
+ case String:
+ return lhs.toString() < rhs.toString();
+
+ case Object:
+ break;
+ } // switch
+ }
+
+ if (lhs.isObject())
+ lhs = ToPrimitive(lhs, JSC::PreferNumber);
+
+ if (rhs.isObject())
+ rhs = ToPrimitive(rhs, JSC::PreferNumber);
+
+ if (lhs.isString() && rhs.isString())
+ return lhs.toString() < rhs.toString();
+
+ return lhs.toNumber() < rhs.toNumber();
+}
+
+static bool Equals(QScriptValue lhs, QScriptValue rhs)
+{
+ if (type(lhs) == type(rhs)) {
+ switch (type(lhs)) {
+ case QScript::Undefined:
+ case QScript::Null:
+ return true;
+
+ case QScript::Number:
+ return lhs.toNumber() == rhs.toNumber();
+
+ case QScript::Boolean:
+ return lhs.toBool() == rhs.toBool();
+
+ case QScript::String:
+ return lhs.toString() == rhs.toString();
+
+ case QScript::Object:
+ if (lhs.isVariant())
+ return lhs.strictlyEquals(rhs) || (lhs.toVariant() == rhs.toVariant());
+#ifndef QT_NO_QOBJECT
+ else if (lhs.isQObject())
+ return (lhs.strictlyEquals(rhs)) || (lhs.toQObject() == rhs.toQObject());
+#endif
+ else
+ return lhs.strictlyEquals(rhs);
+ }
+ }
+
+ if (lhs.isNull() && rhs.isUndefined())
+ return true;
+
+ else if (lhs.isUndefined() && rhs.isNull())
+ return true;
+
+ else if (IsNumerical(lhs) && rhs.isString())
+ return lhs.toNumber() == rhs.toNumber();
+
+ else if (lhs.isString() && IsNumerical(rhs))
+ return lhs.toNumber() == rhs.toNumber();
+
+ else if (lhs.isBool())
+ return Equals(lhs.toNumber(), rhs);
+
+ else if (rhs.isBool())
+ return Equals(lhs, rhs.toNumber());
+
+ else if (lhs.isObject() && !rhs.isNull()) {
+ lhs = ToPrimitive(lhs);
+
+ if (lhs.isValid() && !lhs.isObject())
+ return Equals(lhs, rhs);
+ }
+
+ else if (rhs.isObject() && ! lhs.isNull()) {
+ rhs = ToPrimitive(rhs);
+ if (rhs.isValid() && !rhs.isObject())
+ return Equals(lhs, rhs);
+ }
+
+ return false;
+}
+
+} // namespace QScript
+
+/*!
+ Returns true if this QScriptValue is less than \a other, otherwise
+ returns false. The comparison follows the behavior described in
+ \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison
+ Algorithm".
+
+ Note that if this QScriptValue or the \a other value are objects,
+ calling this function has side effects on the script engine, since
+ the engine will call the object's valueOf() function (and possibly
+ toString()) in an attempt to convert the object to a primitive value
+ (possibly resulting in an uncaught script exception).
+
+ \sa equals()
+*/
+bool QScriptValue::lessThan(const QScriptValue &other) const
+{
+ Q_D(const QScriptValue);
+ // no equivalent function in JSC? There's a jsLess() in VM/Machine.cpp
+ if (!isValid() || !other.isValid())
+ return false;
+ if (QScriptValuePrivate::getEngine(other) && d->engine
+ && (QScriptValuePrivate::getEngine(other) != d->engine)) {
+ qWarning("QScriptValue::lessThan: "
+ "cannot compare to a value created in "
+ "a different engine");
+ return false;
+ }
+ return QScript::LessThan(*this, other);
+}
+
+/*!
+ Returns true if this QScriptValue is equal to \a other, otherwise
+ returns false. The comparison follows the behavior described in
+ \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison
+ Algorithm".
+
+ This function can return true even if the type of this QScriptValue
+ is different from the type of the \a other value; i.e. the
+ comparison is not strict. For example, comparing the number 9 to
+ the string "9" returns true; comparing an undefined value to a null
+ value returns true; comparing a \c{Number} object whose primitive
+ value is 6 to a \c{String} object whose primitive value is "6"
+ returns true; and comparing the number 1 to the boolean value
+ \c{true} returns true. If you want to perform a comparison
+ without such implicit value conversion, use strictlyEquals().
+
+ Note that if this QScriptValue or the \a other value are objects,
+ calling this function has side effects on the script engine, since
+ the engine will call the object's valueOf() function (and possibly
+ toString()) in an attempt to convert the object to a primitive value
+ (possibly resulting in an uncaught script exception).
+
+ \sa strictlyEquals(), lessThan()
+*/
+bool QScriptValue::equals(const QScriptValue &other) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !other.d_ptr)
+ return (d_ptr == other.d_ptr);
+ if (QScriptValuePrivate::getEngine(other) && d->engine
+ && (QScriptValuePrivate::getEngine(other) != d->engine)) {
+ qWarning("QScriptValue::equals: "
+ "cannot compare to a value created in "
+ "a different engine");
+ return false;
+ }
+ if (d->isJSC() && other.d_ptr->isJSC()) {
+ QScriptEnginePrivate *eng_p = d->engine;
+ if (!eng_p)
+ eng_p = other.d_ptr->engine;
+ if (eng_p) {
+ QScript::APIShim shim(eng_p);
+ JSC::ExecState *exec = eng_p->currentFrame;
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue);
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ return result;
+ }
+ }
+ return QScript::Equals(*this, other);
+}
+
+/*!
+ Returns true if this QScriptValue is equal to \a other using strict
+ comparison (no conversion), otherwise returns false. The comparison
+ follows the behavior described in \l{ECMA-262} section 11.9.6, "The
+ Strict Equality Comparison Algorithm".
+
+ If the type of this QScriptValue is different from the type of the
+ \a other value, this function returns false. If the types are equal,
+ the result depends on the type, as shown in the following table:
+
+ \table
+ \header \o Type \o Result
+ \row \o Undefined \o true
+ \row \o Null \o true
+ \row \o Boolean \o true if both values are true, false otherwise
+ \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise
+ \row \o String \o true if both values are exactly the same sequence of characters, false otherwise
+ \row \o Object \o true if both values refer to the same object, false otherwise
+ \endtable
+
+ \sa equals()
+*/
+bool QScriptValue::strictlyEquals(const QScriptValue &other) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !other.d_ptr)
+ return (d_ptr == other.d_ptr);
+ if (QScriptValuePrivate::getEngine(other) && d->engine
+ && (QScriptValuePrivate::getEngine(other) != d->engine)) {
+ qWarning("QScriptValue::strictlyEquals: "
+ "cannot compare to a value created in "
+ "a different engine");
+ return false;
+ }
+
+ if (d->type != other.d_ptr->type) {
+ if (d->type == QScriptValuePrivate::JavaScriptCore) {
+ QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
+ if (eng_p)
+ return JSC::JSValue::strictEqual(eng_p->currentFrame, d->jscValue, eng_p->scriptValueToJSCValue(other));
+ } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) {
+ QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine;
+ if (eng_p)
+ return JSC::JSValue::strictEqual(eng_p->currentFrame, eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue);
+ }
+
+ return false;
+ }
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
+ JSC::ExecState *exec = eng_p ? eng_p->currentFrame : 0;
+ return JSC::JSValue::strictEqual(exec, d->jscValue, other.d_ptr->jscValue);
+ }
+ case QScriptValuePrivate::Number:
+ return (d->numberValue == other.d_ptr->numberValue);
+ case QScriptValuePrivate::String:
+ return (d->stringValue == other.d_ptr->stringValue);
+ }
+ return false;
+}
+
+/*!
+ Returns the string value of this QScriptValue, as defined in
+ \l{ECMA-262} section 9.8, "ToString".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's toString() function (and possibly valueOf()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa isString()
+*/
+QString QScriptValue::toString() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return QString();
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toString(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toString(0, d->jscValue);
+ } }
+ case QScriptValuePrivate::Number:
+ return QScript::ToString(d->numberValue);
+ case QScriptValuePrivate::String:
+ return d->stringValue;
+ }
+ return QString();
+}
+
+/*!
+ Returns the number value of this QScriptValue, as defined in
+ \l{ECMA-262} section 9.3, "ToNumber".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16()
+*/
+qsreal QScriptValue::toNumber() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toNumber(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toNumber(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return d->numberValue;
+ case QScriptValuePrivate::String:
+ return QScript::ToNumber(d->stringValue);
+ }
+ return 0;
+}
+
+/*!
+ \obsolete
+
+ Use toBool() instead.
+*/
+bool QScriptValue::toBoolean() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return false;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toBool(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToBool(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToBool(d->stringValue);
+ }
+ return false;
+}
+
+/*!
+ \since 4.5
+
+ Returns the boolean value of this QScriptValue, using the conversion
+ rules described in \l{ECMA-262} section 9.2, "ToBoolean".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa isBool()
+*/
+bool QScriptValue::toBool() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return false;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toBool(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToBool(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToBool(d->stringValue);
+ }
+ return false;
+}
+
+/*!
+ Returns the signed 32-bit integer value of this QScriptValue, using
+ the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa toNumber(), toUInt32()
+*/
+qint32 QScriptValue::toInt32() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toInt32(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toInt32(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToInt32(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToInt32(d->stringValue);
+ }
+ return 0;
+}
+
+/*!
+ Returns the unsigned 32-bit integer value of this QScriptValue, using
+ the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa toNumber(), toInt32()
+*/
+quint32 QScriptValue::toUInt32() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toUInt32(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toUInt32(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToUInt32(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToUInt32(d->stringValue);
+ }
+ return 0;
+}
+
+/*!
+ Returns the unsigned 16-bit integer value of this QScriptValue, using
+ the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa toNumber()
+*/
+quint16 QScriptValue::toUInt16() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toUInt16(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toUInt16(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToUInt16(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToUInt16(d->stringValue);
+ }
+ return 0;
+}
+
+/*!
+ Returns the integer value of this QScriptValue, using the conversion
+ rules described in \l{ECMA-262} section 9.4, "ToInteger".
+
+ Note that if this QScriptValue is an object, calling this function
+ has side effects on the script engine, since the engine will call
+ the object's valueOf() function (and possibly toString()) in an
+ attempt to convert the object to a primitive value (possibly
+ resulting in an uncaught script exception).
+
+ \sa toNumber()
+*/
+qsreal QScriptValue::toInteger() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toInteger(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toInteger(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QScript::ToInteger(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QScript::ToInteger(d->stringValue);
+ }
+ return 0;
+}
+
+/*!
+ Returns the QVariant value of this QScriptValue, if it can be
+ converted to a QVariant; otherwise returns an invalid QVariant.
+ The conversion is performed according to the following table:
+
+ \table
+ \header \o Input Type \o Result
+ \row \o Undefined \o An invalid QVariant.
+ \row \o Null \o An invalid QVariant.
+ \row \o Boolean \o A QVariant containing the value of the boolean.
+ \row \o Number \o A QVariant containing the value of the number.
+ \row \o String \o A QVariant containing the value of the string.
+ \row \o QVariant Object \o The result is the QVariant value of the object (no conversion).
+ \row \o QObject Object \o A QVariant containing a pointer to the QObject.
+ \row \o Date Object \o A QVariant containing the date value (toDateTime()).
+ \row \o RegExp Object \o A QVariant containing the regular expression value (toRegExp()).
+ \row \o Array Object \o The array is converted to a QVariantList. Each element is converted to a QVariant, recursively; cyclic references are not followed.
+ \row \o Object \o The object is converted to a QVariantMap. Each property is converted to a QVariant, recursively; cyclic references are not followed.
+ \endtable
+
+ \sa isVariant()
+*/
+QVariant QScriptValue::toVariant() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return QVariant();
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore: {
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toVariant(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toVariant(0, d->jscValue);
+ }
+ }
+ case QScriptValuePrivate::Number:
+ return QVariant(d->numberValue);
+ case QScriptValuePrivate::String:
+ return QVariant(d->stringValue);
+ }
+ return QVariant();
+}
+
+/*!
+ \obsolete
+
+ This function is obsolete; use QScriptEngine::toObject() instead.
+*/
+QScriptValue QScriptValue::toObject() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->engine)
+ return QScriptValue();
+ return engine()->toObject(*this);
+}
+
+/*!
+ Returns a QDateTime representation of this value, in local time.
+ If this QScriptValue is not a date, or the value of the date is NaN
+ (Not-a-Number), an invalid QDateTime is returned.
+
+ \sa isDate()
+*/
+QDateTime QScriptValue::toDateTime() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->engine)
+ return QDateTime();
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toDateTime(d->engine->currentFrame, d->jscValue);
+}
+
+#ifndef QT_NO_REGEXP
+/*!
+ Returns the QRegExp representation of this value.
+ If this QScriptValue is not a regular expression, an empty
+ QRegExp is returned.
+
+ \sa isRegExp()
+*/
+QRegExp QScriptValue::toRegExp() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->engine)
+ return QRegExp();
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toRegExp(d->engine->currentFrame, d->jscValue);
+}
+#endif // QT_NO_REGEXP
+
+/*!
+ If this QScriptValue is a QObject, returns the QObject pointer
+ that the QScriptValue represents; otherwise, returns 0.
+
+ If the QObject that this QScriptValue wraps has been deleted,
+ this function returns 0 (i.e. it is possible for toQObject()
+ to return 0 even when isQObject() returns true).
+
+ \sa isQObject()
+*/
+QObject *QScriptValue::toQObject() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->engine)
+ return 0;
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toQObject(d->engine->currentFrame, d->jscValue);
+}
+
+/*!
+ If this QScriptValue is a QMetaObject, returns the QMetaObject pointer
+ that the QScriptValue represents; otherwise, returns 0.
+
+ \sa isQMetaObject()
+*/
+const QMetaObject *QScriptValue::toQMetaObject() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->engine)
+ return 0;
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toQMetaObject(d->engine->currentFrame, d->jscValue);
+}
+
+/*!
+ Sets the value of this QScriptValue's property with the given \a name to
+ the given \a value.
+
+ If this QScriptValue is not an object, this function does nothing.
+
+ If this QScriptValue does not already have a property with name \a name,
+ a new property is created; the given \a flags then specify how this
+ property may be accessed by script code.
+
+ If \a value is invalid, the property is removed.
+
+ If the property is implemented using a setter function (i.e. has the
+ PropertySetter flag set), calling setProperty() has side-effects on
+ the script engine, since the setter function will be called with the
+ given \a value as argument (possibly resulting in an uncaught script
+ exception).
+
+ Note that you cannot specify custom getter or setter functions for
+ built-in properties, such as the \c{length} property of Array objects
+ or meta properties of QObject objects.
+
+ \sa property()
+*/
+
+void QScriptValue::setProperty(const QString &name, const QScriptValue &value,
+ const PropertyFlags &flags)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+ QScript::APIShim shim(d->engine);
+ QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
+ if (valueEngine && (valueEngine != d->engine)) {
+ qWarning("QScriptValue::setProperty(%s) failed: "
+ "cannot set value created in a different engine",
+ qPrintable(name));
+ return;
+ }
+ JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
+ d->setProperty(name, jsValue, flags);
+}
+
+/*!
+ Returns the value of this QScriptValue's property with the given \a name,
+ using the given \a mode to resolve the property.
+
+ If no such property exists, an invalid QScriptValue is returned.
+
+ If the property is implemented using a getter function (i.e. has the
+ PropertyGetter flag set), calling property() has side-effects on the
+ script engine, since the getter function will be called (possibly
+ resulting in an uncaught script exception). If an exception
+ occurred, property() returns the value that was thrown (typically
+ an \c{Error} object).
+
+ \sa setProperty(), propertyFlags(), QScriptValueIterator
+*/
+QScriptValue QScriptValue::property(const QString &name,
+ const ResolveFlags &mode) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ return d->engine->scriptValueFromJSCValue(d->property(name, mode));
+}
+
+/*!
+ \overload
+
+ Returns the property at the given \a arrayIndex, using the given \a
+ mode to resolve the property.
+
+ This function is provided for convenience and performance when
+ working with array objects.
+
+ If this QScriptValue is not an Array object, this function behaves
+ as if property() was called with the string representation of \a
+ arrayIndex.
+*/
+QScriptValue QScriptValue::property(quint32 arrayIndex,
+ const ResolveFlags &mode) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ return d->engine->scriptValueFromJSCValue(d->property(arrayIndex, mode));
+}
+
+/*!
+ \overload
+
+ Sets the property at the given \a arrayIndex to the given \a value.
+
+ This function is provided for convenience and performance when
+ working with array objects.
+
+ If this QScriptValue is not an Array object, this function behaves
+ as if setProperty() was called with the string representation of \a
+ arrayIndex.
+*/
+void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value,
+ const PropertyFlags &flags)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+ if (QScriptValuePrivate::getEngine(value)
+ && (QScriptValuePrivate::getEngine(value) != d->engine)) {
+ qWarning("QScriptValue::setProperty() failed: "
+ "cannot set value created in a different engine");
+ return;
+ }
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
+ d->setProperty(arrayIndex, jsValue, flags);
+}
+
+/*!
+ \since 4.4
+
+ Returns the value of this QScriptValue's property with the given \a name,
+ using the given \a mode to resolve the property.
+
+ This overload of property() is useful when you need to look up the
+ same property repeatedly, since the lookup can be performed faster
+ when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle(), setProperty()
+*/
+QScriptValue QScriptValue::property(const QScriptString &name,
+ const ResolveFlags &mode) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ return d->engine->scriptValueFromJSCValue(d->property(name.d_ptr->identifier, mode));
+}
+
+/*!
+ \since 4.4
+
+ Sets the value of this QScriptValue's property with the given \a
+ name to the given \a value. The given \a flags specify how this
+ property may be accessed by script code.
+
+ This overload of setProperty() is useful when you need to set the
+ same property repeatedly, since the operation can be performed
+ faster when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle()
+*/
+void QScriptValue::setProperty(const QScriptString &name,
+ const QScriptValue &value,
+ const PropertyFlags &flags)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
+ return;
+ QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
+ if (valueEngine && (valueEngine != d->engine)) {
+ qWarning("QScriptValue::setProperty(%s) failed: "
+ "cannot set value created in a different engine",
+ qPrintable(name.toString()));
+ return;
+ }
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
+ d->setProperty(name.d_ptr->identifier, jsValue, flags);
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name,
+ const ResolveFlags &mode) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return 0;
+ QScript::APIShim shim(d->engine);
+ JSC::ExecState *exec = d->engine->currentFrame;
+ return d->propertyFlags(JSC::Identifier(exec, name), mode);
+
+}
+
+/*!
+ \since 4.4
+
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &name,
+ const ResolveFlags &mode) const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
+ return 0;
+ return d->propertyFlags(name.d_ptr->identifier, mode);
+}
+
+/*!
+ Calls this QScriptValue as a function, using \a thisObject as
+ the `this' object in the function call, and passing \a args
+ as arguments to the function. Returns the value returned from
+ the function.
+
+ If this QScriptValue is not a function, call() does nothing
+ and returns an invalid QScriptValue.
+
+ Note that if \a thisObject is not an object, the global object
+ (see \l{QScriptEngine::globalObject()}) will be used as the
+ `this' object.
+
+ Calling call() can cause an exception to occur in the script engine;
+ in that case, call() returns the value that was thrown (typically an
+ \c{Error} object). You can call
+ QScriptEngine::hasUncaughtException() to determine if an exception
+ occurred.
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
+
+ \sa construct()
+*/
+QScriptValue QScriptValue::call(const QScriptValue &thisObject,
+ const QScriptValueList &args)
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue callee = d->jscValue;
+ JSC::CallData callData;
+ JSC::CallType callType = callee.getCallData(callData);
+ if (callType == JSC::CallTypeNone)
+ return QScriptValue();
+
+ if (QScriptValuePrivate::getEngine(thisObject)
+ && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) {
+ qWarning("QScriptValue::call() failed: "
+ "cannot call function with thisObject created in "
+ "a different engine");
+ return QScriptValue();
+ }
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+
+ JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject);
+ if (!jscThisObject || !jscThisObject.isObject())
+ jscThisObject = d->engine->globalObject();
+
+ QVarLengthArray<JSC::JSValue, 8> argsVector(args.size());
+ for (int i = 0; i < args.size(); ++i) {
+ const QScriptValue &arg = args.at(i);
+ if (!arg.isValid()) {
+ argsVector[i] = JSC::jsUndefined();
+ } else if (QScriptValuePrivate::getEngine(arg)
+ && (QScriptValuePrivate::getEngine(arg) != d->engine)) {
+ qWarning("QScriptValue::call() failed: "
+ "cannot call function with argument created in "
+ "a different engine");
+ return QScriptValue();
+ } else {
+ argsVector[i] = d->engine->scriptValueToJSCValue(arg);
+ }
+ }
+ JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
+
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs);
+ if (exec->hadException()) {
+ result = exec->exception();
+ } else {
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ }
+ return d->engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Calls this QScriptValue as a function, using \a thisObject as
+ the `this' object in the function call, and passing \a arguments
+ as arguments to the function. Returns the value returned from
+ the function.
+
+ If this QScriptValue is not a function, call() does nothing
+ and returns an invalid QScriptValue.
+
+ \a arguments can be an arguments object, an array, null or
+ undefined; any other type will cause a TypeError to be thrown.
+
+ Note that if \a thisObject is not an object, the global object
+ (see \l{QScriptEngine::globalObject()}) will be used as the
+ `this' object.
+
+ One common usage of this function is to forward native function
+ calls to another function:
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3
+
+ \sa construct(), QScriptContext::argumentsObject()
+*/
+QScriptValue QScriptValue::call(const QScriptValue &thisObject,
+ const QScriptValue &arguments)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue callee = d->jscValue;
+ JSC::CallData callData;
+ JSC::CallType callType = callee.getCallData(callData);
+ if (callType == JSC::CallTypeNone)
+ return QScriptValue();
+
+ if (QScriptValuePrivate::getEngine(thisObject)
+ && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) {
+ qWarning("QScriptValue::call() failed: "
+ "cannot call function with thisObject created in "
+ "a different engine");
+ return QScriptValue();
+ }
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+
+ JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject);
+ if (!jscThisObject || !jscThisObject.isObject())
+ jscThisObject = d->engine->globalObject();
+
+ JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments);
+ // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply()
+ JSC::MarkedArgumentBuffer applyArgs;
+ if (!array.isUndefinedOrNull()) {
+ if (!array.isObject()) {
+ return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
+ }
+ if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info)
+ JSC::asArguments(array)->fillArgList(exec, applyArgs);
+ else if (JSC::isJSArray(&exec->globalData(), array))
+ JSC::asArray(array)->fillArgList(exec, applyArgs);
+ else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) {
+ unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned i = 0; i < length; ++i)
+ applyArgs.append(JSC::asArray(array)->get(exec, i));
+ } else {
+ return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
+ }
+ }
+
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs);
+ if (exec->hadException()) {
+ result = exec->exception();
+ } else {
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ }
+ return d->engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Creates a new \c{Object} and calls this QScriptValue as a
+ constructor, using the created object as the `this' object and
+ passing \a args as arguments. If the return value from the
+ constructor call is an object, then that object is returned;
+ otherwise the default constructed object is returned.
+
+ If this QScriptValue is not a function, construct() does nothing
+ and returns an invalid QScriptValue.
+
+ Calling construct() can cause an exception to occur in the script
+ engine; in that case, construct() returns the value that was thrown
+ (typically an \c{Error} object). You can call
+ QScriptEngine::hasUncaughtException() to determine if an exception
+ occurred.
+
+ \sa call(), QScriptEngine::newObject()
+*/
+QScriptValue QScriptValue::construct(const QScriptValueList &args)
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue callee = d->jscValue;
+ JSC::ConstructData constructData;
+ JSC::ConstructType constructType = callee.getConstructData(constructData);
+ if (constructType == JSC::ConstructTypeNone)
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+
+ QVarLengthArray<JSC::JSValue, 8> argsVector(args.size());
+ for (int i = 0; i < args.size(); ++i) {
+ QScriptValue arg = args.at(i);
+ if (QScriptValuePrivate::getEngine(arg) != d->engine && QScriptValuePrivate::getEngine(arg)) {
+ qWarning("QScriptValue::construct() failed: "
+ "cannot construct function with argument created in "
+ "a different engine");
+ return QScriptValue();
+ }
+ if (!arg.isValid())
+ argsVector[i] = JSC::jsUndefined();
+ else
+ argsVector[i] = d->engine->scriptValueToJSCValue(args.at(i));
+ }
+
+ JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
+
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ JSC::JSValue result;
+ JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, jscArgs);
+ if (exec->hadException()) {
+ result = exec->exception();
+ } else {
+ result = newObject;
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ }
+ return d->engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Creates a new \c{Object} and calls this QScriptValue as a
+ constructor, using the created object as the `this' object and
+ passing \a arguments as arguments. If the return value from the
+ constructor call is an object, then that object is returned;
+ otherwise the default constructed object is returned.
+
+ If this QScriptValue is not a function, construct() does nothing
+ and returns an invalid QScriptValue.
+
+ \a arguments can be an arguments object, an array, null or
+ undefined. Any other type will cause a TypeError to be thrown.
+
+ \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject()
+*/
+QScriptValue QScriptValue::construct(const QScriptValue &arguments)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue callee = d->jscValue;
+ JSC::ConstructData constructData;
+ JSC::ConstructType constructType = callee.getConstructData(constructData);
+ if (constructType == JSC::ConstructTypeNone)
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+
+ if (QScriptValuePrivate::getEngine(arguments) != d->engine && QScriptValuePrivate::getEngine(arguments)) {
+ qWarning("QScriptValue::construct() failed: "
+ "cannot construct function with argument created in "
+ "a different engine");
+ return QScriptValue();
+ }
+ JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments);
+ // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply()
+ JSC::MarkedArgumentBuffer applyArgs;
+ if (!array.isUndefinedOrNull()) {
+ if (!array.isObject()) {
+ return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
+ }
+ if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info)
+ JSC::asArguments(array)->fillArgList(exec, applyArgs);
+ else if (JSC::isJSArray(&exec->globalData(), array))
+ JSC::asArray(array)->fillArgList(exec, applyArgs);
+ else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) {
+ unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned i = 0; i < length; ++i)
+ applyArgs.append(JSC::asArray(array)->get(exec, i));
+ } else {
+ return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
+ }
+ }
+
+ JSC::JSValue savedException;
+ QScriptEnginePrivate::saveException(exec, &savedException);
+ JSC::JSValue result;
+ JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, applyArgs);
+ if (exec->hadException()) {
+ result = exec->exception();
+ } else {
+ result = newObject;
+ QScriptEnginePrivate::restoreException(exec, savedException);
+ }
+ return d->engine->scriptValueFromJSCValue(result);
+}
+
+/*!
+ Returns the QScriptEngine that created this QScriptValue,
+ or 0 if this QScriptValue is invalid or the value is not
+ associated with a particular engine.
+*/
+QScriptEngine *QScriptValue::engine() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return 0;
+ return QScriptEnginePrivate::get(d->engine);
+}
+
+/*!
+ \obsolete
+
+ Use isBool() instead.
+*/
+bool QScriptValue::isBoolean() const
+{
+ Q_D(const QScriptValue);
+ return d && d->isJSC() && d->jscValue.isBoolean();
+}
+
+/*!
+ \since 4.5
+
+ Returns true if this QScriptValue is of the primitive type Boolean;
+ otherwise returns false.
+
+ \sa toBool()
+*/
+bool QScriptValue::isBool() const
+{
+ Q_D(const QScriptValue);
+ return d && d->isJSC() && d->jscValue.isBoolean();
+}
+
+/*!
+ Returns true if this QScriptValue is of the primitive type Number;
+ otherwise returns false.
+
+ \sa toNumber()
+*/
+bool QScriptValue::isNumber() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return false;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore:
+ return d->jscValue.isNumber();
+ case QScriptValuePrivate::Number:
+ return true;
+ case QScriptValuePrivate::String:
+ return false;
+ }
+ return false;
+}
+
+/*!
+ Returns true if this QScriptValue is of the primitive type String;
+ otherwise returns false.
+
+ \sa toString()
+*/
+bool QScriptValue::isString() const
+{
+ Q_D(const QScriptValue);
+ if (!d)
+ return false;
+ switch (d->type) {
+ case QScriptValuePrivate::JavaScriptCore:
+ return d->jscValue.isString();
+ case QScriptValuePrivate::Number:
+ return false;
+ case QScriptValuePrivate::String:
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Returns true if this QScriptValue is a function; otherwise returns
+ false.
+
+ \sa call()
+*/
+bool QScriptValue::isFunction() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScript::isFunction(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is of the primitive type Null;
+ otherwise returns false.
+
+ \sa QScriptEngine::nullValue()
+*/
+bool QScriptValue::isNull() const
+{
+ Q_D(const QScriptValue);
+ return d && d->isJSC() && d->jscValue.isNull();
+}
+
+/*!
+ Returns true if this QScriptValue is of the primitive type Undefined;
+ otherwise returns false.
+
+ \sa QScriptEngine::undefinedValue()
+*/
+bool QScriptValue::isUndefined() const
+{
+ Q_D(const QScriptValue);
+ return d && d->isJSC() && d->jscValue.isUndefined();
+}
+
+/*!
+ Returns true if this QScriptValue is of the Object type; otherwise
+ returns false.
+
+ Note that function values, variant values, and QObject values are
+ objects, so this function returns true for such values.
+
+ \sa toObject(), QScriptEngine::newObject()
+*/
+bool QScriptValue::isObject() const
+{
+ Q_D(const QScriptValue);
+ return d && d->isObject();
+}
+
+/*!
+ Returns true if this QScriptValue is a variant value;
+ otherwise returns false.
+
+ \sa toVariant(), QScriptEngine::newVariant()
+*/
+bool QScriptValue::isVariant() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isVariant(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is a QObject; otherwise returns
+ false.
+
+ Note: This function returns true even if the QObject that this
+ QScriptValue wraps has been deleted.
+
+ \sa toQObject(), QScriptEngine::newQObject()
+*/
+bool QScriptValue::isQObject() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isQObject(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is a QMetaObject; otherwise returns
+ false.
+
+ \sa toQMetaObject(), QScriptEngine::newQMetaObject()
+*/
+bool QScriptValue::isQMetaObject() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC())
+ return false;
+ return QScriptEnginePrivate::isQMetaObject(d->jscValue);
+}
+
+/*!
+ Returns true if this QScriptValue is valid; otherwise returns
+ false.
+*/
+bool QScriptValue::isValid() const
+{
+ Q_D(const QScriptValue);
+ return d && (!d->isJSC() || !!d->jscValue);
+}
+
+/*!
+ \since 4.4
+
+ Returns the internal data of this QScriptValue object. QtScript uses
+ this property to store the primitive value of Date, String, Number
+ and Boolean objects. For other types of object, custom data may be
+ stored using setData().
+*/
+QScriptValue QScriptValue::data() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isObject())
+ return QScriptValue();
+ if (d->jscValue.inherits(&QScriptObject::info)) {
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ return d->engine->scriptValueFromJSCValue(scriptObject->data());
+ } else {
+ // ### make hidden property
+ return property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal);
+ }
+}
+
+/*!
+ \since 4.4
+
+ Sets the internal \a data of this QScriptValue object. You can use
+ this function to set object-specific data that won't be directly
+ accessible to scripts, but may be retrieved in C++ using the data()
+ function.
+
+ \sa QScriptEngine::reportAdditionalMemoryCost()
+*/
+void QScriptValue::setData(const QScriptValue &data)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+ QScript::APIShim shim(d->engine);
+ JSC::JSValue other = d->engine->scriptValueToJSCValue(data);
+ if (d->jscValue.inherits(&QScriptObject::info)) {
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ scriptObject->setData(other);
+ } else {
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::Identifier id = JSC::Identifier(exec, "__qt_data__");
+ if (!data.isValid()) {
+ JSC::asObject(d->jscValue)->removeDirect(id);
+ } else {
+ // ### make hidden property
+ JSC::asObject(d->jscValue)->putDirect(id, other);
+ }
+ }
+}
+
+/*!
+ \since 4.4
+
+ Returns the custom script class that this script object is an
+ instance of, or 0 if the object is not of a custom class.
+
+ \sa setScriptClass()
+*/
+QScriptClass *QScriptValue::scriptClass() const
+{
+ Q_D(const QScriptValue);
+ if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
+ return 0;
+ return static_cast<QScript::ClassObjectDelegate*>(delegate)->scriptClass();
+}
+
+/*!
+ \since 4.4
+
+ Sets the custom script class of this script object to \a scriptClass.
+ This can be used to "promote" a plain script object (e.g. created
+ by the "new" operator in a script, or by QScriptEngine::newObject() in C++)
+ to an object of a custom type.
+
+ If \a scriptClass is 0, the object will be demoted to a plain
+ script object.
+
+ \sa scriptClass(), setData()
+*/
+void QScriptValue::setScriptClass(QScriptClass *scriptClass)
+{
+ Q_D(QScriptValue);
+ if (!d || !d->isObject())
+ return;
+ if (!d->jscValue.inherits(&QScriptObject::info)) {
+ qWarning("QScriptValue::setScriptClass() failed: "
+ "cannot change class of non-QScriptObject");
+ return;
+ }
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ if (!scriptClass) {
+ scriptObject->setDelegate(0);
+ } else {
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) {
+ delegate = new QScript::ClassObjectDelegate(scriptClass);
+ scriptObject->setDelegate(delegate);
+ }
+ static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass);
+ }
+}
+
+/*!
+ \internal
+
+ Returns the ID of this object, or -1 if this QScriptValue is not an
+ object.
+
+ \sa QScriptEngine::objectById()
+*/
+qint64 QScriptValue::objectId() const
+{
+ return d_ptr?d_ptr->objectId():-1;
+}
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptvalue.h b/src/script/api/qscriptvalue.h
new file mode 100644
index 0000000..9cb5d38
--- /dev/null
+++ b/src/script/api/qscriptvalue.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTVALUE_H
+#define QSCRIPTVALUE_H
+
+#include <QtCore/qstring.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QScriptClass;
+class QScriptValue;
+class QScriptEngine;
+class QScriptString;
+class QVariant;
+class QObject;
+struct QMetaObject;
+class QDateTime;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+
+typedef QList<QScriptValue> QScriptValueList;
+
+typedef double qsreal;
+
+class QScriptValuePrivate;
+class QScriptEnginePrivate;
+struct QScriptValuePrivatePointerDeleter;
+class Q_SCRIPT_EXPORT QScriptValue
+{
+public:
+ enum ResolveFlag {
+ ResolveLocal = 0x00,
+ ResolvePrototype = 0x01,
+ ResolveScope = 0x02,
+ ResolveFull = ResolvePrototype | ResolveScope
+ };
+
+ Q_DECLARE_FLAGS(ResolveFlags, ResolveFlag)
+
+ enum PropertyFlag {
+ ReadOnly = 0x00000001,
+ Undeletable = 0x00000002,
+ SkipInEnumeration = 0x00000004,
+
+ PropertyGetter = 0x00000008,
+ PropertySetter = 0x00000010,
+
+ QObjectMember = 0x00000020,
+
+ KeepExistingFlags = 0x00000800,
+
+ UserRange = 0xff000000 // Users may use these as they see fit.
+ };
+ Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
+
+ enum SpecialValue {
+ NullValue,
+ UndefinedValue
+ };
+
+public:
+ QScriptValue();
+ ~QScriptValue();
+ QScriptValue(const QScriptValue &other);
+ QScriptValue(QScriptEngine *engine, SpecialValue val);
+ QScriptValue(QScriptEngine *engine, bool val);
+ QScriptValue(QScriptEngine *engine, int val);
+ QScriptValue(QScriptEngine *engine, uint val);
+ QScriptValue(QScriptEngine *engine, qsreal val);
+ QScriptValue(QScriptEngine *engine, const QString &val);
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QScriptValue(QScriptEngine *engine, const char *val);
+#endif
+
+ QScriptValue(SpecialValue value);
+ QScriptValue(bool value);
+ QScriptValue(int value);
+ QScriptValue(uint value);
+ QScriptValue(qsreal value);
+ QScriptValue(const QString &value);
+ QScriptValue(const QLatin1String &value);
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QScriptValue(const char *value);
+#endif
+
+ QScriptValue &operator=(const QScriptValue &other);
+
+ QScriptEngine *engine() const;
+
+ bool isValid() const;
+ bool isBool() const;
+ bool isBoolean() const;
+ bool isNumber() const;
+ bool isFunction() const;
+ bool isNull() const;
+ bool isString() const;
+ bool isUndefined() const;
+ bool isVariant() const;
+ bool isQObject() const;
+ bool isQMetaObject() const;
+ bool isObject() const;
+ bool isDate() const;
+ bool isRegExp() const;
+ bool isArray() const;
+ bool isError() const;
+
+ QString toString() const;
+ qsreal toNumber() const;
+ bool toBool() const;
+ bool toBoolean() const;
+ qsreal toInteger() const;
+ qint32 toInt32() const;
+ quint32 toUInt32() const;
+ quint16 toUInt16() const;
+ QVariant toVariant() const;
+ QObject *toQObject() const;
+ const QMetaObject *toQMetaObject() const;
+ QScriptValue toObject() const;
+ QDateTime toDateTime() const;
+#ifndef QT_NO_REGEXP
+ QRegExp toRegExp() const;
+#endif
+
+ bool instanceOf(const QScriptValue &other) const;
+
+ bool lessThan(const QScriptValue &other) const;
+ bool equals(const QScriptValue &other) const;
+ bool strictlyEquals(const QScriptValue &other) const;
+
+ QScriptValue prototype() const;
+ void setPrototype(const QScriptValue &prototype);
+
+ QScriptValue scope() const;
+ void setScope(const QScriptValue &scope);
+
+ QScriptValue property(const QString &name,
+ const ResolveFlags &mode = ResolvePrototype) const;
+ void setProperty(const QString &name, const QScriptValue &value,
+ const PropertyFlags &flags = KeepExistingFlags);
+
+ QScriptValue property(quint32 arrayIndex,
+ const ResolveFlags &mode = ResolvePrototype) const;
+ void setProperty(quint32 arrayIndex, const QScriptValue &value,
+ const PropertyFlags &flags = KeepExistingFlags);
+
+ QScriptValue property(const QScriptString &name,
+ const ResolveFlags &mode = ResolvePrototype) const;
+ void setProperty(const QScriptString &name, const QScriptValue &value,
+ const PropertyFlags &flags = KeepExistingFlags);
+
+ QScriptValue::PropertyFlags propertyFlags(
+ const QString &name, const ResolveFlags &mode = ResolvePrototype) const;
+ QScriptValue::PropertyFlags propertyFlags(
+ const QScriptString &name, const ResolveFlags &mode = ResolvePrototype) const;
+
+ QScriptValue call(const QScriptValue &thisObject = QScriptValue(),
+ const QScriptValueList &args = QScriptValueList());
+ QScriptValue call(const QScriptValue &thisObject,
+ const QScriptValue &arguments);
+ QScriptValue construct(const QScriptValueList &args = QScriptValueList());
+ QScriptValue construct(const QScriptValue &arguments);
+
+ QScriptValue data() const;
+ void setData(const QScriptValue &data);
+
+ QScriptClass *scriptClass() const;
+ void setScriptClass(QScriptClass *scriptClass);
+
+ qint64 objectId() const;
+
+private:
+ // force compile error, prevent QScriptValue(bool) to be called
+ QScriptValue(void *);
+ // force compile error, prevent QScriptValue(QScriptEngine*, bool) to be called
+ QScriptValue(QScriptEngine *, void *);
+
+ QScriptValue(QScriptValuePrivate*);
+
+private:
+ QExplicitlySharedDataPointer<QScriptValuePrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QScriptValue)
+
+ friend class QScriptEnginePrivate;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QScriptValue::ResolveFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QScriptValue::PropertyFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h
new file mode 100644
index 0000000..c996ed3
--- /dev/null
+++ b/src/script/api/qscriptvalue_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTVALUE_P_H
+#define QSCRIPTVALUE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+#include "wtf/Platform.h"
+#include "JSValue.h"
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QScriptEnginePrivate;
+
+class QScriptValue;
+class QScriptValuePrivate
+{
+ Q_DISABLE_COPY(QScriptValuePrivate)
+public:
+ inline void* operator new(size_t, QScriptEnginePrivate*);
+ inline void operator delete(void*);
+
+ enum Type {
+ JavaScriptCore,
+ Number,
+ String
+ };
+
+ inline QScriptValuePrivate(QScriptEnginePrivate*);
+ inline ~QScriptValuePrivate();
+
+ inline void initFrom(JSC::JSValue value);
+ inline void initFrom(qsreal value);
+ inline void initFrom(const QString &value);
+
+ inline bool isJSC() const;
+ inline bool isObject() const;
+
+ static inline QScriptValuePrivate *get(const QScriptValue &q)
+ {
+ return q.d_ptr.data();
+ }
+
+ static inline QScriptValue toPublic(QScriptValuePrivate *d)
+ {
+ return QScriptValue(d);
+ }
+
+ static inline QScriptEnginePrivate *getEngine(const QScriptValue &q)
+ {
+ if (!q.d_ptr)
+ return 0;
+ return q.d_ptr->engine;
+ }
+
+ inline JSC::JSValue property(const JSC::Identifier &id,
+ const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const;
+ inline JSC::JSValue property(quint32 index, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const;
+ inline JSC::JSValue property(const JSC::UString &, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const;
+ inline void setProperty(const JSC::UString &name, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ inline void setProperty(const JSC::Identifier &id, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ inline void setProperty(quint32 index, const JSC::JSValue &value,
+ const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags);
+ inline QScriptValue::PropertyFlags propertyFlags(
+ const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const;
+
+ void detachFromEngine();
+
+ qint64 objectId()
+ {
+ if ( (type == JavaScriptCore) && (engine) && jscValue.isCell() )
+ return (qint64)jscValue.asCell();
+ else
+ return -1;
+ }
+
+ QScriptEnginePrivate *engine;
+ Type type;
+ JSC::JSValue jscValue;
+ qsreal numberValue;
+ QString stringValue;
+
+ // linked list of engine's script values
+ QScriptValuePrivate *prev;
+ QScriptValuePrivate *next;
+
+ QBasicAtomicInt ref;
+};
+
+inline QScriptValuePrivate::QScriptValuePrivate(QScriptEnginePrivate *e)
+ : engine(e), prev(0), next(0)
+{
+ ref = 0;
+}
+
+inline bool QScriptValuePrivate::isJSC() const
+{
+ return (type == JavaScriptCore);
+}
+
+inline bool QScriptValuePrivate::isObject() const
+{
+ return isJSC() && jscValue && jscValue.isObject();
+}
+
+// Rest of inline functions implemented in qscriptengine_p.h
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/api/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp
new file mode 100644
index 0000000..5f53b46
--- /dev/null
+++ b/src/script/api/qscriptvalueiterator.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptvalueiterator.h"
+
+#include "qscriptstring.h"
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "qscriptvalue_p.h"
+#include "qlinkedlist.h"
+
+
+#include "JSObject.h"
+#include "PropertyNameArray.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.3
+ \class QScriptValueIterator
+
+ \brief The QScriptValueIterator class provides a Java-style iterator for QScriptValue.
+
+ \ingroup script
+
+
+ The QScriptValueIterator constructor takes a QScriptValue as
+ argument. After construction, the iterator is located at the very
+ beginning of the sequence of properties. Here's how to iterate over
+ all the properties of a QScriptValue:
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0
+
+ The next() advances the iterator. The name(), value() and flags()
+ functions return the name, value and flags of the last item that was
+ jumped over.
+
+ If you want to remove properties as you iterate over the
+ QScriptValue, use remove(). If you want to modify the value of a
+ property, use setValue().
+
+ Note that QScriptValueIterator only iterates over the QScriptValue's
+ own properties; i.e. it does not follow the prototype chain. You can
+ use a loop like this to follow the prototype chain:
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1
+
+ Note that QScriptValueIterator will not automatically skip over
+ properties that have the QScriptValue::SkipInEnumeration flag set;
+ that flag only affects iteration in script code. If you want, you
+ can skip over such properties with code like the following:
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2
+
+ \sa QScriptValue::property()
+*/
+
+class QScriptValueIteratorPrivate
+{
+public:
+ QScriptValueIteratorPrivate()
+ : initialized(false)
+ {}
+
+ ~QScriptValueIteratorPrivate()
+ {
+ if (!initialized)
+ return;
+ QScriptEnginePrivate *eng_p = engine();
+ if (!eng_p)
+ return;
+ QScript::APIShim shim(eng_p);
+ propertyNames.clear(); //destroying the identifiers need to be done under the APIShim guard
+ }
+
+ QScriptValuePrivate *object() const
+ {
+ return QScriptValuePrivate::get(objectValue);
+ }
+
+ QScriptEnginePrivate *engine() const
+ {
+ return QScriptEnginePrivate::get(objectValue.engine());
+ }
+
+ void ensureInitialized()
+ {
+ if (initialized)
+ return;
+ QScriptEnginePrivate *eng_p = engine();
+ QScript::APIShim shim(eng_p);
+ JSC::ExecState *exec = eng_p->globalExec();
+ JSC::PropertyNameArray propertyNamesArray(exec);
+ JSC::asObject(object()->jscValue)->getOwnPropertyNames(exec, propertyNamesArray, JSC::IncludeDontEnumProperties);
+
+ JSC::PropertyNameArray::const_iterator propertyNamesIt = propertyNamesArray.begin();
+ for(; propertyNamesIt != propertyNamesArray.end(); ++propertyNamesIt) {
+ propertyNames.append(*propertyNamesIt);
+ }
+ it = propertyNames.begin();
+ initialized = true;
+ }
+
+ QScriptValue objectValue;
+ QLinkedList<JSC::Identifier> propertyNames;
+ QLinkedList<JSC::Identifier>::iterator it;
+ QLinkedList<JSC::Identifier>::iterator current;
+ bool initialized;
+};
+
+/*!
+ Constructs an iterator for traversing \a object. The iterator is
+ set to be at the front of the sequence of properties (before the
+ first property).
+*/
+QScriptValueIterator::QScriptValueIterator(const QScriptValue &object)
+ : d_ptr(0)
+{
+ if (object.isObject()) {
+ d_ptr.reset(new QScriptValueIteratorPrivate());
+ d_ptr->objectValue = object;
+ }
+}
+
+/*!
+ Destroys the iterator.
+*/
+QScriptValueIterator::~QScriptValueIterator()
+{
+}
+
+/*!
+ Returns true if there is at least one item ahead of the iterator
+ (i.e. the iterator is \e not at the back of the property sequence);
+ otherwise returns false.
+
+ \sa next(), hasPrevious()
+*/
+bool QScriptValueIterator::hasNext() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->engine())
+ return false;
+
+ const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized();
+ return d->it != d->propertyNames.end();
+}
+
+/*!
+ Advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the
+ container leads to undefined results.
+
+ \sa hasNext(), previous(), name()
+*/
+void QScriptValueIterator::next()
+{
+ Q_D(QScriptValueIterator);
+ if (!d)
+ return;
+ d->ensureInitialized();
+
+ d->current = d->it;
+ ++(d->it);
+}
+
+/*!
+ Returns true if there is at least one item behind the iterator
+ (i.e. the iterator is \e not at the front of the property sequence);
+ otherwise returns false.
+
+ \sa previous(), hasNext()
+*/
+bool QScriptValueIterator::hasPrevious() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->engine())
+ return false;
+
+ const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized();
+ return d->it != d->propertyNames.begin();
+}
+
+/*!
+ Moves the iterator back by one position.
+
+ Calling this function on an iterator located at the front of the
+ container leads to undefined results.
+
+ \sa hasPrevious(), next(), name()
+*/
+void QScriptValueIterator::previous()
+{
+ Q_D(QScriptValueIterator);
+ if (!d)
+ return;
+ d->ensureInitialized();
+ --(d->it);
+ d->current = d->it;
+}
+
+/*!
+ Moves the iterator to the front of the QScriptValue (before the
+ first property).
+
+ \sa toBack(), next()
+*/
+void QScriptValueIterator::toFront()
+{
+ Q_D(QScriptValueIterator);
+ if (!d)
+ return;
+ d->ensureInitialized();
+ d->it = d->propertyNames.begin();
+}
+
+/*!
+ Moves the iterator to the back of the QScriptValue (after the
+ last property).
+
+ \sa toFront(), previous()
+*/
+void QScriptValueIterator::toBack()
+{
+ Q_D(QScriptValueIterator);
+ if (!d)
+ return;
+ d->ensureInitialized();
+ d->it = d->propertyNames.end();
+}
+
+/*!
+ Returns the name of the last property that was jumped over using
+ next() or previous().
+
+ \sa value(), flags()
+*/
+QString QScriptValueIterator::name() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return QString();
+ return d->current->ustring();
+}
+
+/*!
+ \since 4.4
+
+ Returns the name of the last property that was jumped over using
+ next() or previous().
+*/
+QScriptString QScriptValueIterator::scriptName() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return QScriptString();
+ return d->engine()->toStringHandle(*d->current);
+}
+
+/*!
+ Returns the value of the last property that was jumped over using
+ next() or previous().
+
+ \sa setValue(), name()
+*/
+QScriptValue QScriptValueIterator::value() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return QScriptValue();
+ QScript::APIShim shim(d->engine());
+ JSC::JSValue jsValue = d->object()->property(*d->current);
+ return d->engine()->scriptValueFromJSCValue(jsValue);
+}
+
+/*!
+ Sets the \a value of the last property that was jumped over using
+ next() or previous().
+
+ \sa value(), name()
+*/
+void QScriptValueIterator::setValue(const QScriptValue &value)
+{
+ Q_D(QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return;
+ QScript::APIShim shim(d->engine());
+ JSC::JSValue jsValue = d->engine()->scriptValueToJSCValue(value);
+ d->object()->setProperty(*d->current, jsValue);
+}
+
+/*!
+ Returns the flags of the last property that was jumped over using
+ next() or previous().
+
+ \sa value()
+*/
+QScriptValue::PropertyFlags QScriptValueIterator::flags() const
+{
+ Q_D(const QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return 0;
+ QScript::APIShim shim(d->engine());
+ return d->object()->propertyFlags(*d->current);
+}
+
+/*!
+ Removes the last property that was jumped over using next()
+ or previous().
+
+ \sa setValue()
+*/
+void QScriptValueIterator::remove()
+{
+ Q_D(QScriptValueIterator);
+ if (!d || !d->initialized || !d->engine())
+ return;
+ QScript::APIShim shim(d->engine());
+ d->object()->setProperty(*d->current, JSC::JSValue());
+ d->propertyNames.erase(d->current);
+}
+
+/*!
+ Makes the iterator operate on \a object. The iterator is set to be
+ at the front of the sequence of properties (before the first
+ property).
+*/
+QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue &object)
+{
+ d_ptr.reset();
+ if (object.isObject()) {
+ d_ptr.reset(new QScriptValueIteratorPrivate());
+ d_ptr->objectValue = object;
+ }
+ return *this;
+}
+
+QT_END_NAMESPACE
diff --git a/src/script/api/qscriptvalueiterator.h b/src/script/api/qscriptvalueiterator.h
new file mode 100644
index 0000000..d3dd987
--- /dev/null
+++ b/src/script/api/qscriptvalueiterator.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTVALUEITERATOR_H
+#define QSCRIPTVALUEITERATOR_H
+
+#include <QtScript/qscriptvalue.h>
+
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QString;
+class QScriptString;
+
+class QScriptValueIteratorPrivate;
+class Q_SCRIPT_EXPORT QScriptValueIterator
+{
+public:
+ QScriptValueIterator(const QScriptValue &value);
+ ~QScriptValueIterator();
+
+ bool hasNext() const;
+ void next();
+
+ bool hasPrevious() const;
+ void previous();
+
+ QString name() const;
+ QScriptString scriptName() const;
+
+ QScriptValue value() const;
+ void setValue(const QScriptValue &value);
+
+ QScriptValue::PropertyFlags flags() const;
+
+ void remove();
+
+ void toFront();
+ void toBack();
+
+ QScriptValueIterator& operator=(QScriptValue &value);
+
+private:
+ QScopedPointer<QScriptValueIteratorPrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QScriptValueIterator)
+ Q_DISABLE_COPY(QScriptValueIterator)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTVALUEITERATOR_H