aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/3rdparty/v80
-rw-r--r--src/declarative/debugger/qdeclarativedebughelper.cpp4
-rw-r--r--src/declarative/debugger/qjsdebuggeragent.cpp296
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h19
-rw-r--r--src/declarative/declarative.pro2
-rw-r--r--src/declarative/items/context2d/qsgcontext2d.cpp6
-rw-r--r--src/declarative/items/context2d/qsgcontext2d_p.h6
-rw-r--r--src/declarative/items/qsgitem.cpp2
-rw-r--r--src/declarative/qml/qdeclarative.h8
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp2
-rw-r--r--src/declarative/qml/qdeclarativecompileddata.cpp4
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp8
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h4
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp3
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp4
-rw-r--r--src/declarative/qml/qdeclarativecontext.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h2
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp11
-rw-r--r--src/declarative/qml/qdeclarativeengine.h7
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h5
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp20
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp14
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h12
-rw-r--r--src/declarative/qml/qdeclarativeprivate.h8
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp8
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h5
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase_p.h2
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp2
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h3
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h2
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp4
-rw-r--r--src/declarative/qml/qdeclarativevme_p.h2
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp40
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp10
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h2
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp5
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest_p.h2
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp44
-rw-r--r--src/declarative/qml/v4/qdeclarativev4irbuilder.cpp2
-rw-r--r--src/declarative/qml/v8/qjsconverter_p.h272
-rw-r--r--src/declarative/qml/v8/qjsengine.cpp431
-rw-r--r--src/declarative/qml/v8/qjsengine.h151
-rw-r--r--src/declarative/qml/v8/qjsvalue.cpp1024
-rw-r--r--src/declarative/qml/v8/qjsvalue.h165
-rw-r--r--src/declarative/qml/v8/qjsvalue_impl_p.h1133
-rw-r--r--src/declarative/qml/v8/qjsvalue_p.h213
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator.cpp294
-rw-r--r--src/declarative/qml/v8/qjsvalueiterator.h64
-rw-r--r--src/declarative/qml/v8/qscript_impl_p.h41
-rw-r--r--src/declarative/qml/v8/qscriptisolate_p.h71
-rw-r--r--src/declarative/qml/v8/qscriptoriginalglobalobject_p.h158
-rw-r--r--src/declarative/qml/v8/qscriptshareddata_p.h151
-rw-r--r--src/declarative/qml/v8/qscripttools_p.h216
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp2
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp751
-rw-r--r--src/declarative/qml/v8/qv8engine_impl_p.h131
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h108
-rw-r--r--src/declarative/qml/v8/qv8include.cpp2
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp36
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp20
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper.cpp38
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper_p.h4
-rw-r--r--src/declarative/qml/v8/script.pri20
-rw-r--r--src/declarative/qml/v8/v8.pri4
-rw-r--r--src/declarative/util/qdeclarativebind.cpp5
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp4
-rw-r--r--src/imports/folderlistmodel/folderlistmodel.pro2
-rw-r--r--src/imports/gestures/gestures.pro2
-rwxr-xr-xsrc/imports/inputcontext/inputcontext.pro2
-rw-r--r--src/imports/inputcontext/plugin.cpp2
-rw-r--r--src/imports/testlib/main.cpp6
-rw-r--r--src/imports/testlib/testlib.pro2
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/qmltest/quicktest.cpp7
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitem.cpp2
-rw-r--r--src/qtquick1/qtquick1.pro2
-rw-r--r--src/qtquick1/util/qdeclarativebind.cpp5
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel.cpp2
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel_p.h2
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel_p_p.h2
-rw-r--r--src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h2
-rw-r--r--src/qtquick1/util/qdeclarativeview.cpp1
-rw-r--r--src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch286
-rw-r--r--src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch397
-rw-r--r--src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch63
87 files changed, 6464 insertions, 420 deletions
diff --git a/src/3rdparty/v8 b/src/3rdparty/v8
-Subproject bec11b8b7f89d135e7d9a823ac4fe98c70d017c
+Subproject 472c04c9e7a64e8734c76d2cf97a7cc5b773b78
diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp
index 6eea82c948..5f5d8754bb 100644
--- a/src/declarative/debugger/qdeclarativedebughelper.cpp
+++ b/src/declarative/debugger/qdeclarativedebughelper.cpp
@@ -39,12 +39,10 @@
**
****************************************************************************/
-#include <QtScript/QScriptEngine>
-
#include "private/qdeclarativedebughelper_p.h"
#include <QtCore/QAbstractAnimation>
-#include <QtScript/QScriptEngine>
+#include <QtDeclarative/QJSEngine>
#include <private/qdeclarativeengine_p.h>
#include <private/qabstractanimation_p.h>
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
index 3169f91b59..f47def802a 100644
--- a/src/declarative/debugger/qjsdebuggeragent.cpp
+++ b/src/declarative/debugger/qjsdebuggeragent.cpp
@@ -46,9 +46,9 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtCore/qurl.h>
-#include <QtScript/qscriptcontextinfo.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptvalueiterator.h>
+#include <QtDeclarative/qjsengine.h>
+
+#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
@@ -61,9 +61,9 @@ public:
void continueExec();
void recordKnownObjects(const QList<JSAgentWatchData> &);
- QList<JSAgentWatchData> getLocals(QScriptContext *);
+ QList<JSAgentWatchData> getLocals(void *);
void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
- QScriptEngine *engine() { return q->engine(); }
+ QJSEngine *engine() { return q->engine(); }
void stopped();
public:
@@ -111,7 +111,7 @@ private:
} // anonymous namespace
static JSAgentWatchData fromScriptValue(const QString &expression,
- const QScriptValue &value)
+ const QJSValue &value)
{
static const QString arrayStr = QCoreApplication::translate
("Debugger::JSAgentWatchData", "[Array of length %1]");
@@ -123,7 +123,7 @@ static JSAgentWatchData fromScriptValue(const QString &expression,
data.name = data.exp;
data.hasChildren = false;
data.value = value.toString().toUtf8();
- data.objectId = value.objectId();
+ // data.objectId = value.objectId();
if (value.isArray()) {
data.type = "Array";
data.value = arrayStr.arg(value.property(QLatin1String("length")).toString()).toUtf8();
@@ -167,30 +167,30 @@ static JSAgentWatchData fromScriptValue(const QString &expression,
return data;
}
-static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
+static QList<JSAgentWatchData> expandObject(const QJSValue &object)
{
QList<JSAgentWatchData> result;
- QScriptValueIterator it(object);
- while (it.hasNext()) {
- it.next();
- if (it.flags() & QScriptValue::SkipInEnumeration)
- continue;
- if (/*object.isQObject() &&*/ it.value().isFunction()) {
- // Cosmetics: skip all functions and slot, there are too many of them,
- // and it is not useful information in the debugger.
- continue;
- }
- JSAgentWatchData data = fromScriptValue(it.name(), it.value());
- result.append(data);
- }
- if (result.isEmpty()) {
- JSAgentWatchData data;
- data.name = "<no initialized data>";
- data.hasChildren = false;
- data.value = " ";
- data.objectId = 0;
- result.append(data);
- }
+// QScriptValueIterator it(object);
+// while (it.hasNext()) {
+// it.next();
+// if (it.flags() & QScriptValue::SkipInEnumeration)
+// continue;
+// if (/*object.isQObject() &&*/ it.value().isFunction()) {
+// // Cosmetics: skip all functions and slot, there are too many of them,
+// // and it is not useful information in the debugger.
+// continue;
+// }
+// JSAgentWatchData data = fromScriptValue(it.name(), it.value());
+// result.append(data);
+// }
+// if (result.isEmpty()) {
+// JSAgentWatchData data;
+// data.name = "<no initialized data>";
+// data.hasChildren = false;
+// data.value = " ";
+// data.objectId = 0;
+// result.append(data);
+// }
return result;
}
@@ -206,20 +206,20 @@ void QJSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>&
knownObjectIds << data.objectId;
}
-QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
+QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(void *ctx)
{
QList<JSAgentWatchData> locals;
- if (ctx) {
- QScriptValue activationObject = ctx->activationObject();
- QScriptValue thisObject = ctx->thisObject();
- locals = expandObject(activationObject);
- if (thisObject.isObject()
- && thisObject.objectId() != engine()->globalObject().objectId()
- && QScriptValueIterator(thisObject).hasNext())
- locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
- recordKnownObjects(locals);
- knownObjectIds << activationObject.objectId();
- }
+// if (ctx) {
+// QScriptValue activationObject = ctx->activationObject();
+// QScriptValue thisObject = ctx->thisObject();
+// locals = expandObject(activationObject);
+// if (thisObject.isObject()
+// && thisObject.objectId() != engine()->globalObject().objectId()
+// && QScriptValueIterator(thisObject).hasNext())
+// locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
+// recordKnownObjects(locals);
+// knownObjectIds << activationObject.objectId();
+// }
return locals;
}
@@ -228,20 +228,18 @@ QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
report debugging-related events (e.g. step completion) to the given
\a backend.
*/
-QJSDebuggerAgent::QJSDebuggerAgent(QScriptEngine *engine, QObject *parent)
+QJSDebuggerAgent::QJSDebuggerAgent(QJSEngine *engine, QObject *parent)
: QObject(parent)
- , QScriptEngineAgent(engine)
, d(new QJSDebuggerAgentPrivate(this))
{
- QJSDebuggerAgent::engine()->setAgent(this);
+ //QJSDebuggerAgent::engine()->setAgent(this);
}
QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
: QObject(parent)
- , QScriptEngineAgent(0)
, d(new QJSDebuggerAgentPrivate(this))
{
- QJSDebuggerAgent::engine()->setAgent(this);
+ //QJSDebuggerAgent::engine()->setAgent(this);
}
/*!
@@ -249,7 +247,7 @@ QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
*/
QJSDebuggerAgent::~QJSDebuggerAgent()
{
- engine()->setAgent(0);
+ //engine()->setAgent(0);
delete d;
}
@@ -317,9 +315,9 @@ QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
{
SetupExecEnv execEnv(d);
- QScriptValue v;
- if (d->knownObjectIds.contains(objectId))
- v = engine()->objectById(objectId);
+ QJSValue v;
+// if (d->knownObjectIds.contains(objectId))
+// v = engine()->objectById(objectId);
QList<JSAgentWatchData> result = expandObject(v);
d->recordKnownObjects(result);
@@ -329,21 +327,21 @@ QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
QList<JSAgentWatchData> QJSDebuggerAgent::locals()
{
SetupExecEnv execEnv(d);
- return d->getLocals(engine()->currentContext());
+ return d->getLocals(0/*engine()->currentContext()*/);
}
QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId)
{
SetupExecEnv execEnv(d);
- int deep = 0;
- QScriptContext *ctx = engine()->currentContext();
- while (ctx && deep < frameId) {
- ctx = ctx->parentContext();
- deep++;
- }
+// int deep = 0;
+// QScriptContext *ctx = engine()->currentContext();
+// while (ctx && deep < frameId) {
+// ctx = ctx->parentContext();
+// deep++;
+// }
- return d->getLocals(ctx);
+ return d->getLocals(0/*ctx*/);
}
QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
@@ -352,37 +350,37 @@ QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
QList<JSAgentStackData> backtrace;
- for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
- QScriptContextInfo info(ctx);
-
- JSAgentStackData frame;
- frame.functionName = info.functionName().toUtf8();
- if (frame.functionName.isEmpty()) {
- if (ctx->parentContext()) {
- switch (info.functionType()) {
- case QScriptContextInfo::ScriptFunction:
- frame.functionName = "<anonymous>";
- break;
- case QScriptContextInfo::NativeFunction:
- frame.functionName = "<native>";
- break;
- case QScriptContextInfo::QtFunction:
- case QScriptContextInfo::QtPropertyFunction:
- frame.functionName = "<native slot>";
- break;
- }
- } else {
- frame.functionName = "<global>";
- }
- }
- frame.lineNumber = info.lineNumber();
- // if the line number is unknown, fallback to the function line number
- if (frame.lineNumber == -1)
- frame.lineNumber = info.functionStartLineNumber();
-
- frame.fileUrl = info.fileName().toUtf8();
- backtrace.append(frame);
- }
+// for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
+// QScriptContextInfo info(ctx);
+
+// JSAgentStackData frame;
+// frame.functionName = info.functionName().toUtf8();
+// if (frame.functionName.isEmpty()) {
+// if (ctx->parentContext()) {
+// switch (info.functionType()) {
+// case QScriptContextInfo::ScriptFunction:
+// frame.functionName = "<anonymous>";
+// break;
+// case QScriptContextInfo::NativeFunction:
+// frame.functionName = "<native>";
+// break;
+// case QScriptContextInfo::QtFunction:
+// case QScriptContextInfo::QtPropertyFunction:
+// frame.functionName = "<native slot>";
+// break;
+// }
+// } else {
+// frame.functionName = "<global>";
+// }
+// }
+// frame.lineNumber = info.lineNumber();
+// // if the line number is unknown, fallback to the function line number
+// if (frame.lineNumber == -1)
+// frame.lineNumber = info.functionStartLineNumber();
+
+// frame.fileUrl = info.fileName().toUtf8();
+// backtrace.append(frame);
+// }
return backtrace;
}
@@ -405,9 +403,9 @@ void QJSDebuggerAgent::setProperty(qint64 objectId,
SetupExecEnv execEnv(d);
if (d->knownObjectIds.contains(objectId)) {
- QScriptValue object = engine()->objectById(objectId);
+ QJSValue object;// = engine()->objectById(objectId);
if (object.isObject()) {
- QScriptValue result = engine()->evaluate(value);
+ QJSValue result = engine()->evaluate(value);
object.setProperty(property, result);
}
}
@@ -457,7 +455,7 @@ void QJSDebuggerAgent::functionEntry(qint64 scriptId)
/*!
\reimp
*/
-void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
+void QJSDebuggerAgent::functionExit(qint64 scriptId, const QJSValue &returnValue)
{
Q_UNUSED(scriptId);
Q_UNUSED(returnValue);
@@ -476,53 +474,53 @@ void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, in
{
Q_UNUSED(columnNumber);
- if (state == StoppedState)
- return; //no re-entrency
-
- // check breakpoints
- if (!breakpoints.isEmpty()) {
- QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
- QScriptContext *ctx = engine()->currentContext();
- QScriptContextInfo info(ctx);
- if (it == filenames.constEnd()) {
- // It is possible that the scripts are loaded before the agent is attached
- QString filename = info.fileName();
-
- JSAgentStackData frame;
- frame.functionName = info.functionName().toUtf8();
-
- QPair<QString, qint32> key = qMakePair(filename, lineNumber);
- it = filenames.insert(scriptId, filename);
- }
-
- const QString filePath = it.value();
- JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
-
- foreach (const JSAgentBreakpointData &bp, bps) {
- if (bp.lineNumber == lineNumber) {
- stopped();
- return;
- }
- }
- }
-
- switch (state) {
- case NoState:
- case StoppedState:
- // Do nothing
- break;
- case SteppingOutState:
- if (stepDepth >= 0)
- break;
- //fallthough
- case SteppingOverState:
- if (stepDepth > 0)
- break;
- //fallthough
- case SteppingIntoState:
- stopped();
- break;
- }
+// if (state == StoppedState)
+// return; //no re-entrency
+
+// // check breakpoints
+// if (!breakpoints.isEmpty()) {
+// QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+// QScriptContext *ctx = engine()->currentContext();
+// QScriptContextInfo info(ctx);
+// if (it == filenames.constEnd()) {
+// // It is possible that the scripts are loaded before the agent is attached
+// QString filename = info.fileName();
+
+// JSAgentStackData frame;
+// frame.functionName = info.functionName().toUtf8();
+
+// QPair<QString, qint32> key = qMakePair(filename, lineNumber);
+// it = filenames.insert(scriptId, filename);
+// }
+
+// const QString filePath = it.value();
+// JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
+
+// foreach (const JSAgentBreakpointData &bp, bps) {
+// if (bp.lineNumber == lineNumber) {
+// stopped();
+// return;
+// }
+// }
+// }
+
+// switch (state) {
+// case NoState:
+// case StoppedState:
+// // Do nothing
+// break;
+// case SteppingOutState:
+// if (stepDepth >= 0)
+// break;
+// //fallthough
+// case SteppingOverState:
+// if (stepDepth > 0)
+// break;
+// //fallthough
+// case SteppingIntoState:
+// stopped();
+// break;
+// }
}
@@ -530,7 +528,7 @@ void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, in
\reimp
*/
void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
- const QScriptValue &exception,
+ const QJSValue &exception,
bool hasHandler)
{
Q_UNUSED(scriptId);
@@ -546,30 +544,16 @@ void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
/*!
\reimp
*/
-void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
+void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QJSValue &exception)
{
Q_UNUSED(scriptId);
Q_UNUSED(exception);
}
-bool QJSDebuggerAgent::supportsExtension(Extension extension) const
-{
- return extension == QScriptEngineAgent::DebuggerInvocationRequest;
-}
-
-QVariant QJSDebuggerAgent::extension(Extension extension, const QVariant &argument)
-{
- if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
- d->stopped();
- return QVariant();
- }
- return QScriptEngineAgent::extension(extension, argument);
-}
-
void QJSDebuggerAgentPrivate::stopped()
{
bool becauseOfException = false;
- const QScriptValue &exception = QScriptValue();
+ const QJSValue &exception = QJSValue();
knownObjectIds.clear();
state = StoppedState;
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
index 309588eb2f..30cbfe67b4 100644
--- a/src/declarative/debugger/qjsdebuggeragent_p.h
+++ b/src/declarative/debugger/qjsdebuggeragent_p.h
@@ -53,11 +53,11 @@
// We mean it.
//
-#include <QtScript/qscriptengineagent.h>
#include <QtCore/qset.h>
+#include <QtDeclarative/qjsengine.h>
QT_BEGIN_NAMESPACE
-class QScriptValue;
+class QJSValue;
class QDeclarativeEngine;
QT_END_NAMESPACE
@@ -136,16 +136,17 @@ inline uint qHash(const JSAgentBreakpointData &b)
}
-class QJSDebuggerAgent : public QObject, public QScriptEngineAgent
+class QJSDebuggerAgent : public QObject
{
Q_OBJECT
public:
- QJSDebuggerAgent(QScriptEngine *engine, QObject *parent = 0);
+ QJSDebuggerAgent(QJSEngine *engine, QObject *parent = 0);
QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent = 0);
~QJSDebuggerAgent();
bool isInitialized() const;
+ QJSEngine * engine() {return 0; }
void setBreakpoints(const JSAgentBreakpoints &);
void setWatchExpressions(const QStringList &);
@@ -175,20 +176,16 @@ public:
void functionEntry(qint64 scriptId);
void functionExit(qint64 scriptId,
- const QScriptValue &returnValue);
+ const QJSValue &returnValue);
void positionChange(qint64 scriptId,
int lineNumber, int columnNumber);
void exceptionThrow(qint64 scriptId,
- const QScriptValue &exception,
+ const QJSValue &exception,
bool hasHandler);
void exceptionCatch(qint64 scriptId,
- const QScriptValue &exception);
-
- bool supportsExtension(Extension extension) const;
- QVariant extension(Extension extension,
- const QVariant &argument = QVariant());
+ const QJSValue &exception);
Q_SIGNALS:
void stopped(bool becauseOfException,
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index aa638e468e..2d9248ef66 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -6,7 +6,7 @@ QPRO_PWD = $$PWD
CONFIG += module
MODULE_PRI += ../../modules/qt_declarative.pri
-QT = core-private gui-private script-private network script opengl-private
+QT = core-private gui-private network opengl-private
contains(QT_CONFIG, svg): QT += svg
DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp
index 97234a6315..4cfe1ba012 100644
--- a/src/declarative/items/context2d/qsgcontext2d.cpp
+++ b/src/declarative/items/context2d/qsgcontext2d.cpp
@@ -3361,7 +3361,7 @@ void QSGContext2D::release()
}
}
-void QSGContext2D::processCommands(const QScriptValue& commands)
+void QSGContext2D::processCommands(const QJSValue& commands)
{
#ifdef QSGCANVASITEM_DEBUG
QElapsedTimer t;
@@ -3369,7 +3369,7 @@ void QSGContext2D::processCommands(const QScriptValue& commands)
#endif
int ii = 0;
if (commands.isArray()) {
- QScriptValue cmd = commands.property(ii);
+ QJSValue cmd = commands.property(ii);
while(cmd.isValid()) {
processCommand(cmd);
ii++;
@@ -3460,7 +3460,7 @@ bool QSGContext2D::event(QEvent *e)
return QObject::event(e);
}
-void QSGContext2D::processCommand(const QScriptValue& cmd)
+void QSGContext2D::processCommand(const QJSValue& cmd)
{
int action = cmd.property(0).toInt32();
switch (action) {
diff --git a/src/declarative/items/context2d/qsgcontext2d_p.h b/src/declarative/items/context2d/qsgcontext2d_p.h
index 335d954fc1..f8fc9b75a2 100644
--- a/src/declarative/items/context2d/qsgcontext2d_p.h
+++ b/src/declarative/items/context2d/qsgcontext2d_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qvariant.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <private/qv8engine_p.h>
#include <QMutex>
#include <QWaitCondition>
@@ -323,7 +323,7 @@ public slots:
void paint(QPainter* painter);
void sync();
- void processCommands(const QScriptValue& commands);
+ void processCommands(const QJSValue& commands);
signals:
void changed();
void painted();
@@ -385,7 +385,7 @@ protected:
virtual bool event(QEvent *);
private:
- void processCommand(const QScriptValue& command);
+ void processCommand(const QJSValue& command);
Q_DECLARE_PRIVATE(QSGContext2D)
};
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index 55d84a7fa5..043c568a82 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -42,7 +42,7 @@
#include "qsgitem.h"
#include "qsgcanvas.h"
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
#include "qsgcanvas_p.h"
#include "qsgevent.h"
diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h
index 38b2a841ba..4c962f890e 100644
--- a/src/declarative/qml/qdeclarative.h
+++ b/src/declarative/qml/qdeclarative.h
@@ -395,8 +395,8 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
class QDeclarativeContext;
class QDeclarativeEngine;
-class QScriptValue;
-class QScriptEngine;
+class QJSValue;
+class QJSEngine;
Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *);
Q_DECLARATIVE_EXPORT QDeclarativeContext *qmlContext(const QObject *);
Q_DECLARATIVE_EXPORT QDeclarativeEngine *qmlEngine(const QObject *);
@@ -454,7 +454,7 @@ Q_DECLARATIVE_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor
\endqml
*/
inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor,
- QScriptValue (*callback)(QDeclarativeEngine *, QScriptEngine *))
+ QJSValue (*callback)(QDeclarativeEngine *, QJSEngine *))
{
QDeclarativePrivate::RegisterModuleApi api = {
0,
@@ -537,7 +537,7 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi
\endqml
*/
inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor,
- QObject *(*callback)(QDeclarativeEngine *, QScriptEngine *))
+ QObject *(*callback)(QDeclarativeEngine *, QJSEngine *))
{
QDeclarativePrivate::RegisterModuleApi api = {
0,
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 684726d346..069744153a 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -367,7 +367,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
bool isUndefined = false;
v8::HandleScope handle_scope;
- v8::Context::Scope scope(ep->v8engine.context());
+ v8::Context::Scope scope(ep->v8engine()->context());
v8::Local<v8::Value> result = d->v8value(0, &isUndefined);
bool needsErrorData = false;
diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp
index d08a808d77..da7c3fea7b 100644
--- a/src/declarative/qml/qdeclarativecompileddata.cpp
+++ b/src/declarative/qml/qdeclarativecompileddata.cpp
@@ -126,7 +126,6 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData()
if (rootPropertyCache)
rootPropertyCache->release();
- qDeleteAll(cachedPrograms);
qDeleteAll(cachedClosures);
for (int ii = 0; ii < v8bindings.count(); ++ii)
@@ -135,12 +134,9 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData()
void QDeclarativeCompiledData::clear()
{
- qDeleteAll(cachedPrograms);
qDeleteAll(cachedClosures);
for (int ii = 0; ii < cachedClosures.count(); ++ii)
cachedClosures[ii] = 0;
- for (int ii = 0; ii < cachedPrograms.count(); ++ii)
- cachedPrograms[ii] = 0;
}
const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 7a15aed460..5e1d3f60a9 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -2371,7 +2371,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
if (propName.at(0).isUpper())
COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine.illegalNames().contains(propName))
+ if (enginePrivate->v8engine()->illegalNames().contains(propName))
COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
propNames.insert(prop.name);
@@ -2384,7 +2384,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine.illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
methodNames.insert(name);
}
@@ -2395,7 +2395,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine.illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal method name"));
methodNames.insert(name);
}
@@ -2689,7 +2689,7 @@ bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QStr
}
- if (enginePrivate->v8engine.illegalNames().contains(val))
+ if (enginePrivate->v8engine()->illegalNames().contains(val))
COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
return true;
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index a1dfabbd46..a2b959a568 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -76,7 +76,6 @@ class QDeclarativeComponent;
class QDeclarativeContext;
class QDeclarativeContextData;
-class QScriptProgram;
class Q_AUTOTEST_EXPORT QDeclarativeCompiledData : public QDeclarativeRefCount, public QDeclarativeCleanup
{
public:
@@ -112,8 +111,7 @@ public:
QList<QString> primitives;
QList<QByteArray> datas;
QByteArray bytecode;
- QList<QScriptProgram *> cachedPrograms;
- QList<QScriptValue *> cachedClosures;
+ QList<QJSValue *> cachedClosures;
QList<QDeclarativePropertyCache *> propertyCaches;
QList<QDeclarativeIntegerCache *> contextCaches;
QList<QDeclarativeScriptData *> scripts;
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index b6bcc64afa..ca7f3e0f74 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -54,7 +54,6 @@
#include "private/qdeclarativescriptparser_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeenginedebug_p.h"
-#include <QtScript/qscriptvalueiterator.h>
#include <QStack>
#include <QStringList>
@@ -672,7 +671,7 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args)
QDeclarativeEngine *engine = d->engine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QV8Engine *v8engine = &ep->v8engine;
+ QV8Engine *v8engine = ep->v8engine();
QDeclarativeContext *ctxt = creationContext();
if (!ctxt) ctxt = engine->rootContext();
diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h
index bb4d886914..a3457d1446 100644
--- a/src/declarative/qml/qdeclarativecomponent.h
+++ b/src/declarative/qml/qdeclarativecomponent.h
@@ -47,7 +47,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
QT_BEGIN_HEADER
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index d625a1fd98..ff6e628c66 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -50,12 +50,10 @@
#include "private/qdeclarativev4bindings_p.h"
#include "private/qv8bindings_p.h"
-#include <qscriptengine.h>
+#include <qjsengine.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
-#include <private/qscriptdeclarativeclass_p.h>
-
QT_BEGIN_NAMESPACE
QDeclarativeContextPrivate::QDeclarativeContextPrivate()
diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h
index d8e8506dad..9c2fd01645 100644
--- a/src/declarative/qml/qdeclarativecontext.h
+++ b/src/declarative/qml/qdeclarativecontext.h
@@ -44,7 +44,7 @@
#include <QtCore/qurl.h>
#include <QtCore/qobject.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qvariant.h>
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index bb9c2ada02..5f4072130a 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -63,7 +63,7 @@
#include "private/qdeclarativeparser_p.h"
#include <QtCore/qhash.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtCore/qset.h>
#include <private/qobject_p.h>
diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h
index 9fe5e732b7..aebea738bd 100644
--- a/src/declarative/qml/qdeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedata_p.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <private/qobject_p.h>
#include <private/qv8_p.h>
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index cf672ef337..a2f724e3f8 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -441,7 +441,7 @@ void QDeclarativeEnginePrivate::init()
Q_Q(QDeclarativeEngine);
qRegisterMetaType<QVariant>("QVariant");
qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
- qRegisterMetaType<QScriptValue>("QScriptValue");
+ qRegisterMetaType<QJSValue>("QJSValue");
qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
qRegisterMetaType<QList<int> >("QList<int>");
@@ -449,8 +449,7 @@ void QDeclarativeEnginePrivate::init()
QDeclarativeData::init();
- // Init V8 data
- v8engine.init(q);
+ v8engine()->setEngine(q);
rootContext = new QDeclarativeContext(q,true);
@@ -505,7 +504,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine
Create a new QDeclarativeEngine with the given \a parent.
*/
QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
-: QObject(*new QDeclarativeEnginePrivate(this), parent)
+: QJSEngine(*new QDeclarativeEnginePrivate(this), parent)
{
Q_D(QDeclarativeEngine);
d->init();
@@ -1386,13 +1385,13 @@ bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &ur
void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
{
Q_D(QDeclarativeEngine);
- qt_qmlsqldatabase_setOfflineStoragePath(&d->v8engine, dir);
+ qt_qmlsqldatabase_setOfflineStoragePath(d->v8engine(), dir);
}
QString QDeclarativeEngine::offlineStoragePath() const
{
Q_D(const QDeclarativeEngine);
- return qt_qmlsqldatabase_getOfflineStoragePath(&d->v8engine);
+ return qt_qmlsqldatabase_getOfflineStoragePath(d->v8engine());
}
static void voidptr_destructor(void *v)
diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h
index e97c2d96b0..3f90296681 100644
--- a/src/declarative/qml/qdeclarativeengine.h
+++ b/src/declarative/qml/qdeclarativeengine.h
@@ -45,7 +45,8 @@
#include <QtCore/qurl.h>
#include <QtCore/qobject.h>
#include <QtCore/qmap.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsengine.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtDeclarative/qdeclarativeerror.h>
QT_BEGIN_HEADER
@@ -61,12 +62,12 @@ class QDeclarativeExpression;
class QDeclarativeContext;
class QDeclarativeType;
class QUrl;
-class QScriptEngine;
+class QJSEngine;
class QScriptContext;
class QDeclarativeImageProvider;
class QNetworkAccessManager;
class QDeclarativeNetworkAccessManagerFactory;
-class Q_DECLARATIVE_EXPORT QDeclarativeEngine : public QObject
+class Q_DECLARATIVE_EXPORT QDeclarativeEngine : public QJSEngine
{
Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
Q_OBJECT
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 538e8a05a0..6ff12189da 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -139,8 +139,7 @@ public:
QDeclarativeDelayedError *erroredBindings;
int inProgressCreations;
- // V8 Engine
- QV8Engine v8engine;
+ QV8Engine *v8engine() const { return q_func()->handle(); }
QDeclarativeWorkerScriptEngine *getWorkerScriptEngine();
QDeclarativeWorkerScriptEngine *workerScriptEngine;
@@ -256,7 +255,7 @@ public:
static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &);
static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &);
- static QV8Engine *getV8Engine(QDeclarativeEngine *e) { return &e->d_func()->v8engine; }
+ static QV8Engine *getV8Engine(QDeclarativeEngine *e) { return e->d_func()->v8engine(); }
static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e) { return e->d_func(); }
static QDeclarativeEnginePrivate *get(QDeclarativeContext *c) { return (c && c->engine()) ? QDeclarativeEnginePrivate::get(c->engine()) : 0; }
static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c) { return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0; }
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index ff19a07313..8806996bd4 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -144,11 +144,11 @@ QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObje
// XXX TODO: Implement script caching, like we used to do with QScriptProgram in the
// QtScript days
v8::HandleScope handle_scope;
- v8::Context::Scope ctxtscope(ep->v8engine.context());
+ v8::Context::Scope ctxtscope(ep->v8engine()->context());
v8::TryCatch tc;
- v8::Local<v8::Object> scopeobject = ep->v8engine.qmlScope(ctxt, scope);
- v8::Local<v8::Script> script = ep->v8engine.qmlModeCompile(code, filename, line);
+ v8::Local<v8::Object> scopeobject = ep->v8engine()->qmlScope(ctxt, scope);
+ v8::Local<v8::Script> script = ep->v8engine()->qmlModeCompile(code, filename, line);
v8::Local<v8::Value> result = script->Run(scopeobject);
if (tc.HasCaught()) return v8::Persistent<v8::Function>();
if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject);
@@ -485,9 +485,9 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
v8::Local<v8::Value> result;
{
v8::TryCatch try_catch;
- v8::Handle<v8::Object> This = ep->v8engine.global();
+ v8::Handle<v8::Object> This = ep->v8engine()->global();
if (scopeObject() && requiresThisObject()) {
- v8::Handle<v8::Value> value = ep->v8engine.newQObject(scopeObject());
+ v8::Handle<v8::Value> value = ep->v8engine()->newQObject(scopeObject());
if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
}
@@ -498,7 +498,7 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
if (watcher.wasDeleted()) {
} else if (try_catch.HasCaught()) {
- v8::Context::Scope scope(ep->v8engine.context());
+ v8::Context::Scope scope(ep->v8engine()->context());
v8::Local<v8::Message> message = try_catch.Message();
if (!message.IsEmpty()) {
QDeclarativeExpressionPrivate::exceptionToError(message, error);
@@ -638,9 +638,9 @@ v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondarySc
v8::Local<v8::Value> result;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
QObject *restoreSecondaryScope = 0;
- restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
+ restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
result = evaluate(v8function, isUndefined);
- ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
+ ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
return result;
} else {
return evaluate(v8function, isUndefined);
@@ -663,9 +663,9 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU
{
v8::HandleScope handle_scope;
- v8::Context::Scope context_scope(ep->v8engine.context());
+ v8::Context::Scope context_scope(ep->v8engine()->context());
v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
- rv = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject*> >());
+ rv = ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index 18eea0b614..41705bce72 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -61,7 +61,7 @@
#include <qvector.h>
#include <qlocale.h>
#include <QtCore/qcryptographichash.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <ctype.h>
@@ -1114,7 +1114,7 @@ QT_END_NAMESPACE
#include <QtGui/qquaternion.h>
#include <private/qv8engine_p.h>
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QJSValue);
Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -1195,7 +1195,7 @@ bool QDeclarativeMetaType::canCopy(int type)
default:
if (type == qMetaTypeId<QVariant>() ||
- type == qMetaTypeId<QScriptValue>() ||
+ type == qMetaTypeId<QJSValue>() ||
type == qMetaTypeId<QDeclarativeV8Handle>() ||
typeCategory(type) != Unknown) {
return true;
@@ -1416,8 +1416,8 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
if (type == qMetaTypeId<QVariant>()) {
*static_cast<NS(QVariant) *>(data) = *static_cast<const NS(QVariant)*>(copy);
return true;
- } else if (type == qMetaTypeId<QScriptValue>()) {
- *static_cast<NS(QScriptValue) *>(data) = *static_cast<const NS(QScriptValue)*>(copy);
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ *static_cast<NS(QJSValue) *>(data) = *static_cast<const NS(QJSValue)*>(copy);
return true;
} else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
*static_cast<NS(QDeclarativeV8Handle) *>(data) = *static_cast<const NS(QDeclarativeV8Handle)*>(copy);
@@ -1626,8 +1626,8 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
if (type == qMetaTypeId<QVariant>()) {
*static_cast<NS(QVariant) *>(data) = NS(QVariant)();
return true;
- } else if (type == qMetaTypeId<QScriptValue>()) {
- *static_cast<NS(QScriptValue) *>(data) = NS(QScriptValue)();
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ *static_cast<NS(QJSValue) *>(data) = NS(QJSValue)();
return true;
} else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
*static_cast<NS(QDeclarativeV8Handle) *>(data) = NS(QDeclarativeV8Handle)();
diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h
index cfc4f077f8..429aa7a98f 100644
--- a/src/declarative/qml/qdeclarativemetatype_p.h
+++ b/src/declarative/qml/qdeclarativemetatype_p.h
@@ -59,7 +59,7 @@
#include <QtCore/qvariant.h>
#include <QtCore/qbitarray.h>
#include <private/qdeclarativeglobal_p.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
QT_BEGIN_NAMESPACE
@@ -113,9 +113,9 @@ public:
ModuleApiInstance()
: scriptCallback(0), qobjectCallback(0), qobjectApi(0) {}
- QScriptValue (*scriptCallback)(QDeclarativeEngine *, QScriptEngine *);
- QObject *(*qobjectCallback)(QDeclarativeEngine *, QScriptEngine *);
- QScriptValue scriptApi;
+ QJSValue (*scriptCallback)(QDeclarativeEngine *, QJSEngine *);
+ QObject *(*qobjectCallback)(QDeclarativeEngine *, QJSEngine *);
+ QJSValue scriptApi;
QObject *qobjectApi;
};
struct ModuleApi {
@@ -123,8 +123,8 @@ public:
inline bool operator==(const ModuleApi &) const;
int major;
int minor;
- QScriptValue (*script)(QDeclarativeEngine *, QScriptEngine *);
- QObject *(*qobject)(QDeclarativeEngine *, QScriptEngine *);
+ QJSValue (*script)(QDeclarativeEngine *, QJSEngine *);
+ QObject *(*qobject)(QDeclarativeEngine *, QJSEngine *);
};
static ModuleApi moduleApi(const QByteArray &, int, int);
};
diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h
index 9eacc1d1cb..e8e8f229cf 100644
--- a/src/declarative/qml/qdeclarativeprivate.h
+++ b/src/declarative/qml/qdeclarativeprivate.h
@@ -74,8 +74,8 @@ public:
};
-class QScriptValue;
-class QScriptEngine;
+class QJSValue;
+class QJSEngine;
class QDeclarativeEngine;
class QDeclarativeCustomParser;
namespace QDeclarativePrivate
@@ -243,8 +243,8 @@ namespace QDeclarativePrivate
int versionMajor;
int versionMinor;
- QScriptValue (*scriptApi)(QDeclarativeEngine *, QScriptEngine *);
- QObject *(*qobjectApi)(QDeclarativeEngine *, QScriptEngine *);
+ QJSValue (*scriptApi)(QDeclarativeEngine *, QJSEngine *);
+ QObject *(*qobjectApi)(QDeclarativeEngine *, QJSEngine *);
};
enum RegistrationType {
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 6ff47d7b57..d2148ad874 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -49,7 +49,7 @@
#include <QtCore/qdebug.h>
-Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QJSValue)
Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -83,8 +83,8 @@ static QDeclarativePropertyCache::Data::Flags flagsForPropertyType(int propType,
if (propType < QMetaType::User && propType != QMetaType::QObjectStar && propType != QMetaType::QWidgetStar) {
} else if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
flags |= QDeclarativePropertyCache::Data::IsQmlBinding;
- } else if (propType == qMetaTypeId<QScriptValue>()) {
- flags |= QDeclarativePropertyCache::Data::IsQScriptValue;
+ } else if (propType == qMetaTypeId<QJSValue>()) {
+ flags |= QDeclarativePropertyCache::Data::IsQJSValue;
} else if (propType == qMetaTypeId<QDeclarativeV8Handle>()) {
flags |= QDeclarativePropertyCache::Data::IsV8Handle;
} else {
@@ -518,7 +518,7 @@ QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
rv = cache->property(name);
} else {
QString strname = QV8Engine::toStringStatic(name.string());
- // QString strname = ep->v8engine.toString(name);
+ // QString strname = ep->v8engine()->toString(name);
local = QDeclarativePropertyCache::create(obj->metaObject(), strname);
if (local.isValid())
rv = &local;
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 621463dad9..cdbd49388f 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -60,7 +60,6 @@
#include "private/qhashedstring_p.h"
#include <QtCore/qvector.h>
-#include <QtScript/private/qscriptdeclarativeclass_p.h>
QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
@@ -96,7 +95,7 @@ public:
IsEnumType = 0x00000100, // Property type is an enum
IsQList = 0x00000200, // Property type is a QML list
IsQmlBinding = 0x00000400, // Property type is a QDeclarativeBinding*
- IsQScriptValue = 0x00000800, // Property type is a QScriptValue
+ IsQJSValue = 0x00000800, // Property type is a QScriptValue
IsV8Handle = 0x00001000, // Property type is a QDeclarativeV8Handle
// Apply only to IsFunctions
@@ -127,7 +126,7 @@ public:
bool isEnum() const { return flags & IsEnumType; }
bool isQList() const { return flags & IsQList; }
bool isQmlBinding() const { return flags & IsQmlBinding; }
- bool isQScriptValue() const { return flags & IsQScriptValue; }
+ bool isQJSValue() const { return flags & IsQJSValue; }
bool isV8Handle() const { return flags & IsV8Handle; }
bool isVMEFunction() const { return flags & IsVMEFunction; }
bool hasArguments() const { return flags & HasArguments; }
diff --git a/src/declarative/qml/qdeclarativesqldatabase_p.h b/src/declarative/qml/qdeclarativesqldatabase_p.h
index 337f717b1e..ef88b2e4f5 100644
--- a/src/declarative/qml/qdeclarativesqldatabase_p.h
+++ b/src/declarative/qml/qdeclarativesqldatabase_p.h
@@ -42,7 +42,7 @@
#ifndef QDECLARATIVESQLDATABASE_P_H
#define QDECLARATIVESQLDATABASE_P_H
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
//
// W A R N I N G
// -------------
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index cb3e8aef3e..97c5b38c20 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -1230,7 +1230,7 @@ void QDeclarativeScriptBlob::done()
m_scriptData->pragmas = m_pragmas;
// XXX TODO: Handle errors that occur duing the script compile
- QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ QV8Engine *v8engine = QDeclarativeEnginePrivate::get(engine)->v8engine();
v8::HandleScope handle_scope;
v8::Context::Scope scope(v8engine->context());
v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_source, finalUrl().toString(), 1);
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 20e16750cf..1ca6f8c9c2 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -55,8 +55,7 @@
#include <QtCore/qobject.h>
#include <QtNetwork/qnetworkreply.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptprogram.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtDeclarative/qdeclarativeerror.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <private/qdeclarativecleanup_p.h>
diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h
index abf18ce384..e89747b15a 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -57,8 +57,6 @@
#include "private/qdeclarativecleanup_p.h"
#include "private/qdeclarativemetatype_p.h"
-#include <private/qscriptdeclarativeclass_p.h>
-
#include <private/qhashedstring_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 3b7abe6028..45e4745c1a 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -74,7 +74,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
QT_BEGIN_NAMESPACE
@@ -1025,7 +1025,7 @@ v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentC
return qPersistentNew<v8::Object>(script->m_value);
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
- QV8Engine *v8engine = &ep->v8engine;
+ QV8Engine *v8engine = ep->v8engine();
bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h
index 5312e7e128..d0c98d448e 100644
--- a/src/declarative/qml/qdeclarativevme_p.h
+++ b/src/declarative/qml/qdeclarativevme_p.h
@@ -64,7 +64,7 @@
QT_BEGIN_NAMESPACE
class QObject;
-class QScriptValue;
+class QJSValue;
class QDeclarativeScriptData;
class QDeclarativeCompiledData;
class QDeclarativeCompiledData;
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 247c1aa533..746c9f650b 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -48,7 +48,7 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativebinding_p.h"
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QJSValue);
QT_BEGIN_NAMESPACE
@@ -73,7 +73,7 @@ public:
inline const QTime &asQTime();
inline const QDate &asQDate();
inline const QDateTime &asQDateTime();
- inline const QScriptValue &asQScriptValue();
+ inline const QJSValue &asQJSValue();
inline void setValue(QObject *);
inline void setValue(const QVariant &);
@@ -86,7 +86,7 @@ public:
inline void setValue(const QTime &);
inline void setValue(const QDate &);
inline void setValue(const QDateTime &);
- inline void setValue(const QScriptValue &);
+ inline void setValue(const QJSValue &);
private:
int type;
void *data[4]; // Large enough to hold all types
@@ -135,8 +135,8 @@ void QDeclarativeVMEVariant::cleanup()
} else if (type == qMetaTypeId<QVariant>()) {
((QVariant *)dataPtr())->~QVariant();
type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QScriptValue>()) {
- ((QScriptValue *)dataPtr())->~QScriptValue();
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ ((QJSValue *)dataPtr())->~QJSValue();
type = QVariant::Invalid;
}
@@ -245,12 +245,12 @@ const QDateTime &QDeclarativeVMEVariant::asQDateTime()
return *(QDateTime *)(dataPtr());
}
-const QScriptValue &QDeclarativeVMEVariant::asQScriptValue()
+const QJSValue &QDeclarativeVMEVariant::asQJSValue()
{
- if (type != qMetaTypeId<QScriptValue>())
- setValue(QScriptValue());
+ if (type != qMetaTypeId<QJSValue>())
+ setValue(QJSValue());
- return *(QScriptValue *)(dataPtr());
+ return *(QJSValue *)(dataPtr());
}
void QDeclarativeVMEVariant::setValue(QObject *v)
@@ -367,14 +367,14 @@ void QDeclarativeVMEVariant::setValue(const QDateTime &v)
}
}
-void QDeclarativeVMEVariant::setValue(const QScriptValue &v)
+void QDeclarativeVMEVariant::setValue(const QJSValue &v)
{
- if (type != qMetaTypeId<QScriptValue>()) {
+ if (type != qMetaTypeId<QJSValue>()) {
cleanup();
- type = qMetaTypeId<QScriptValue>();
- new (dataPtr()) QScriptValue(v);
+ type = qMetaTypeId<QJSValue>();
+ new (dataPtr()) QJSValue(v);
} else {
- *(QScriptValue *)(dataPtr()) = v;
+ *(QJSValue *)(dataPtr()) = v;
}
}
@@ -656,18 +656,18 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
v8::HandleScope handle_scope;
- v8::Context::Scope scope(ep->v8engine.context());
+ v8::Context::Scope scope(ep->v8engine()->context());
v8::Handle<v8::Value> *args = 0;
if (data->parameterCount) {
args = new v8::Handle<v8::Value>[data->parameterCount];
for (int ii = 0; ii < data->parameterCount; ++ii)
- args[ii] = ep->v8engine.fromVariant(*(QVariant *)a[ii + 1]);
+ args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
}
v8::TryCatch try_catch;
- v8::Local<v8::Value> result = function->Call(ep->v8engine.global(), data->parameterCount, args);
+ v8::Local<v8::Value> result = function->Call(ep->v8engine()->global(), data->parameterCount, args);
QVariant rv;
if (try_catch.HasCaught()) {
@@ -677,7 +677,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
} else {
- if (a[0]) *(QVariant *)a[0] = ep->v8engine.toVariant(result, 0);
+ if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
@@ -720,7 +720,7 @@ v8::Handle<v8::Function> QDeclarativeVMEMetaObject::method(int index)
QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
{
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
- return data[id].asQScriptValue();
+ return data[id].asQJSValue();
else if (data[id].dataType() == QMetaType::QObjectStar)
return QDeclarativeEnginePrivate::get(ctxt->engine)->objectClass->newQObject(data[id].asQObject());
else
@@ -732,7 +732,7 @@ QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
{
#if 0
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
- return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue());
+ return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQJSValue());
else
#endif
if (data[id].dataType() == QMetaType::QObjectStar)
diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp
index b519573ccf..fc9bb887e8 100644
--- a/src/declarative/qml/qdeclarativeworkerscript.cpp
+++ b/src/declarative/qml/qdeclarativeworkerscript.cpp
@@ -48,10 +48,9 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
-#include <QtScript/qscriptvalueiterator.h>
#include <QtCore/qfile.h>
#include <QtCore/qdatetime.h>
#include <QtNetwork/qnetworkaccessmanager.h>
@@ -190,7 +189,7 @@ private:
};
QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QDeclarativeWorkerScriptEnginePrivate *parent)
-: p(parent), accessManager(0)
+: QV8Engine(0), p(parent), accessManager(0)
{
}
@@ -203,8 +202,7 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init()
{
- QV8Engine::init(0);
-
+ initDeclarativeGlobalObject();
#define CALL_ONMESSAGE_SCRIPT \
"(function(object, message) { "\
"var isfunction = false; "\
@@ -705,7 +703,7 @@ bool QDeclarativeWorkerScript::event(QEvent *event)
QDeclarativeEngine *engine = qmlEngine(this);
if (engine) {
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
- QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ QV8Engine *v8engine = QDeclarativeEnginePrivate::get(engine)->v8engine();
v8::HandleScope handle_scope;
v8::Context::Scope scope(v8engine->context());
v8::Handle<v8::Value> value = QV8Worker::deserialize(workerEvent->data(), v8engine);
diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h
index 85910b16e9..d953b0ff18 100644
--- a/src/declarative/qml/qdeclarativeworkerscript_p.h
+++ b/src/declarative/qml/qdeclarativeworkerscript_p.h
@@ -57,7 +57,7 @@
#include "qdeclarativeparserstatus.h"
#include <QtCore/qthread.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtCore/qurl.h>
QT_BEGIN_HEADER
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index 194a60f2d3..abcc283610 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -51,9 +51,8 @@
#include "qdeclarativeglobal_p.h"
#include <QtCore/qobject.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsvalue.h>
+#include <QtDeclarative/qjsengine.h>
#include <QtNetwork/qnetworkreply.h>
#include <QtCore/qtextcodec.h>
#include <QtCore/qxmlstream.h>
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest_p.h b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
index a2082db59f..c5c53a6ce1 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest_p.h
+++ b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
@@ -42,7 +42,7 @@
#ifndef QDECLARATIVEXMLHTTPREQUEST_P_H
#define QDECLARATIVEXMLHTTPREQUEST_P_H
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
//
// W A R N I N G
// -------------
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 29c9ce05c5..d93d930034 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -217,7 +217,6 @@ public:
typedef QDeclarativeNotifierEndpoint Subscription;
Subscription *subscriptions;
- QScriptDeclarativeClass::PersistentIdentifier *identifiers;
void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);
@@ -240,20 +239,19 @@ public:
inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
inline void subscribe(QObject *o, int notifyIndex, int subIndex);
- inline static qint32 toInt32(qsreal n);
- static const qsreal D32;
- static quint32 toUint32(qsreal n);
+ inline static qint32 toInt32(qreal n);
+ static const qreal D32;
+ static quint32 toUint32(qreal n);
};
QDeclarativeV4BindingsPrivate::QDeclarativeV4BindingsPrivate()
-: subscriptions(0), identifiers(0), program(0), bindings(0)
+: subscriptions(0), program(0), bindings(0)
{
}
QDeclarativeV4BindingsPrivate::~QDeclarativeV4BindingsPrivate()
{
delete [] subscriptions; subscriptions = 0;
- delete [] identifiers; identifiers = 0;
}
int QDeclarativeV4BindingsPrivate::methodCount = -1;
@@ -508,8 +506,6 @@ void QDeclarativeV4BindingsPrivate::init()
{
if (program->subscriptions)
subscriptions = new QDeclarativeV4BindingsPrivate::Subscription[program->subscriptions];
- if (program->identifiers)
- identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers];
bindings = new QDeclarativeV4BindingsPrivate::Binding[program->bindings];
}
@@ -679,15 +675,15 @@ static void throwException(int id, QDeclarativeDelayedError *error,
QDeclarativeEnginePrivate::warning(context->engine, error->error);
}
-const qsreal QDeclarativeV4BindingsPrivate::D32 = 4294967296.0;
+const qreal QDeclarativeV4BindingsPrivate::D32 = 4294967296.0;
-qint32 QDeclarativeV4BindingsPrivate::toInt32(qsreal n)
+qint32 QDeclarativeV4BindingsPrivate::toInt32(qreal n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qsreal abs_n = fabs(n);
+ qreal abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
const double D31 = D32 / 2.0;
@@ -701,13 +697,13 @@ qint32 QDeclarativeV4BindingsPrivate::toInt32(qsreal n)
return qint32 (n);
}
-inline quint32 QDeclarativeV4BindingsPrivate::toUint32(qsreal n)
+inline quint32 QDeclarativeV4BindingsPrivate::toUint32(qreal n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qsreal abs_n = fabs(n);
+ qreal abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
@@ -1015,7 +1011,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
} else {
// Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
// Ideally we should just call the methods in the QScript namespace directly.
- QScriptValue tmp(*src.getstringptr());
+ QJSValue tmp(*src.getstringptr());
if (instr->unaryop.src == instr->unaryop.output) {
output.cleanupString();
MARK_CLEAN_REGISTER(instr->unaryop.output);
@@ -1035,7 +1031,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
} else {
// Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
// Ideally we should just call the methods in the QScript namespace directly.
- QScriptValue tmp(*src.getstringptr());
+ QJSValue tmp(*src.getstringptr());
if (instr->unaryop.src == instr->unaryop.output) {
output.cleanupString();
MARK_CLEAN_REGISTER(instr->unaryop.output);
@@ -1055,7 +1051,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
} else {
// Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
// Ideally we should just call the methods in the QScript namespace directly.
- QScriptValue tmp(*src.getstringptr());
+ QJSValue tmp(*src.getstringptr());
if (instr->unaryop.src == instr->unaryop.output) {
output.cleanupString();
MARK_CLEAN_REGISTER(instr->unaryop.output);
@@ -1103,7 +1099,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
{
- static const qsreal qmlPI = 2.0 * qAsin(1.0);
+ static const qreal qmlPI = 2.0 * qAsin(1.0);
Register &output = registers[instr->unaryop.output];
output.setqreal(qmlPI);
}
@@ -1480,16 +1476,16 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
executedBlocks |= instr->blockop.block;
QML_V4_END_INSTR(Block, blockop)
+ // XXX not applicable in v8
QML_V4_BEGIN_INSTR(InitString, initstring)
- if (!identifiers[instr->initstring.offset].identifier) {
- quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
- QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
+// if (!identifiers[instr->initstring.offset].identifier) {
+// quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
+// QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
- QString str = QString::fromRawData(strdata, len);
+// QString str = QString::fromRawData(strdata, len);
- // XXX not applicable in v8
- // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
- }
+// // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
+// }
QML_V4_END_INSTR(InitString, initstring)
QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
index 34a59caf1a..bddfca18b4 100644
--- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
@@ -436,7 +436,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
_expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
- } else if(m_engine->v8engine.illegalNames().contains(name) ) {
+ } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
return false;
} else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) {
diff --git a/src/declarative/qml/v8/qjsconverter_p.h b/src/declarative/qml/v8/qjsconverter_p.h
new file mode 100644
index 0000000000..4aec472c7a
--- /dev/null
+++ b/src/declarative/qml/v8/qjsconverter_p.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** 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 QJSCONVERTER_P_H
+#define QJSCONVERTER_P_H
+
+#include "qjsvalue.h"
+#include <QtCore/qglobal.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qregexp.h>
+#include <QtCore/qdatetime.h>
+
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+/*
+ \internal
+ \class QJSConverter
+ QJSValue and QJSEngine helper class. This class's responsibility is to convert values
+ between JS values and Qt/C++ values.
+
+ This is a nice way to inline these functions in both QJSValue and QJSEngine.
+*/
+class QJSConverter {
+public:
+ static quint32 toArrayIndex(const QString& string)
+ {
+ // FIXME this function should be exported by JSC C API.
+ bool ok;
+ quint32 idx = string.toUInt(&ok);
+ if (!ok || toString(idx) != string)
+ idx = 0xffffffff;
+
+ return idx;
+ }
+
+ static QString toString(v8::Handle<v8::String> jsString)
+ {
+ if (jsString.IsEmpty())
+ return QString();
+ QString qstr;
+ qstr.resize(jsString->Length());
+ jsString->Write(reinterpret_cast<uint16_t*>(qstr.data()));
+ return qstr;
+ }
+
+ static v8::Handle<v8::String> toString(const QString& string)
+ {
+ return v8::String::New(reinterpret_cast<const uint16_t*>(string.data()), string.size());
+ }
+
+ static QString toString(double value)
+ {
+ // FIXME this should be easier. The ideal fix is to create
+ // a new function in V8 API which could cover the functionality.
+
+ if (qIsNaN(value))
+ return QString::fromLatin1("NaN");
+ if (qIsInf(value))
+ return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity");
+ if (!value)
+ return QString::fromLatin1("0");
+
+ QVarLengthArray<char, 25> buf;
+ int decpt;
+ int sign;
+ char* result = 0;
+ char* endresult;
+ (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result);
+
+ if (!result)
+ return QString();
+
+ int resultLen = endresult - result;
+ if (decpt <= 0 && decpt > -6) {
+ buf.resize(-decpt + 2 + sign);
+ qMemSet(buf.data(), '0', -decpt + 2 + sign);
+ if (sign) // fix the sign.
+ buf[0] = '-';
+ buf[sign + 1] = '.';
+ buf.append(result, resultLen);
+ } else {
+ if (sign)
+ buf.append('-');
+ int length = buf.size() - sign + resultLen;
+ if (decpt <= 21 && decpt > 0) {
+ if (length <= decpt) {
+ const char* zeros = "0000000000000000000000000";
+ buf.append(result, resultLen);
+ buf.append(zeros, decpt - length);
+ } else {
+ buf.append(result, decpt);
+ buf.append('.');
+ buf.append(result + decpt, resultLen - decpt);
+ }
+ } else if (result[0] >= '0' && result[0] <= '9') {
+ if (length > 1) {
+ buf.append(result, 1);
+ buf.append('.');
+ buf.append(result + 1, resultLen - 1);
+ } else
+ buf.append(result, resultLen);
+ buf.append('e');
+ buf.append(decpt >= 0 ? '+' : '-');
+ int e = qAbs(decpt - 1);
+ if (e >= 100)
+ buf.append('0' + e / 100);
+ if (e >= 10)
+ buf.append('0' + (e % 100) / 10);
+ buf.append('0' + e % 10);
+ }
+ }
+ free(result);
+ buf.append(0);
+ return QString::fromLatin1(buf.constData());
+ }
+
+ enum {
+ PropertyAttributeMask = v8::ReadOnly | v8::DontDelete | v8::DontEnum,
+ };
+
+ // return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter
+ static uint toPropertyAttributes(const QFlags<QJSValue::PropertyFlag>& flags)
+ {
+ uint attr = 0;
+ if (flags.testFlag(QJSValue::ReadOnly))
+ attr |= v8::ReadOnly;
+ if (flags.testFlag(QJSValue::Undeletable))
+ attr |= v8::DontDelete;
+ if (flags.testFlag(QJSValue::SkipInEnumeration))
+ attr |= v8::DontEnum;
+// if (flags.testFlag(QScriptValue::PropertyGetter))
+// attr |= QScriptValue::PropertyGetter;
+// if (flags.testFlag(QScriptValue::PropertySetter))
+// attr |= QScriptValue::PropertySetter;
+ return attr;
+ }
+
+ // Converts a JS RegExp to a QRegExp.
+ // The conversion is not 100% exact since ECMA regexp and QRegExp
+ // have different semantics/flags, but we try to do our best.
+ static QRegExp toRegExp(v8::Handle<v8::RegExp> jsRegExp)
+ {
+ QString pattern = QJSConverter::toString(jsRegExp->GetSource());
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
+ if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase)
+ caseSensitivity = Qt::CaseInsensitive;
+ return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2);
+ }
+
+ // Converts a QRegExp to a JS RegExp.
+ // The conversion is not 100% exact since ECMA regexp and QRegExp
+ // have different semantics/flags, but we try to do our best.
+ static v8::Handle<v8::RegExp> toRegExp(const QRegExp &re)
+ {
+ // Convert the pattern to a ECMAScript pattern.
+ QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax());
+ if (re.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;
+ }
+
+ int flags = v8::RegExp::kNone;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ flags |= v8::RegExp::kIgnoreCase;
+
+ return v8::RegExp::New(QJSConverter::toString(pattern), static_cast<v8::RegExp::Flags>(flags));
+ }
+
+ // Converts a QStringList to JS.
+ // The result is a new Array object with length equal to the length
+ // of the QStringList, and the elements being the QStringList's
+ // elements converted to JS Strings.
+ static v8::Handle<v8::Array> toStringList(const QStringList &lst)
+ {
+ v8::Handle<v8::Array> result = v8::Array::New(lst.size());
+ for (int i = 0; i < lst.size(); ++i)
+ result->Set(i, toString(lst.at(i)));
+ return result;
+ }
+
+ // Converts a JS Array object to a QStringList.
+ // The result is a QStringList with length equal to the length
+ // of the JS Array, and elements being the JS Array's elements
+ // converted to QStrings.
+ static QStringList toStringList(v8::Handle<v8::Array> jsArray)
+ {
+ QStringList result;
+ uint32_t length = jsArray->Length();
+ for (uint32_t i = 0; i < length; ++i)
+ result.append(toString(jsArray->Get(i)->ToString()));
+ return result;
+ }
+
+
+ // Converts a JS Date to a QDateTime.
+ static QDateTime toDateTime(v8::Handle<v8::Date> jsDate)
+ {
+ return QDateTime::fromMSecsSinceEpoch(jsDate->NumberValue());
+ }
+
+ // Converts a QDateTime to a JS Date.
+ static v8::Handle<v8::Value> toDateTime(const QDateTime &dt)
+ {
+ double date;
+ if (!dt.isValid())
+ date = qSNaN();
+ else
+ date = dt.toMSecsSinceEpoch();
+ return v8::Date::New(date);
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/v8/qjsengine.cpp b/src/declarative/qml/v8/qjsengine.cpp
new file mode 100644
index 0000000000..e80fcb4e7e
--- /dev/null
+++ b/src/declarative/qml/v8/qjsengine.cpp
@@ -0,0 +1,431 @@
+/****************************************************************************
+**
+** 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 "qjsengine.h"
+#include "qjsvalue.h"
+#include "qjsvalue_p.h"
+#include "qscriptisolate_p.h"
+#include "qscript_impl_p.h"
+#include "qv8engine_p.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdatetime.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qpluginloader.h>
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+
+#undef Q_D
+#undef Q_Q
+#define Q_D(blah)
+#define Q_Q(blah)
+
+Q_DECLARE_METATYPE(QJSValue)
+Q_DECLARE_METATYPE(QObjectList)
+Q_DECLARE_METATYPE(QList<int>)
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ Constructs a QJSEngine object.
+
+ The globalObject() is initialized to have properties as described in
+ \l{ECMA-262}, Section 15.1.
+*/
+QJSEngine::QJSEngine()
+ : d(new QV8Engine(this))
+{
+}
+
+/*!
+ \internal
+*/
+QJSEngine::QJSEngine(QJSEngine::ContextOwnership ownership)
+ : d(new QV8Engine(this, ownership))
+{
+}
+
+/*!
+ Constructs a QJSEngine object with the given \a parent.
+
+ The globalObject() is initialized to have properties as described in
+ \l{ECMA-262}, Section 15.1.
+*/
+
+QJSEngine::QJSEngine(QObject *parent)
+ : QObject(parent)
+ , d(new QV8Engine(this))
+{
+}
+
+QJSEngine::QJSEngine(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+ , d(new QV8Engine(this))
+{
+}
+
+/*!
+ Destroys this QJSEngine.
+*/
+QJSEngine::~QJSEngine()
+{
+ delete d;
+}
+
+/*!
+ 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(),
+ uncaughtExceptionBacktrace()
+*/
+bool QJSEngine::hasUncaughtException() const
+{
+ Q_D(const QJSEngine);
+ QScriptIsolate api(d);
+ return d->hasUncaughtException();
+}
+
+/*!
+ Returns the current uncaught exception, or an invalid QJSValue
+ 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(),
+ uncaughtExceptionBacktrace()
+*/
+QJSValue QJSEngine::uncaughtException() const
+{
+ Q_D(const QJSEngine);
+ QScriptIsolate api(d);
+ return d->scriptValueFromInternal(d->uncaughtException());
+}
+
+/*!
+ Clears any uncaught exceptions in this engine.
+
+ \sa hasUncaughtException()
+*/
+void QJSEngine::clearExceptions()
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d);
+ d->clearExceptions();
+}
+
+
+/*!
+ 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 QJSEngine 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 QJSEngine::collectGarbage()
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d);
+ d->collectGarbage();
+}
+
+/*!
+ 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.
+*/
+QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber));
+}
+
+QJSValue QJSEngine::nullValue()
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Null()));
+}
+
+QJSValue QJSEngine::undefinedValue()
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Undefined()));
+}
+
+QJSValue QJSEngine::newObject()
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
+}
+
+QJSValue QJSEngine::newArray(uint length)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(d->newArray(length));
+}
+
+/*!
+ 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 QJSValue. 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 QJSValue::toQObject(), reportAdditionalMemoryCost()
+*/
+QJSValue QJSEngine::newQObject(QObject *object)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(d->newQObject(object));
+}
+
+/*!
+ 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(), QJSValue::toVariant(), reportAdditionalMemoryCost()
+*/
+QJSValue QJSEngine::newVariant(const QVariant &value)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(d->newVariant(value));
+}
+
+
+QJSValue QJSEngine::globalObject() const
+{
+ Q_D(const QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(d->global());
+}
+
+QJSValue QJSEngine::toObject(const QJSValue& value)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(QJSValuePrivate::get(value)->toObject(d));
+}
+
+/*!
+ Creates a QtScript object of class Date from the given \a value.
+
+ \sa QJSValue::toDateTime()
+*/
+QJSValue QJSEngine::newDate(const QDateTime &dt)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(v8::Handle<v8::Value>(QJSConverter::toDateTime(dt)));
+}
+
+/*!
+ Creates a QtScript object of class Date with the given
+ \a value (the number of milliseconds since 01 January 1970,
+ UTC).
+*/
+QJSValue QJSEngine::newDate(double date)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(v8::Handle<v8::Value>(v8::Date::New(date)));
+}
+
+/*!
+ Creates a QtScript object of class RegExp with the given
+ \a regexp.
+
+ \sa QJSValue::toRegExp()
+*/
+QJSValue QJSEngine::newRegExp(const QRegExp &regexp)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(d->newRegExp(regexp));
+}
+
+/*!
+ 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).
+*/
+QJSValue QJSEngine::newRegExp(const QString &pattern, const QString &flags)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return QJSValuePrivate::get(d->newRegExp(pattern, flags));
+}
+
+/*!
+ * \internal
+ * used by QJSEngine::toScriptValue
+ */
+QJSValue QJSEngine::create(int type, const void *ptr)
+{
+ Q_D(QJSEngine);
+ QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr));
+}
+
+/*!
+ \internal
+ \since 4.5
+ convert \a value to \a type, store the result in \a ptr
+*/
+bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
+{
+ QJSValuePrivate *vp = QJSValuePrivate::get(value);
+ QV8Engine *engine = vp->engine();
+ if (engine) {
+ QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
+ v8::HandleScope handleScope;
+ return engine->metaTypeFromJS(*vp, type, ptr);
+ } else {
+ switch (type) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(ptr) = vp->toBool();
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = vp->toInt32();
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = vp->toUInt32();
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger();
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger();
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(ptr) = vp->toNumber();
+ return true;
+ case QMetaType::QString:
+ *reinterpret_cast<QString*>(ptr) = vp->toString();
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(ptr) = vp->toNumber();
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(ptr) = vp->toInt32();
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16();
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = vp->toInt32();
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16();
+ return true;
+ case QMetaType::QChar:
+ *reinterpret_cast<QChar*>(ptr) = vp->toUInt16();
+ return true;
+ default:
+ return false;
+ }
+ }
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qjsengine.cpp"
diff --git a/src/declarative/qml/v8/qjsengine.h b/src/declarative/qml/v8/qjsengine.h
new file mode 100644
index 0000000000..5109cefcf4
--- /dev/null
+++ b/src/declarative/qml/v8/qjsengine.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 QJSENGINE_H
+#define QJSENGINE_H
+
+#include <QtCore/qmetatype.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qobject.h>
+#include <QtDeclarative/qjsvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QDateTime;
+class QV8Engine;
+
+class QRegExp;
+
+template <typename T>
+inline T qjsvalue_cast(const QJSValue &);
+
+class Q_SCRIPT_EXPORT QJSEngine
+ : public QObject
+{
+ Q_OBJECT
+public:
+ enum ContextOwnership {
+ AdoptCurrentContext,
+ CreateNewContext
+ };
+
+ QJSEngine();
+ explicit QJSEngine(ContextOwnership ownership);
+ explicit QJSEngine(QObject *parent);
+ virtual ~QJSEngine();
+
+ QJSValue globalObject() const;
+
+ QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+
+ bool hasUncaughtException() const;
+ QJSValue uncaughtException() const;
+ void clearExceptions();
+
+ QJSValue nullValue();
+ QJSValue undefinedValue();
+
+ QJSValue newVariant(const QVariant &value);
+
+ QJSValue newRegExp(const QRegExp &regexp);
+
+ QJSValue newObject();
+ QJSValue newArray(uint length = 0);
+ QJSValue newRegExp(const QString &pattern, const QString &flags);
+ QJSValue newDate(double value);
+ QJSValue newDate(const QDateTime &value);
+
+ QJSValue newQObject(QObject *object);
+
+ template <typename T>
+ inline QJSValue toScriptValue(const T &value)
+ {
+ return create(qMetaTypeId<T>(), &value);
+ }
+ template <typename T>
+ inline T fromScriptValue(const QJSValue &value)
+ {
+ return qjsvalue_cast<T>(value);
+ }
+
+ void collectGarbage();
+
+ QJSValue toObject(const QJSValue &value);
+
+ QV8Engine *handle() const { return d; }
+
+Q_SIGNALS:
+ void signalHandlerException(const QJSValue &exception);
+
+private:
+ QJSValue create(int type, const void *ptr);
+
+ static bool convertV2(const QJSValue &value, int type, void *ptr);
+
+ friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *);
+
+protected:
+ QJSEngine(QObjectPrivate &dd, QObject *parent = 0);
+
+private:
+ QV8Engine *d;
+ Q_DISABLE_COPY(QJSEngine)
+ friend class QV8Engine;
+};
+
+inline bool qjsvalue_cast_helper(const QJSValue &value, int type, void *ptr)
+{
+ return QJSEngine::convertV2(value, type, ptr);
+}
+
+template<typename T>
+T qjsvalue_cast(const QJSValue &value)
+{
+ T t;
+ const int id = qMetaTypeId<T>();
+
+ if (qjsvalue_cast_helper(value, id, &t))
+ return t;
+ else if (value.isVariant())
+ return qvariant_cast<T>(value.toVariant());
+
+ return T();
+}
+
+template <>
+inline QVariant qjsvalue_cast<QVariant>(const QJSValue &value)
+{
+ return value.toVariant();
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSENGINE_H
diff --git a/src/declarative/qml/v8/qjsvalue.cpp b/src/declarative/qml/v8/qjsvalue.cpp
new file mode 100644
index 0000000000..eff7b4321a
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalue.cpp
@@ -0,0 +1,1024 @@
+/****************************************************************************
+**
+** 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 "qscriptisolate_p.h"
+#include "qjsengine.h"
+#include "qv8engine_p.h"
+#include "qjsvalue.h"
+#include "qjsvalue_p.h"
+#include "qscript_impl_p.h"
+#include "qscriptshareddata_p.h"
+#include <QtCore/qregexp.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs an invalid value.
+*/
+QJSValue::QJSValue()
+ : d_ptr(InvalidValue())
+{
+}
+
+/*!
+ Constructs a new QJSValue with a boolean \a value.
+*/
+QJSValue::QJSValue(bool value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ \enum QJSValue::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.
+*/
+
+/*!
+ Constructs a new QJSValue with a number \a value.
+*/
+QJSValue::QJSValue(int value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ Constructs a new QJSValue with a number \a value.
+*/
+QJSValue::QJSValue(uint value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ Constructs a new QJSValue with a number \a value.
+*/
+QJSValue::QJSValue(double value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ Constructs a new QJSValue with a string \a value.
+*/
+QJSValue::QJSValue(const QString& value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ Constructs a new QJSValue with a special \a value.
+*/
+QJSValue::QJSValue(SpecialValue value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ Constructs a new QJSValue with a string \a value.
+*/
+QJSValue::QJSValue(const QLatin1String &value)
+ : d_ptr(new QJSValuePrivate(value))
+{
+}
+
+/*!
+ \fn QJSValue::QJSValue(const QLatin1String &value)
+
+ Constructs a new QJSValue with a string \a value.
+*/
+#ifndef QT_NO_CAST_FROM_ASCII
+QJSValue::QJSValue(const char *value)
+ : d_ptr(new QJSValuePrivate(QString::fromAscii(value)))
+{
+}
+#endif
+
+/*!
+ Block automatic convertion to bool
+ \internal
+*/
+QJSValue::QJSValue(void* d)
+{
+ Q_UNUSED(d);
+ Q_ASSERT(false);
+}
+
+/*!
+ Constructs a new QJSValue from private
+ \internal
+*/
+QJSValue::QJSValue(QJSValuePrivate* d)
+ : d_ptr(d)
+{
+}
+
+/*!
+ Constructs a new QJSValue from private
+ \internal
+*/
+QJSValue::QJSValue(QScriptPassPointer<QJSValuePrivate> d)
+ : d_ptr(d.give())
+{
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the boolean \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, bool value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the integer \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, int value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the unsigned integer \a value and
+ registers it with the script \a engine.
+ */
+QJSValue::QJSValue(QJSEngine* engine, uint value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the double \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, double value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the string \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, const QString& value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the string \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, const char* value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), QString::fromUtf8(value));
+ } else {
+ d_ptr = new QJSValuePrivate(QString::fromUtf8(value));
+ }
+}
+
+/*!
+ \obsolete
+
+ Constructs a new QJSValue with the special \a value and
+ registers it with the script \a engine.
+*/
+QJSValue::QJSValue(QJSEngine* engine, SpecialValue value)
+{
+ if (engine) {
+ QScriptIsolate api(QV8Engine::get(engine), QScriptIsolate::NotNullEngine);
+ d_ptr = new QJSValuePrivate(QV8Engine::get(engine), value);
+ } else {
+ d_ptr = new QJSValuePrivate(value);
+ }
+}
+
+/*!
+ Constructs a new QJSValue 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).
+*/
+QJSValue::QJSValue(const QJSValue& other)
+ : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+ Destroys this QJSValue.
+*/
+QJSValue::~QJSValue()
+{
+}
+
+/*!
+ Returns true if this QJSValue is valid; otherwise returns
+ false.
+*/
+bool QJSValue::isValid() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isValid();
+}
+
+/*!
+ Returns true if this QJSValue is of the primitive type Boolean;
+ otherwise returns false.
+
+ \sa toBool()
+*/
+bool QJSValue::isBool() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isBool();
+}
+
+/*!
+ \obsolete
+
+ Use isBool() instead.
+ Returns true if this QJSValue is of the primitive type Boolean;
+ otherwise returns false.
+*/
+bool QJSValue::isBoolean() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isBool();
+}
+
+/*!
+ Returns true if this QJSValue is of the primitive type Number;
+ otherwise returns false.
+
+ \sa toNumber()
+*/
+bool QJSValue::isNumber() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isNumber();
+}
+
+/*!
+ Returns true if this QJSValue is of the primitive type Null;
+ otherwise returns false.
+
+ \sa QJSEngine::nullValue()
+*/
+bool QJSValue::isNull() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isNull();
+}
+
+/*!
+ Returns true if this QJSValue is of the primitive type String;
+ otherwise returns false.
+
+ \sa toString()
+*/
+bool QJSValue::isString() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isString();
+}
+
+/*!
+ Returns true if this QJSValue is of the primitive type Undefined;
+ otherwise returns false.
+
+ \sa QJSEngine::undefinedValue()
+*/
+bool QJSValue::isUndefined() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isUndefined();
+}
+
+/*!
+ Returns true if this QJSValue is an object of the Error class;
+ otherwise returns false.
+
+ \sa QScriptContext::throwError()
+*/
+bool QJSValue::isError() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isError();
+}
+
+/*!
+ Returns true if this QJSValue is an object of the Array class;
+ otherwise returns false.
+
+ \sa QJSEngine::newArray()
+*/
+bool QJSValue::isArray() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isArray();
+ }
+
+/*!
+ Returns true if this QJSValue 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(), QJSEngine::newObject()
+*/
+bool QJSValue::isObject() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isObject();
+}
+
+/*!
+ Returns true if this QJSValue is a function; otherwise returns
+ false.
+
+ \sa call()
+*/
+bool QJSValue::isFunction() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isCallable();
+}
+
+/*!
+ Returns true if this QJSValue is a variant value;
+ otherwise returns false.
+
+ \sa toVariant(), QJSEngine::newVariant()
+*/
+bool QJSValue::isVariant() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isVariant();
+}
+
+/*!
+ Returns the string value of this QJSValue, as defined in
+ \l{ECMA-262} section 9.8, "ToString".
+
+ Note that if this QJSValue 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 QJSValue::toString() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toString();
+}
+
+/*!
+ Returns the number value of this QJSValue, as defined in
+ \l{ECMA-262} section 9.3, "ToNumber".
+
+ Note that if this QJSValue 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()
+*/
+double QJSValue::toNumber() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toNumber();
+}
+
+/*!
+ Returns the boolean value of this QJSValue, using the conversion
+ rules described in \l{ECMA-262} section 9.2, "ToBoolean".
+
+ Note that if this QJSValue 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 QJSValue::toBool() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toBool();
+}
+
+/*!
+ \obsolete
+
+ Use toBool() instead.
+*/
+bool QJSValue::toBoolean() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toBool();
+}
+
+/*!
+ Returns the integer value of this QJSValue, using the conversion
+ rules described in \l{ECMA-262} section 9.4, "ToInteger".
+
+ Note that if this QJSValue 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()
+*/
+double QJSValue::toInteger() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toInteger();
+}
+
+/*!
+ Returns the signed 32-bit integer value of this QJSValue, using
+ the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
+
+ Note that if this QJSValue 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 QJSValue::toInt32() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toInt32();
+}
+
+/*!
+ Returns the unsigned 32-bit integer value of this QJSValue, using
+ the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
+
+ Note that if this QJSValue 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 QJSValue::toUInt32() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toUInt32();
+}
+
+/*!
+ Returns the unsigned 16-bit integer value of this QJSValue, using
+ the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16".
+
+ Note that if this QJSValue 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 QJSValue::toUInt16() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toUInt16();
+}
+
+/*!
+ \obsolete
+
+ This function is obsolete; use QJSEngine::toObject() instead.
+*/
+QJSValue QJSValue::toObject() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->toObject());
+}
+
+/*!
+ Returns the QVariant value of this QJSValue, 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 QJSValue::toVariant() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toVariant();
+}
+
+
+/*!
+ Calls this QJSValue 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 QJSValue is not a function, call() does nothing
+ and returns an invalid QJSValue.
+
+ Note that if \a thisObject is not an object, the global object
+ (see \l{QJSEngine::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
+ QJSEngine::hasUncaughtException() to determine if an exception
+ occurred.
+
+ \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
+
+ \sa construct()
+*/
+QJSValue QJSValue::call(const QJSValue& thisObject, const QJSValueList& args)
+{
+ Q_D(QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->call(QJSValuePrivate::get(thisObject), args);
+}
+
+/*!
+ Creates a new \c{Object} and calls this QJSValue 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 QJSValue is not a function, construct() does nothing
+ and returns an invalid QJSValue.
+
+ 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
+ QJSEngine::hasUncaughtException() to determine if an exception
+ occurred.
+
+ \sa call(), QJSEngine::newObject()
+*/
+QJSValue QJSValue::construct(const QJSValueList &args)
+{
+ Q_D(QJSValue);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->construct(args));
+}
+
+/*!
+ Returns the QJSEngine that created this QJSValue,
+ or 0 if this QJSValue is invalid or the value is not
+ associated with a particular engine.
+*/
+QJSEngine* QJSValue::engine() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ QV8Engine* engine = d->engine();
+ if (engine)
+ return QV8Engine::get(engine);
+ return 0;
+}
+
+
+/*!
+ If this QJSValue is an object, returns the internal prototype
+ (\c{__proto__} property) of this object; otherwise returns an
+ invalid QJSValue.
+
+ \sa setPrototype(), isObject()
+*/
+QJSValue QJSValue::prototype() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->prototype());
+}
+
+/*!
+ If this QJSValue 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 QJSValue::setPrototype(const QJSValue& prototype)
+{
+ Q_D(QJSValue);
+ QScriptIsolate api(d->engine());
+ d->setPrototype(QJSValuePrivate::get(prototype));
+}
+
+/*!
+ Assigns the \a other value to this QJSValue.
+
+ 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.
+*/
+QJSValue& QJSValue::operator=(const QJSValue& other)
+{
+ d_ptr = other.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns true if this QJSValue 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 QJSValue
+ 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 QJSValue 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 QJSValue::equals(const QJSValue& other) const
+{
+ Q_D(const QJSValue);
+ QJSValuePrivate* otherValue = QJSValuePrivate::get(other);
+ QScriptIsolate api(d->engine() ? d->engine() : otherValue->engine());
+ return d_ptr->equals(otherValue);
+}
+
+/*!
+ Returns true if this QJSValue 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 QJSValue 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 QJSValue::strictlyEquals(const QJSValue& other) const
+{
+ Q_D(const QJSValue);
+ QJSValuePrivate* o = QJSValuePrivate::get(other);
+ QScriptIsolate api(d->engine() ? d->engine() : o->engine());
+ return d_ptr->strictlyEquals(o);
+}
+
+/*!
+ Returns true if this QJSValue is an instance of
+ \a other; otherwise returns false.
+
+ This QJSValue 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
+ QJSValue.
+*/
+bool QJSValue::instanceOf(const QJSValue &other) const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->instanceOf(QJSValuePrivate::get(other));
+}
+
+/*!
+ Returns the value of this QJSValue's property with the given \a name,
+ using the given \a mode to resolve the property.
+
+ If no such property exists, an invalid QJSValue 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(), QJSValueIterator
+*/
+QJSValue QJSValue::property(const QString& name) const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->property(name));
+}
+
+/*!
+ \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 QJSValue is not an Array object, this function behaves
+ as if property() was called with the string representation of \a
+ arrayIndex.
+*/
+QJSValue QJSValue::property(quint32 arrayIndex) const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->property(arrayIndex));
+}
+
+/*!
+ Sets the value of this QJSValue's property with the given \a name to
+ the given \a value.
+
+ If this QJSValue is not an object, this function does nothing.
+
+ If this QJSValue 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 QJSValue::setProperty(const QString& name, const QJSValue& value)
+{
+ Q_D(QJSValue);
+ QScriptIsolate api(d->engine());
+ d->setProperty(name, QJSValuePrivate::get(value));
+}
+
+/*!
+ \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 QJSValue is not an Array object, this function behaves
+ as if setProperty() was called with the string representation of \a
+ arrayIndex.
+*/
+void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
+{
+ Q_D(QJSValue);
+ QScriptIsolate api(d->engine());
+ d->setProperty(arrayIndex, QJSValuePrivate::get(value));
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QJSValue::PropertyFlags QJSValue::propertyFlags(const QString& name) const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->propertyFlags(name);
+}
+
+/*!
+ * If this QJSValue is a QObject, returns the QObject pointer
+ * that the QJSValue represents; otherwise, returns 0.
+ *
+ * If the QObject that this QJSValue 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 *QJSValue::toQObject() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toQObject();
+}
+
+/*!
+ Returns a QDateTime representation of this value, in local time.
+ If this QJSValue is not a date, or the value of the date is NaN
+ (Not-a-Number), an invalid QDateTime is returned.
+
+ \sa isDate()
+*/
+QDateTime QJSValue::toDateTime() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toDataTime();
+}
+
+/*!
+ Returns the QRegExp representation of this value.
+ If this QJSValue is not a regular expression, an empty
+ QRegExp is returned.
+
+ \sa isRegExp()
+*/
+QRegExp QJSValue::toRegExp() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->toRegExp();
+}
+
+/*!
+ Returns true if this QJSValue is an object of the Date class;
+ otherwise returns false.
+
+ \sa QJSEngine::newDate()
+*/
+bool QJSValue::isDate() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isDate();
+}
+
+/*!
+ Returns true if this QJSValue is an object of the RegExp class;
+ otherwise returns false.
+
+ \sa QJSEngine::newRegExp()
+*/
+bool QJSValue::isRegExp() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isRegExp();
+}
+
+/*!
+ Returns true if this QJSValue is a QObject; otherwise returns
+ false.
+
+ Note: This function returns true even if the QObject that this
+ QJSValue wraps has been deleted.
+
+ \sa toQObject(), QJSEngine::newQObject()
+*/
+bool QJSValue::isQObject() const
+{
+ Q_D(const QJSValue);
+ QScriptIsolate api(d->engine());
+ return d->isQObject();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qjsvalue.h b/src/declarative/qml/v8/qjsvalue.h
new file mode 100644
index 0000000000..07276bc694
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalue.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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 QJSVALUE_H
+#define QJSVALUE_H
+
+#include <QtCore/qstring.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QJSValue;
+class QJSEngine;
+class QVariant;
+class QObject;
+struct QMetaObject;
+class QDateTime;
+class QRegExp;
+
+typedef QList<QJSValue> QJSValueList;
+
+class QJSValuePrivate;
+struct QScriptValuePrivatePointerDeleter;
+template <class T> class QScriptPassPointer;
+
+class Q_SCRIPT_EXPORT QJSValue
+{
+public:
+ enum PropertyFlag {
+ ReadOnly = 0x00000001,
+ Undeletable = 0x00000002,
+ SkipInEnumeration = 0x00000004
+ };
+ Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
+
+ enum SpecialValue {
+ NullValue,
+ UndefinedValue
+ };
+
+public:
+ QJSValue();
+ ~QJSValue();
+ QJSValue(const QJSValue &other);
+ QJSValue(QJSEngine *engine, SpecialValue val);
+ QJSValue(QJSEngine *engine, bool val);
+ QJSValue(QJSEngine *engine, int val);
+ QJSValue(QJSEngine *engine, uint val);
+ QJSValue(QJSEngine *engine, double val);
+ QJSValue(QJSEngine *engine, const QString &val);
+
+ QJSValue(SpecialValue value);
+ QJSValue(bool value);
+ QJSValue(int value);
+ QJSValue(uint value);
+ QJSValue(double value);
+ QJSValue(const QString &value);
+ QJSValue(const QLatin1String &value);
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QJSValue(const char *str);
+#endif
+
+ QJSValue &operator=(const QJSValue &other);
+
+ QJSEngine *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 isObject() const;
+ bool isDate() const;
+ bool isRegExp() const;
+ bool isArray() const;
+ bool isError() const;
+
+ QString toString() const;
+ double toNumber() const;
+ bool toBool() const;
+ bool toBoolean() const;
+ double toInteger() const;
+ qint32 toInt32() const;
+ quint32 toUInt32() const;
+ quint16 toUInt16() const;
+ QVariant toVariant() const;
+ QObject *toQObject() const;
+ QJSValue toObject() const;
+ QDateTime toDateTime() const;
+ QRegExp toRegExp() const;
+
+ bool instanceOf(const QJSValue &other) const;
+
+ bool equals(const QJSValue &other) const;
+ bool strictlyEquals(const QJSValue &other) const;
+
+ QJSValue prototype() const;
+ void setPrototype(const QJSValue &prototype);
+
+ QJSValue property(const QString &name) const;
+ void setProperty(const QString &name, const QJSValue &value);
+
+ QJSValue property(quint32 arrayIndex) const;
+ void setProperty(quint32 arrayIndex, const QJSValue &value);
+
+ QJSValue::PropertyFlags propertyFlags(const QString &name) const;
+
+ QJSValue call(const QJSValue &thisObject = QJSValue(),
+ const QJSValueList &args = QJSValueList());
+ QJSValue construct(const QJSValueList &args = QJSValueList());
+
+private:
+ // force compile error, prevent QJSValue(bool) to be called
+ QJSValue(void *);
+ // force compile error, prevent QJSValue(QScriptEngine*, bool) to be called
+ QJSValue(QJSEngine *, void *);
+ QJSValue(QJSEngine *, const char *);
+
+ QJSValue(QJSValuePrivate*);
+ QJSValue(QScriptPassPointer<QJSValuePrivate>);
+
+private:
+ QExplicitlySharedDataPointer<QJSValuePrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QJSValue)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QJSValue::PropertyFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/v8/qjsvalue_impl_p.h b/src/declarative/qml/v8/qjsvalue_impl_p.h
new file mode 100644
index 0000000000..adff6ce945
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalue_impl_p.h
@@ -0,0 +1,1133 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QJSVALUE_IMPL_P_H
+#define QJSVALUE_IMPL_P_H
+
+#include "qjsconverter_p.h"
+#include "qjsvalue_p.h"
+#include "qv8engine_p.h"
+#include "qscriptisolate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+QJSValuePrivate* QJSValuePrivate::get(const QJSValue& q) { Q_ASSERT(q.d_ptr.data()); return q.d_ptr.data(); }
+
+QJSValue QJSValuePrivate::get(const QJSValuePrivate* d)
+{
+ Q_ASSERT(d);
+ return QJSValue(const_cast<QJSValuePrivate*>(d));
+}
+
+QJSValue QJSValuePrivate::get(QScriptPassPointer<QJSValuePrivate> d)
+{
+ Q_ASSERT(d);
+ return QJSValue(d);
+}
+
+QJSValue QJSValuePrivate::get(QJSValuePrivate* d)
+{
+ Q_ASSERT(d);
+ return QJSValue(d);
+}
+
+QJSValuePrivate::QJSValuePrivate()
+ : m_engine(0), m_state(Invalid)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(bool value)
+ : m_engine(0), m_state(CBool), u(value)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(int value)
+ : m_engine(0), m_state(CNumber), u(value)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(uint value)
+ : m_engine(0), m_state(CNumber), u(value)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(double value)
+ : m_engine(0), m_state(CNumber), u(value)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(const QString& value)
+ : m_engine(0), m_state(CString), u(new QString(value))
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(QJSValue::SpecialValue value)
+ : m_engine(0), m_state(value == QJSValue::NullValue ? CNull : CUndefined)
+{
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, bool value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, int value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, uint value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, double value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, const QString& value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, QJSValue::SpecialValue value)
+ : m_engine(engine), m_state(JSValue)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value> value)
+ : m_engine(engine), m_state(JSValue), m_value(v8::Persistent<v8::Value>::New(value))
+{
+ Q_ASSERT(engine);
+ // It shouldn't happen, v8 shows errors by returning an empty handler. This is important debug
+ // information and it can't be simply ignored.
+ Q_ASSERT(!value.IsEmpty());
+ m_engine->registerValue(this);
+}
+
+QJSValuePrivate::~QJSValuePrivate()
+{
+ if (isJSBased()) {
+ m_engine->unregisterValue(this);
+ QScriptIsolate api(m_engine);
+ m_value.Dispose();
+ } else if (isStringBased()) {
+ delete u.m_string;
+ }
+}
+
+bool QJSValuePrivate::toBool() const
+{
+ switch (m_state) {
+ case JSValue:
+ {
+ v8::HandleScope scope;
+ return m_value->ToBoolean()->Value();
+ }
+ case CNumber:
+ return !(qIsNaN(u.m_number) || !u.m_number);
+ case CBool:
+ return u.m_bool;
+ case Invalid:
+ case CNull:
+ case CUndefined:
+ return false;
+ case CString:
+ return u.m_string->length();
+ }
+
+ Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
+ return false; // Avoid compiler warning.
+}
+
+double QJSValuePrivate::toNumber() const
+{
+ switch (m_state) {
+ case JSValue:
+ {
+ v8::HandleScope scope;
+ return m_value->ToNumber()->Value();
+ }
+ case CNumber:
+ return u.m_number;
+ case CBool:
+ return u.m_bool ? 1 : 0;
+ case CNull:
+ case Invalid:
+ return 0;
+ case CUndefined:
+ return qQNaN();
+ case CString:
+ bool ok;
+ double result = u.m_string->toDouble(&ok);
+ if (ok)
+ return result;
+ result = u.m_string->toInt(&ok, 0); // Try other bases.
+ if (ok)
+ return result;
+ if (*u.m_string == QLatin1String("Infinity"))
+ return qInf();
+ if (*u.m_string == QLatin1String("-Infinity"))
+ return -qInf();
+ return u.m_string->length() ? qQNaN() : 0;
+ }
+
+ Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
+ return 0; // Avoid compiler warning.
+}
+
+QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::toObject(QV8Engine* engine) const
+{
+ Q_ASSERT(engine);
+ if (this->engine() && engine != this->engine()) {
+ qWarning("QJSEngine::toObject: cannot convert value created in a different engine");
+ return InvalidValue();
+ }
+
+ v8::HandleScope scope;
+ switch (m_state) {
+ case Invalid:
+ case CNull:
+ case CUndefined:
+ return new QJSValuePrivate;
+ case CString:
+ return new QJSValuePrivate(engine, engine->makeJSValue(*u.m_string)->ToObject());
+ case CNumber:
+ return new QJSValuePrivate(engine, engine->makeJSValue(u.m_number)->ToObject());
+ case CBool:
+ return new QJSValuePrivate(engine, engine->makeJSValue(u.m_bool)->ToObject());
+ case JSValue:
+ if (m_value->IsObject())
+ return const_cast<QJSValuePrivate*>(this);
+ if (m_value->IsNull() || m_value->IsUndefined()) // avoid "Uncaught TypeError: Cannot convert null to object"
+ return InvalidValue();
+ return new QJSValuePrivate(engine, m_value->ToObject());
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Not all states are included in this switch");
+ return InvalidValue();
+ }
+}
+
+/*!
+ This method is created only for QJSValue::toObject() purpose which is obsolete.
+ \internal
+ */
+QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::toObject() const
+{
+ if (isJSBased())
+ return toObject(engine());
+
+ // Without an engine there is not much we can do.
+ return new QJSValuePrivate;
+}
+
+QString QJSValuePrivate::toString() const
+{
+ switch (m_state) {
+ case Invalid:
+ return QString();
+ case CBool:
+ return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false");
+ case CString:
+ return *u.m_string;
+ case CNumber:
+ return QJSConverter::toString(u.m_number);
+ case CNull:
+ return QString::fromLatin1("null");
+ case CUndefined:
+ return QString::fromLatin1("undefined");
+ case JSValue:
+ Q_ASSERT(!m_value.IsEmpty());
+ v8::HandleScope handleScope;
+ v8::TryCatch tryCatch;
+ v8::Local<v8::String> result = m_value->ToString();
+ if (result.IsEmpty()) {
+ result = tryCatch.Exception()->ToString();
+ m_engine->setException(tryCatch.Exception(), tryCatch.Message());
+ }
+ return QJSConverter::toString(result);
+ }
+
+ Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
+ return QString(); // Avoid compiler warning.
+}
+
+QVariant QJSValuePrivate::toVariant() const
+{
+ switch (m_state) {
+ case Invalid:
+ return QVariant();
+ case CBool:
+ return QVariant(u.m_bool);
+ case CString:
+ return QVariant(*u.m_string);
+ case CNumber:
+ return QVariant(u.m_number);
+ case CNull:
+ return QVariant();
+ case CUndefined:
+ return QVariant();
+ case JSValue:
+ break;
+ }
+
+ Q_ASSERT(m_state == JSValue);
+ Q_ASSERT(!m_value.IsEmpty());
+ Q_ASSERT(m_engine);
+
+ v8::HandleScope handleScope;
+ return m_engine->variantFromJS(m_value);
+}
+
+inline QDateTime QJSValuePrivate::toDataTime() const
+{
+ if (!isDate())
+ return QDateTime();
+
+ v8::HandleScope handleScope;
+ return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(m_value));
+
+}
+
+inline QRegExp QJSValuePrivate::toRegExp() const
+{
+ if (!isRegExp())
+ return QRegExp();
+
+ v8::HandleScope handleScope;
+ return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(m_value));
+}
+
+QObject* QJSValuePrivate::toQObject() const
+{
+ if (!isJSBased())
+ return 0;
+
+ v8::HandleScope handleScope;
+ return engine()->qtObjectFromJS(m_value);
+}
+
+double QJSValuePrivate::toInteger() const
+{
+ double result = toNumber();
+ if (qIsNaN(result))
+ return 0;
+ if (qIsInf(result))
+ return result;
+ return (result > 0) ? qFloor(result) : -1 * qFloor(-result);
+}
+
+qint32 QJSValuePrivate::toInt32() const
+{
+ double result = toInteger();
+ // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
+ // some of these operation are invoked in toInteger subcall.
+ if (qIsInf(result))
+ return 0;
+ return result;
+}
+
+quint32 QJSValuePrivate::toUInt32() const
+{
+ double result = toInteger();
+ // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
+ // some of these operation are invoked in toInteger subcall.
+ if (qIsInf(result))
+ return 0;
+ return result;
+}
+
+quint16 QJSValuePrivate::toUInt16() const
+{
+ return toInt32();
+}
+
+inline bool QJSValuePrivate::isArray() const
+{
+ return isJSBased() && m_value->IsArray();
+}
+
+inline bool QJSValuePrivate::isBool() const
+{
+ return m_state == CBool || (isJSBased() && m_value->IsBoolean());
+}
+
+inline bool QJSValuePrivate::isCallable() const
+{
+ if (isFunction())
+ return true;
+ if (isObject()) {
+ // Our C++ wrappers register function handlers but not always act as callables.
+ return v8::Object::Cast(*m_value)->IsCallable();
+ }
+ return false;
+}
+
+inline bool QJSValuePrivate::isError() const
+{
+ if (!isJSBased())
+ return false;
+ v8::HandleScope handleScope;
+ return m_value->IsError();
+}
+
+inline bool QJSValuePrivate::isFunction() const
+{
+ return isJSBased() && m_value->IsFunction();
+}
+
+inline bool QJSValuePrivate::isNull() const
+{
+ return m_state == CNull || (isJSBased() && m_value->IsNull());
+}
+
+inline bool QJSValuePrivate::isNumber() const
+{
+ return m_state == CNumber || (isJSBased() && m_value->IsNumber());
+}
+
+inline bool QJSValuePrivate::isObject() const
+{
+ return isJSBased() && m_value->IsObject();
+}
+
+inline bool QJSValuePrivate::isString() const
+{
+ return m_state == CString || (isJSBased() && m_value->IsString());
+}
+
+inline bool QJSValuePrivate::isUndefined() const
+{
+ return m_state == CUndefined || (isJSBased() && m_value->IsUndefined());
+}
+
+inline bool QJSValuePrivate::isValid() const
+{
+ return m_state != Invalid;
+}
+
+inline bool QJSValuePrivate::isVariant() const
+{
+ return isJSBased() && m_engine->isVariant(m_value);
+}
+
+bool QJSValuePrivate::isDate() const
+{
+ return (isJSBased() && m_value->IsDate());
+}
+
+bool QJSValuePrivate::isRegExp() const
+{
+ return (isJSBased() && m_value->IsRegExp());
+}
+
+bool QJSValuePrivate::isQObject() const
+{
+ return isJSBased() && engine()->isQObject(m_value);
+}
+
+inline bool QJSValuePrivate::equals(QJSValuePrivate* other)
+{
+ if (!isValid())
+ return !other->isValid();
+
+ if (!other->isValid())
+ return false;
+
+ if (!isJSBased() && !other->isJSBased()) {
+ switch (m_state) {
+ case CNull:
+ case CUndefined:
+ return other->isUndefined() || other->isNull();
+ case CNumber:
+ switch (other->m_state) {
+ case CBool:
+ case CString:
+ return u.m_number == other->toNumber();
+ case CNumber:
+ return u.m_number == other->u.m_number;
+ default:
+ return false;
+ }
+ case CBool:
+ switch (other->m_state) {
+ case CBool:
+ return u.m_bool == other->u.m_bool;
+ case CNumber:
+ return toNumber() == other->u.m_number;
+ case CString:
+ return toNumber() == other->toNumber();
+ default:
+ return false;
+ }
+ case CString:
+ switch (other->m_state) {
+ case CBool:
+ return toNumber() == other->toNumber();
+ case CNumber:
+ return toNumber() == other->u.m_number;
+ case CString:
+ return *u.m_string == *other->u.m_string;
+ default:
+ return false;
+ }
+ default:
+ Q_ASSERT_X(false, "QJSValue::equals", "Not all states are included in the previous switch statement.");
+ }
+ }
+
+ v8::HandleScope handleScope;
+ if (isJSBased() && !other->isJSBased()) {
+ if (!other->assignEngine(engine())) {
+ qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
+ return false;
+ }
+ } else if (!isJSBased() && other->isJSBased()) {
+ if (!assignEngine(other->engine())) {
+ qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
+ return false;
+ }
+ }
+
+ Q_ASSERT(this->engine() && other->engine());
+ if (this->engine() != other->engine()) {
+ qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
+ return false;
+ }
+ return m_value->Equals(other->m_value);
+}
+
+inline bool QJSValuePrivate::strictlyEquals(QJSValuePrivate* other)
+{
+ if (isJSBased()) {
+ // We can't compare these two values without binding to the same engine.
+ if (!other->isJSBased()) {
+ if (other->assignEngine(engine()))
+ return m_value->StrictEquals(other->m_value);
+ return false;
+ }
+ if (other->engine() != engine()) {
+ qWarning("QJSValue::strictlyEquals: cannot compare to a value created in a different engine");
+ return false;
+ }
+ return m_value->StrictEquals(other->m_value);
+ }
+ if (isStringBased()) {
+ if (other->isStringBased())
+ return *u.m_string == *(other->u.m_string);
+ if (other->isJSBased()) {
+ assignEngine(other->engine());
+ return m_value->StrictEquals(other->m_value);
+ }
+ }
+ if (isNumberBased()) {
+ if (other->isJSBased()) {
+ assignEngine(other->engine());
+ return m_value->StrictEquals(other->m_value);
+ }
+ if (m_state != other->m_state)
+ return false;
+ if (m_state == CNumber)
+ return u.m_number == other->u.m_number;
+ Q_ASSERT(m_state == CBool);
+ return u.m_bool == other->u.m_bool;
+ }
+
+ if (!isValid() && !other->isValid())
+ return true;
+
+ return false;
+}
+
+inline bool QJSValuePrivate::lessThan(QJSValuePrivate *other) const
+{
+ if (engine() != other->engine() && engine() && other->engine()) {
+ qWarning("QJSValue::lessThan: cannot compare to a value created in a different engine");
+ return false;
+ }
+
+ if (!isValid() || !other->isValid())
+ return false;
+
+ if (isString() && other->isString())
+ return toString() < other->toString();
+
+ if (isObject() || other->isObject()) {
+ v8::HandleScope handleScope;
+ QV8Engine *eng = m_engine ? engine() : other->engine();
+ // FIXME: lessThan can throw an exception which will be dropped by this code:
+ Q_ASSERT(eng);
+ eng->saveException();
+ QScriptSharedDataPointer<QJSValuePrivate> cmp(eng->evaluate(QString::fromLatin1("(function(a,b){return a<b})")));
+ Q_ASSERT(cmp->isFunction());
+ v8::Handle<v8::Value> args[2];
+ cmp->prepareArgumentsForCall(args, QJSValueList() << QJSValuePrivate::get(this) << QJSValuePrivate::get(other));
+ QScriptSharedDataPointer<QJSValuePrivate> resultValue(cmp->call(0, 2, args));
+ bool result = resultValue->toBool();
+ eng->restoreException();
+ return result;
+ }
+
+ double nthis = toNumber();
+ double nother = other->toNumber();
+ if (qIsNaN(nthis) || qIsNaN(nother)) {
+ // Should return undefined in ECMA standard.
+ return false;
+ }
+ return nthis < nother;
+}
+
+inline bool QJSValuePrivate::instanceOf(QJSValuePrivate* other) const
+{
+ if (!isObject() || !other->isFunction())
+ return false;
+ if (engine() != other->engine()) {
+ qWarning("QJSValue::instanceof: cannot perform operation on a value created in a different engine");
+ return false;
+ }
+ v8::HandleScope handleScope;
+ return instanceOf(v8::Handle<v8::Object>::Cast(other->m_value));
+}
+
+inline bool QJSValuePrivate::instanceOf(v8::Handle<v8::Object> other) const
+{
+ Q_ASSERT(isObject());
+ Q_ASSERT(other->IsFunction());
+
+ v8::Handle<v8::Object> self = v8::Handle<v8::Object>::Cast(m_value);
+ v8::Handle<v8::Value> selfPrototype = self->GetPrototype();
+ v8::Handle<v8::Value> otherPrototype = other->Get(v8::String::New("prototype"));
+
+ while (!selfPrototype->IsNull()) {
+ if (selfPrototype->StrictEquals(otherPrototype))
+ return true;
+ // In general a prototype can be an object or null, but in the loop it can't be null, so
+ // we can cast it safely.
+ selfPrototype = v8::Handle<v8::Object>::Cast(selfPrototype)->GetPrototype();
+ }
+ return false;
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::prototype() const
+{
+ if (isObject()) {
+ v8::HandleScope handleScope;
+ return new QJSValuePrivate(engine(), v8::Handle<v8::Object>::Cast(m_value)->GetPrototype());
+ }
+ return InvalidValue();
+}
+
+inline void QJSValuePrivate::setPrototype(QJSValuePrivate* prototype)
+{
+ if (isObject() && (prototype->isObject() || prototype->isNull())) {
+ if (engine() != prototype->engine()) {
+ if (prototype->engine()) {
+ qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
+ return;
+ }
+ prototype->assignEngine(engine());
+ }
+ v8::HandleScope handleScope;
+ if (!v8::Handle<v8::Object>::Cast(m_value)->SetPrototype(*prototype))
+ qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
+ }
+}
+
+inline void QJSValuePrivate::setProperty(const QString& name, QJSValuePrivate* value, uint attribs)
+{
+ if (!isObject())
+ return;
+ v8::HandleScope handleScope;
+ setProperty(QJSConverter::toString(name), value, attribs);
+}
+
+inline void QJSValuePrivate::setProperty(v8::Handle<v8::String> name, QJSValuePrivate* value, uint attribs)
+{
+ if (!isObject())
+ return;
+
+ if (!value->isJSBased())
+ value->assignEngine(engine());
+
+ if (!value->isValid()) {
+ // Remove the property.
+ v8::HandleScope handleScope;
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::Object> recv(v8::Object::Cast(*m_value));
+// if (attribs & QJSValue::PropertyGetter && !(attribs & QJSValue::PropertySetter)) {
+// v8::Local<v8::Object> descriptor = engine()->originalGlobalObject()->getOwnPropertyDescriptor(recv, name);
+// if (!descriptor.IsEmpty()) {
+// v8::Local<v8::Value> setter = descriptor->Get(v8::String::New("set"));
+// if (!setter.IsEmpty() && !setter->IsUndefined()) {
+// recv->Delete(name);
+// engine()->originalGlobalObject()->defineGetterOrSetter(recv, name, setter, QJSValue::PropertySetter);
+// if (tryCatch.HasCaught())
+// engine()->setException(tryCatch.Exception(), tryCatch.Message());
+// return;
+// }
+// }
+// } else if (attribs & QJSValue::PropertySetter && !(attribs & QJSValue::PropertyGetter)) {
+// v8::Local<v8::Object> descriptor = engine()->originalGlobalObject()->getOwnPropertyDescriptor(recv, name);
+// if (!descriptor.IsEmpty()) {
+// v8::Local<v8::Value> getter = descriptor->Get(v8::String::New("get"));
+// if (!getter.IsEmpty() && !getter->IsUndefined()) {
+// recv->Delete(name);
+// engine()->originalGlobalObject()->defineGetterOrSetter(recv, name, getter, QJSValue::PropertyGetter);
+// if (tryCatch.HasCaught())
+// engine()->setException(tryCatch.Exception(), tryCatch.Message());
+// return;
+// }
+// }
+// }
+ recv->Delete(name);
+ if (tryCatch.HasCaught())
+ engine()->setException(tryCatch.Exception(), tryCatch.Message());
+ return;
+ }
+
+ if (engine() != value->engine()) {
+ qWarning("QJSValue::setProperty(%s) failed: "
+ "cannot set value created in a different engine",
+ qPrintable(QJSConverter::toString(name)));
+ return;
+ }
+
+ v8::TryCatch tryCatch;
+// if (attribs & (QJSValue::PropertyGetter | QJSValue::PropertySetter)) {
+// engine()->originalGlobalObject()->defineGetterOrSetter(*this, name, value->m_value, attribs);
+// } else {
+ v8::Object::Cast(*m_value)->Set(name, value->m_value, v8::PropertyAttribute(attribs & QJSConverter::PropertyAttributeMask));
+// }
+ if (tryCatch.HasCaught())
+ engine()->setException(tryCatch.Exception(), tryCatch.Message());
+}
+
+inline void QJSValuePrivate::setProperty(quint32 index, QJSValuePrivate* value, uint attribs)
+{
+ // FIXME this method should by integrated with other overloads to use the same code patch.
+ // for now it is not possible as v8 doesn't allow to set property attributes using index based api.
+
+ if (!isObject())
+ return;
+
+ if (attribs) {
+ // FIXME we dont need to convert index to a string.
+ //Object::Set(int,value) do not take attributes.
+ setProperty(QString::number(index), value, attribs);
+ return;
+ }
+
+ if (!value->isJSBased())
+ value->assignEngine(engine());
+
+ if (!value->isValid()) {
+ // Remove the property.
+ v8::HandleScope handleScope;
+ v8::TryCatch tryCatch;
+ v8::Object::Cast(*m_value)->Delete(index);
+ if (tryCatch.HasCaught())
+ engine()->setException(tryCatch.Exception(), tryCatch.Message());
+ return;
+ }
+
+ if (engine() != value->engine()) {
+ qWarning("QJSValue::setProperty() failed: cannot set value created in a different engine");
+ return;
+ }
+
+ v8::HandleScope handleScope;
+ v8::TryCatch tryCatch;
+ v8::Object::Cast(*m_value)->Set(index, value->m_value);
+ if (tryCatch.HasCaught())
+ engine()->setException(tryCatch.Exception(), tryCatch.Message());
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(const QString& name) const
+{
+ if (!name.length())
+ return InvalidValue();
+
+ v8::HandleScope handleScope;
+ return property(QJSConverter::toString(name));
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(v8::Handle<v8::String> name) const
+{
+ Q_ASSERT(!name.IsEmpty());
+ if (!isObject())
+ return InvalidValue();
+ return property<>(name);
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(quint32 index) const
+{
+ if (!isObject())
+ return InvalidValue();
+ return property<>(index);
+}
+
+template<typename T>
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(T name) const
+{
+ Q_ASSERT(isObject());
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Object> self(v8::Object::Cast(*m_value));
+
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::Value> result = self->Get(name);
+ if (tryCatch.HasCaught()) {
+ result = tryCatch.Exception();
+ engine()->setException(result, tryCatch.Message());
+ return new QJSValuePrivate(engine(), result);
+ }
+ if (result.IsEmpty() || (result->IsUndefined() && !self->Has(name))) {
+ // In QtScript we make a distinction between a property that exists and has value undefined,
+ // and a property that doesn't exist; in the latter case, we should return an invalid value.
+ return InvalidValue();
+ }
+ return new QJSValuePrivate(engine(), result);
+}
+
+inline bool QJSValuePrivate::deleteProperty(const QString& name)
+{
+ if (!isObject())
+ return false;
+
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
+ return self->Delete(QJSConverter::toString(name));
+}
+
+inline QJSValue::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const
+{
+ if (!isObject())
+ return QJSValue::PropertyFlags(0);
+
+ v8::HandleScope handleScope;
+ return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), QJSConverter::toString(name));
+}
+
+inline QJSValue::PropertyFlags QJSValuePrivate::propertyFlags(v8::Handle<v8::String> name) const
+{
+ if (!isObject())
+ return QJSValue::PropertyFlags(0);
+
+ v8::HandleScope handleScope;
+ return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), name);
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, const QJSValueList& args)
+{
+ if (!isCallable())
+ return InvalidValue();
+
+ v8::HandleScope handleScope;
+
+ // Convert all arguments and bind to the engine.
+ int argc = args.size();
+ QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc);
+ if (!prepareArgumentsForCall(argv.data(), args)) {
+ qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
+ return InvalidValue();
+ }
+
+ return call(thisObject, argc, argv.data());
+}
+
+QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, int argc, v8::Handle<v8::Value> *argv)
+{
+ QV8Engine *e = engine();
+
+ v8::Handle<v8::Object> recv;
+
+ if (!thisObject || !thisObject->isObject()) {
+ recv = v8::Handle<v8::Object>(v8::Object::Cast(*e->global()));
+ } else {
+ if (!thisObject->assignEngine(e)) {
+ qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine");
+ return InvalidValue();
+ }
+
+ recv = v8::Handle<v8::Object>(v8::Object::Cast(*thisObject->m_value));
+ }
+
+ if (argc < 0) {
+ v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array"));
+ e->setException(exeption);
+ return new QJSValuePrivate(e, exeption);
+ }
+
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsFunction(recv, argc, argv);
+
+ if (result.IsEmpty()) {
+ result = tryCatch.Exception();
+ // TODO: figure out why v8 doesn't always produce an exception value.
+ //Q_ASSERT(!result.IsEmpty());
+ if (result.IsEmpty())
+ result = v8::Exception::Error(v8::String::New("missing exception value"));
+ e->setException(result, tryCatch.Message());
+ }
+
+ return new QJSValuePrivate(e, result);
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::construct(int argc, v8::Handle<v8::Value> *argv)
+{
+ QV8Engine *e = engine();
+
+ if (argc < 0) {
+ v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array"));
+ e->setException(exeption);
+ return new QJSValuePrivate(e, exeption);
+ }
+
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsConstructor(argc, argv);
+
+ if (result.IsEmpty()) {
+ result = tryCatch.Exception();
+ e->setException(result, tryCatch.Message());
+ }
+
+ return new QJSValuePrivate(e, result);
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::construct(const QJSValueList& args)
+{
+ if (!isCallable())
+ return InvalidValue();
+
+ v8::HandleScope handleScope;
+
+ // Convert all arguments and bind to the engine.
+ int argc = args.size();
+ QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc);
+ if (!prepareArgumentsForCall(argv.data(), args)) {
+ qWarning("QJSValue::construct() failed: cannot construct function with argument created in a different engine");
+ return InvalidValue();
+ }
+
+ return construct(argc, argv.data());
+}
+
+/*! \internal
+ * Make sure this value is associated with a v8 value belogning to this engine.
+ * If the value was invalid, or belogning to another engine, return false.
+ */
+bool QJSValuePrivate::assignEngine(QV8Engine* engine)
+{
+ Q_ASSERT(engine);
+ v8::HandleScope handleScope;
+ switch (m_state) {
+ case Invalid:
+ return false;
+ case CBool:
+ m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_bool));
+ break;
+ case CString:
+ m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(*u.m_string));
+ delete u.m_string;
+ break;
+ case CNumber:
+ m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_number));
+ break;
+ case CNull:
+ m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::NullValue));
+ break;
+ case CUndefined:
+ m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::UndefinedValue));
+ break;
+ default:
+ if (this->engine() == engine)
+ return true;
+ else if (!isJSBased())
+ Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
+ else
+ qWarning("JSValue can't be rassigned to an another engine.");
+ return false;
+ }
+ m_engine = engine;
+ m_state = JSValue;
+
+ m_engine->registerValue(this);
+ return true;
+}
+
+/*!
+ \internal
+ reinitialize this value to an invalid value.
+*/
+void QJSValuePrivate::reinitialize()
+{
+ if (isJSBased()) {
+ m_engine->unregisterValue(this);
+ m_value.Dispose();
+ m_value.Clear();
+ } else if (isStringBased()) {
+ delete u.m_string;
+ }
+ m_engine = 0;
+ m_state = Invalid;
+}
+
+/*!
+ \internal
+ reinitialize this value to an JSValue.
+*/
+void QJSValuePrivate::reinitialize(QV8Engine* engine, v8::Handle<v8::Value> value)
+{
+ Q_ASSERT_X(this != InvalidValue(), Q_FUNC_INFO, "static invalid can't be reinitialized to a different value");
+ if (isJSBased()) {
+ m_value.Dispose();
+ // avoid double registration
+ m_engine->unregisterValue(this);
+ } else if (isStringBased()) {
+ delete u.m_string;
+ }
+ m_engine = engine;
+ m_state = JSValue;
+ m_value = v8::Persistent<v8::Value>::New(value);
+ m_engine->registerValue(this);
+}
+
+QV8Engine* QJSValuePrivate::engine() const
+{
+ return m_engine;
+}
+
+inline QJSValuePrivate::operator v8::Handle<v8::Value>() const
+{
+ Q_ASSERT(isJSBased());
+ return m_value;
+}
+
+inline QJSValuePrivate::operator v8::Handle<v8::Object>() const
+{
+ Q_ASSERT(isObject());
+ return v8::Handle<v8::Object>::Cast(m_value);
+}
+
+/*!
+ * Return a v8::Handle, assign to the engine if needed.
+ */
+v8::Handle<v8::Value> QJSValuePrivate::asV8Value(QV8Engine* engine)
+{
+ if (!m_engine) {
+ if (!assignEngine(engine))
+ return v8::Handle<v8::Value>();
+ }
+ Q_ASSERT(isJSBased());
+ return m_value;
+}
+
+/*!
+ \internal
+ Returns true if QSV have an engine associated.
+*/
+bool QJSValuePrivate::isJSBased() const
+{
+#ifndef QT_NO_DEBUG
+ // internals check.
+ if (m_state >= JSValue)
+ Q_ASSERT(!m_value.IsEmpty());
+ else
+ Q_ASSERT(m_value.IsEmpty());
+#endif
+ return m_state >= JSValue;
+}
+
+/*!
+ \internal
+ Returns true if current value of QSV is placed in m_number.
+*/
+bool QJSValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; }
+
+/*!
+ \internal
+ Returns true if current value of QSV is placed in m_string.
+*/
+bool QJSValuePrivate::isStringBased() const { return m_state == CString; }
+
+/*!
+ \internal
+ Converts arguments and bind them to the engine.
+ \attention argv should be big enough
+*/
+inline bool QJSValuePrivate::prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& args) const
+{
+ QJSValueList::const_iterator i = args.constBegin();
+ for (int j = 0; i != args.constEnd(); j++, i++) {
+ QJSValuePrivate* value = QJSValuePrivate::get(*i);
+ if ((value->isJSBased() && engine() != value->engine())
+ || (!value->isJSBased() && value->isValid() && !value->assignEngine(engine())))
+ // Different engines are not allowed!
+ return false;
+ if (value->isValid())
+ argv[j] = *value;
+ else
+ argv[j] = engine()->makeJSValue(QJSValue::UndefinedValue);
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/v8/qjsvalue_p.h b/src/declarative/qml/v8/qjsvalue_p.h
new file mode 100644
index 0000000000..7b2a001f97
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalue_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QJSVALUE_P_H
+#define QJSVALUE_P_H
+
+#include <private/qv8_p.h>
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qvarlengtharray.h>
+#include <qdebug.h>
+
+#include "qscripttools_p.h"
+#include "qscriptshareddata_p.h"
+#include "qjsvalue.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QJSValuePrivate
+*/
+class QJSValuePrivate
+ : public QSharedData
+ , public QScriptLinkedNode
+{
+public:
+ inline QJSValuePrivate();
+ inline static QJSValuePrivate* get(const QJSValue& q);
+ inline static QJSValue get(const QJSValuePrivate* d);
+ inline static QJSValue get(QJSValuePrivate* d);
+ inline static QJSValue get(QScriptPassPointer<QJSValuePrivate> d);
+ inline ~QJSValuePrivate();
+
+ inline QJSValuePrivate(bool value);
+ inline QJSValuePrivate(int value);
+ inline QJSValuePrivate(uint value);
+ inline QJSValuePrivate(double value);
+ inline QJSValuePrivate(const QString& value);
+ inline QJSValuePrivate(QJSValue::SpecialValue value);
+
+ inline QJSValuePrivate(QV8Engine *engine, bool value);
+ inline QJSValuePrivate(QV8Engine *engine, int value);
+ inline QJSValuePrivate(QV8Engine *engine, uint value);
+ inline QJSValuePrivate(QV8Engine *engine, double value);
+ inline QJSValuePrivate(QV8Engine *engine, const QString& value);
+ inline QJSValuePrivate(QV8Engine *engine, QJSValue::SpecialValue value);
+ inline QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value>);
+ inline void reinitialize();
+ inline void reinitialize(QV8Engine *engine, v8::Handle<v8::Value> value);
+
+ inline bool toBool() const;
+ inline double toNumber() const;
+ inline QScriptPassPointer<QJSValuePrivate> toObject() const;
+ inline QScriptPassPointer<QJSValuePrivate> toObject(QV8Engine *engine) const;
+ inline QString toString() const;
+ inline double toInteger() const;
+ inline qint32 toInt32() const;
+ inline quint32 toUInt32() const;
+ inline quint16 toUInt16() const;
+ inline QDateTime toDataTime() const;
+ inline QRegExp toRegExp() const;
+ inline QObject *toQObject() const;
+ inline QVariant toVariant() const;
+
+ inline bool isArray() const;
+ inline bool isBool() const;
+ inline bool isCallable() const;
+ inline bool isError() const;
+ inline bool isFunction() const;
+ inline bool isNull() const;
+ inline bool isNumber() const;
+ inline bool isObject() const;
+ inline bool isString() const;
+ inline bool isUndefined() const;
+ inline bool isValid() const;
+ inline bool isVariant() const;
+ inline bool isDate() const;
+ inline bool isRegExp() const;
+ inline bool isQObject() const;
+
+ inline bool equals(QJSValuePrivate* other);
+ inline bool strictlyEquals(QJSValuePrivate* other);
+ inline bool lessThan(QJSValuePrivate *other) const;
+ inline bool instanceOf(QJSValuePrivate*) const;
+ inline bool instanceOf(v8::Handle<v8::Object> other) const;
+
+ inline QScriptPassPointer<QJSValuePrivate> prototype() const;
+ inline void setPrototype(QJSValuePrivate* prototype);
+
+ inline void setProperty(const QString &name, QJSValuePrivate *value, uint attribs = 0);
+ inline void setProperty(v8::Handle<v8::String> name, QJSValuePrivate *value, uint attribs = 0);
+ inline void setProperty(quint32 index, QJSValuePrivate* value, uint attribs = 0);
+ inline QScriptPassPointer<QJSValuePrivate> property(const QString& name) const;
+ inline QScriptPassPointer<QJSValuePrivate> property(v8::Handle<v8::String> name) const;
+ inline QScriptPassPointer<QJSValuePrivate> property(quint32 index) const;
+ template<typename T>
+ inline QScriptPassPointer<QJSValuePrivate> property(T name) const;
+ inline bool deleteProperty(const QString& name);
+ inline QJSValue::PropertyFlags propertyFlags(const QString& name) const;
+ inline QJSValue::PropertyFlags propertyFlags(v8::Handle<v8::String> name) const;
+
+ inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValueList& args);
+ inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValue& arguments);
+ inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, int argc, v8::Handle< v8::Value >* argv);
+ inline QScriptPassPointer<QJSValuePrivate> construct(int argc, v8::Handle<v8::Value> *argv);
+ inline QScriptPassPointer<QJSValuePrivate> construct(const QJSValueList& args);
+ inline QScriptPassPointer<QJSValuePrivate> construct(const QJSValue& arguments);
+
+ inline bool assignEngine(QV8Engine *engine);
+ inline QV8Engine *engine() const;
+
+ inline operator v8::Handle<v8::Value>() const;
+ inline operator v8::Handle<v8::Object>() const;
+ inline v8::Handle<v8::Value> asV8Value(QV8Engine *engine);
+private:
+ QV8Engine *m_engine;
+
+ // Please, update class documentation when you change the enum.
+ enum State {
+ Invalid = 0,
+ CString = 0x1000,
+ CNumber,
+ CBool,
+ CNull,
+ CUndefined,
+ JSValue = 0x2000, // V8 values are equal or higher then this value.
+ // JSPrimitive,
+ // JSObject
+ } m_state;
+
+ union CValue {
+ bool m_bool;
+ double m_number;
+ QString* m_string;
+
+ CValue() : m_number(0) {}
+ CValue(bool value) : m_bool(value) {}
+ CValue(int number) : m_number(number) {}
+ CValue(uint number) : m_number(number) {}
+ CValue(double number) : m_number(number) {}
+ CValue(QString* string) : m_string(string) {}
+ } u;
+ // v8::Persistent is not a POD, so can't be part of the union.
+ v8::Persistent<v8::Value> m_value;
+
+ Q_DISABLE_COPY(QJSValuePrivate)
+ inline bool isJSBased() const;
+ inline bool isNumberBased() const;
+ inline bool isStringBased() const;
+ inline bool prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& arguments) const;
+};
+
+// This template is used indirectly by the Q_GLOBAL_STATIC macro below
+template<>
+class QGlobalStaticDeleter<QJSValuePrivate>
+{
+public:
+ QGlobalStatic<QJSValuePrivate> &globalStatic;
+ QGlobalStaticDeleter(QGlobalStatic<QJSValuePrivate> &_globalStatic)
+ : globalStatic(_globalStatic)
+ {
+ globalStatic.pointer->ref.ref();
+ }
+
+ inline ~QGlobalStaticDeleter()
+ {
+ if (!globalStatic.pointer->ref.deref()) { // Logic copy & paste from SharedDataPointer
+ delete globalStatic.pointer;
+ }
+ globalStatic.pointer = 0;
+ globalStatic.destroyed = true;
+ }
+};
+
+Q_GLOBAL_STATIC(QJSValuePrivate, InvalidValue)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/v8/qjsvalueiterator.cpp b/src/declarative/qml/v8/qjsvalueiterator.cpp
new file mode 100644
index 0000000000..ca9123f0c0
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalueiterator.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** 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 "qjsvalueiterator.h"
+
+#include "qscriptisolate_p.h"
+#include "qjsvalue_p.h"
+#include "qv8engine_p.h"
+#include "qscript_impl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QJSValueIterator
+
+ \brief The QJSValueIterator class provides a Java-style iterator for QJSValue.
+
+ \ingroup script
+
+
+ The QJSValueIterator constructor takes a QJSValue 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 QJSValue:
+
+ \snippet doc/src/snippets/code/src_script_QJSValueIterator.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
+ QJSValue, use remove(). If you want to modify the value of a
+ property, use setValue().
+
+ Note that QJSValueIterator only iterates over the QJSValue'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_QJSValueIterator.cpp 1
+
+ Note that QJSValueIterator will not automatically skip over
+ properties that have the QJSValue::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_QJSValueIterator.cpp 2
+
+ \sa QJSValue::property()
+*/
+
+using v8::Persistent;
+using v8::Local;
+using v8::Array;
+using v8::String;
+using v8::Handle;
+using v8::Object;
+using v8::Value;
+
+// FIXME (Qt5) This class should be refactored. It should use the common Iterator interface.
+// FIXME it could be faster!
+class QJSValueIteratorPrivate {
+public:
+ inline QJSValueIteratorPrivate(const QJSValuePrivate* value);
+ inline ~QJSValueIteratorPrivate();
+
+ inline bool hasNext() const;
+ inline bool next();
+
+ inline QString name() const;
+
+ inline QScriptPassPointer<QJSValuePrivate> value() const;
+
+ inline bool isValid() const;
+ inline QV8Engine* engine() const;
+private:
+ Q_DISABLE_COPY(QJSValueIteratorPrivate)
+ //void dump(QString) const;
+
+ QScriptSharedDataPointer<QJSValuePrivate> m_object;
+ QList<v8::Persistent<v8::String> > m_names;
+ QMutableListIterator<v8::Persistent<v8::String> > m_iterator;
+};
+
+inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value)
+ : m_object(const_cast<QJSValuePrivate*>(value))
+ , m_iterator(m_names)
+{
+ Q_ASSERT(value);
+ QV8Engine *engine = m_object->engine();
+ QScriptIsolate api(engine);
+ if (!m_object->isObject())
+ m_object = 0;
+ else {
+ v8::HandleScope scope;
+ Handle<Value> tmp = *value;
+ Handle<Object> obj = Handle<Object>::Cast(tmp);
+ Local<Array> names;
+
+ // FIXME we need newer V8!
+ //names = obj->GetOwnPropertyNames();
+ names = engine->getOwnPropertyNames(obj);
+
+ // it is suboptimal, it would be better to write iterator instead
+ uint32_t count = names->Length();
+ Local<String> name;
+ m_names.reserve(count); // The count is the maximal count of values.
+ for (uint32_t i = count - 1; i < count; --i) {
+ name = names->Get(i)->ToString();
+ m_names.append(v8::Persistent<v8::String>::New(name));
+ }
+
+ // Reinitialize the iterator.
+ m_iterator = m_names;
+ }
+}
+
+inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate()
+{
+ QMutableListIterator<v8::Persistent<v8::String> > it = m_names;
+ //FIXME: we need register this QJSVAlueIterator
+ if (engine()) {
+ while (it.hasNext()) {
+ it.next().Dispose();
+ }
+ } else {
+ // FIXME leak ?
+ }
+}
+
+inline bool QJSValueIteratorPrivate::hasNext() const
+{
+ //dump("hasNext()");
+ return isValid()
+ ? m_iterator.hasNext() : false;
+}
+
+inline bool QJSValueIteratorPrivate::next()
+{
+ //dump("next();");
+ if (m_iterator.hasNext()) {
+ m_iterator.next();
+ return true;
+ }
+ return false;
+}
+
+inline QString QJSValueIteratorPrivate::name() const
+{
+ //dump("name");
+ if (!isValid())
+ return QString();
+
+ return QJSConverter::toString(m_iterator.value());
+}
+
+inline QScriptPassPointer<QJSValuePrivate> QJSValueIteratorPrivate::value() const
+{
+ //dump("value()");
+ if (!isValid())
+ return InvalidValue();
+
+ return m_object->property(m_iterator.value());
+}
+
+inline bool QJSValueIteratorPrivate::isValid() const
+{
+ bool result = m_object ? m_object->isValid() : false;
+ // We know that if this object is still valid then it is an object
+ // if this assumption is not correct then some other logic in this class
+ // have to be changed too.
+ Q_ASSERT(!result || m_object->isObject());
+ return result;
+}
+
+inline QV8Engine* QJSValueIteratorPrivate::engine() const
+{
+ return m_object ? m_object->engine() : 0;
+}
+
+//void QJSValueIteratorPrivate::dump(QString fname) const
+//{
+// qDebug() << " *** " << fname << " ***";
+// foreach (Persistent<String> name, m_names) {
+// qDebug() << " - " << QJSConverter::toString(name);
+// }
+//}
+
+/*!
+ 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).
+*/
+QJSValueIterator::QJSValueIterator(const QJSValue& object)
+ : d_ptr(new QJSValueIteratorPrivate(QJSValuePrivate::get(object)))
+{}
+
+/*!
+ Destroys the iterator.
+*/
+QJSValueIterator::~QJSValueIterator()
+{}
+
+/*!
+ 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 QJSValueIterator::hasNext() const
+{
+ Q_D(const QJSValueIterator);
+ QScriptIsolate api(d->engine());
+ return d->hasNext();
+}
+
+/*!
+ 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()
+*/
+bool QJSValueIterator::next()
+{
+ Q_D(QJSValueIterator);
+ QScriptIsolate api(d->engine());
+ return d->next();
+}
+
+/*!
+ Returns the name of the last property that was jumped over using
+ next() or previous().
+
+ \sa value(), flags()
+*/
+QString QJSValueIterator::name() const
+{
+ Q_D(const QJSValueIterator);
+ QScriptIsolate api(d->engine());
+ return d_ptr->name();
+}
+
+
+/*!
+ Returns the value of the last property that was jumped over using
+ next() or previous().
+
+ \sa setValue(), name()
+*/
+QJSValue QJSValueIterator::value() const
+{
+ Q_D(const QJSValueIterator);
+ QScriptIsolate api(d->engine());
+ return QJSValuePrivate::get(d->value());
+}
+
+
+/*!
+ 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).
+*/
+QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
+{
+ Q_D(QJSValueIterator);
+ QScriptIsolate api(d->engine());
+ d_ptr.reset(new QJSValueIteratorPrivate(QJSValuePrivate::get(object)));
+ return *this;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qjsvalueiterator.h b/src/declarative/qml/v8/qjsvalueiterator.h
new file mode 100644
index 0000000000..1ec4d4b63b
--- /dev/null
+++ b/src/declarative/qml/v8/qjsvalueiterator.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 <QtDeclarative/qjsvalue.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Script)
+
+class QString;
+
+class QJSValueIteratorPrivate;
+class Q_SCRIPT_EXPORT QJSValueIterator
+{
+public:
+ QJSValueIterator(const QJSValue &value);
+ ~QJSValueIterator();
+
+ bool hasNext() const;
+ bool next();
+
+ QString name() const;
+
+ QJSValue value() const;
+ QJSValueIterator& operator=(QJSValue &value);
+
+private:
+ QScopedPointer<QJSValueIteratorPrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QJSValueIterator)
+ Q_DISABLE_COPY(QJSValueIterator)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCRIPTVALUEITERATOR_H
diff --git a/src/declarative/qml/v8/qscript_impl_p.h b/src/declarative/qml/v8/qscript_impl_p.h
new file mode 100644
index 0000000000..e66b561efe
--- /dev/null
+++ b/src/declarative/qml/v8/qscript_impl_p.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QSCRIPT_IMPL_P_H
+#define QSCRIPT_IMPL_P_H
+
+#include "qv8engine_impl_p.h"
+#include "qjsvalue_impl_p.h"
+
+#endif //QSCRIPT_IMPL_P_H
diff --git a/src/declarative/qml/v8/qscriptisolate_p.h b/src/declarative/qml/v8/qscriptisolate_p.h
new file mode 100644
index 0000000000..fa200c00b6
--- /dev/null
+++ b/src/declarative/qml/v8/qscriptisolate_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 APIPREAMBLE_P_H
+#define APIPREAMBLE_P_H
+
+#include <private/qv8_p.h>
+#include "qv8engine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/**
+ \internal
+ Class used to switch to the right isolate. It does the same thing as v8::Isolate::Scope but
+ it checks for a null engine.
+ \attention We decided to put context switching "up" which means that it should be as high
+ as possible on call stack. And it should be switched at most once per public API function call.
+*/
+class QScriptIsolate {
+public:
+ // OperationMode was introduced to reduce number of checking for a null engine pointer. If we
+ // know that given pointer is not null than we should pass NotNullEngine as constructor argument
+ // that would nicely remove checking on compilation time.
+ enum OperationMode {Default, NotNullEngine};
+ inline QScriptIsolate(const QV8Engine *engine, const OperationMode mode = Default)
+ : m_engine(engine)
+ , m_mode(mode)
+ {
+ if (m_mode == NotNullEngine || m_engine) {
+ Q_ASSERT(m_engine);
+ m_engine->context()->Enter();
+ }
+ }
+
+ inline ~QScriptIsolate()
+ {
+ if (m_mode == NotNullEngine || m_engine) {
+ m_engine->context()->Exit();
+ }
+ }
+
+private:
+ Q_DISABLE_COPY(QScriptIsolate);
+ const QV8Engine *m_engine;
+ const OperationMode m_mode;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // APIPREAMBLE_P_H
diff --git a/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h b/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h
new file mode 100644
index 0000000000..c46d0e37a0
--- /dev/null
+++ b/src/declarative/qml/v8/qscriptoriginalglobalobject_p.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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 QSCRIPTORIGINALGLOBALOBJECT_P_H
+#define QSCRIPTORIGINALGLOBALOBJECT_P_H
+
+#include "QtCore/qglobal.h"
+#include "qjsvalue.h"
+
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+
+/*!
+ \internal
+ This class is a workaround for missing V8 API functionality. This class keeps all important
+ properties of an original (default) global object, so we can use it even if the global object was
+ changed.
+
+ FIXME this class is a container for workarounds :-) it should be replaced by proper API calls.
+
+ The class have to be created on the QV8Engine creation time (before any change got applied to
+ global object).
+
+ \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly.
+*/
+class QScriptOriginalGlobalObject
+{
+public:
+ inline QScriptOriginalGlobalObject(const QV8Engine *engine, v8::Handle<v8::Context> context);
+ inline void destroy();
+
+ inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
+ inline v8::Local<v8::Object> getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const;
+ inline bool strictlyEquals(v8::Handle<v8::Object> object);
+private:
+ Q_DISABLE_COPY(QScriptOriginalGlobalObject)
+
+ // Copy of constructors and prototypes used in isType functions.
+ v8::Persistent<v8::Function> m_ownPropertyDescriptor;
+ v8::Persistent<v8::Object> m_globalObject;
+};
+
+QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(const QV8Engine *engine, v8::Handle<v8::Context> context)
+{
+ // Please notice that engine is not fully initialized at this point.
+
+ v8::Context::Scope contextScope(context);
+
+ v8::HandleScope scope;
+
+ m_globalObject = v8::Persistent<v8::Object>::New(context->Global());
+
+ v8::Local<v8::Object> objectConstructor = m_globalObject->Get(v8::String::New("Object"))->ToObject();
+ Q_ASSERT(objectConstructor->IsObject());
+ { // Initialize m_ownPropertyDescriptor.
+ v8::Local<v8::Value> ownPropertyDescriptor = objectConstructor->Get(v8::String::New("getOwnPropertyDescriptor"));
+ Q_ASSERT(!ownPropertyDescriptor.IsEmpty());
+ m_ownPropertyDescriptor = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(ownPropertyDescriptor));
+ }
+}
+
+/*!
+ \internal
+ QScriptOriginalGlobalObject lives as long as QV8Engine that keeps it. In ~QSEP
+ the v8 context is removed, so we need to remove our handlers before. to break this dependency
+ destroy method should be called before or insight QSEP destructor.
+*/
+inline void QScriptOriginalGlobalObject::destroy()
+{
+ m_ownPropertyDescriptor.Dispose();
+ m_globalObject.Dispose();
+ // After this line this instance is unusable.
+}
+
+inline QJSValue::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
+{
+ Q_ASSERT(object->IsObject());
+ Q_ASSERT(!property.IsEmpty());
+ v8::Local<v8::Object> descriptor = getOwnPropertyDescriptor(object, property);
+ if (descriptor.IsEmpty()) {
+// // Property isn't owned by this object.
+// if (!(mode & QScriptValue::ResolvePrototype))
+// return 0;
+ v8::Local<v8::Value> prototype = object->GetPrototype();
+ if (prototype->IsNull())
+ return 0;
+ return getPropertyFlags(v8::Local<v8::Object>::Cast(prototype), property);
+ }
+ v8::Local<v8::String> writableName = v8::String::New("writable");
+ v8::Local<v8::String> configurableName = v8::String::New("configurable");
+ v8::Local<v8::String> enumerableName = v8::String::New("enumerable");
+// v8::Local<v8::String> getName = v8::String::New("get");
+// v8::Local<v8::String> setName = v8::String::New("set");
+
+ unsigned flags = 0;
+
+ if (!descriptor->Get(configurableName)->BooleanValue())
+ flags |= QJSValue::Undeletable;
+ if (!descriptor->Get(enumerableName)->BooleanValue())
+ flags |= QJSValue::SkipInEnumeration;
+
+ //"writable" is only a property of the descriptor if it is not an accessor
+ if (descriptor->Has(writableName)) {
+ if (!descriptor->Get(writableName)->BooleanValue())
+ flags |= QJSValue::ReadOnly;
+ } else {
+// if (descriptor->Get(getName)->IsObject())
+// flags |= QScriptValue::PropertyGetter;
+// if (descriptor->Get(setName)->IsObject())
+// flags |= QScriptValue::PropertySetter;
+ }
+
+ return QJSValue::PropertyFlag(flags);
+}
+
+inline v8::Local<v8::Object> QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const
+{
+ Q_ASSERT(object->IsObject());
+ Q_ASSERT(!property.IsEmpty());
+ // FIXME do we need try catch here?
+ v8::Handle<v8::Value> argv[] = {object, property};
+ v8::Local<v8::Value> descriptor = m_ownPropertyDescriptor->Call(m_globalObject, /* argc */ 2, argv);
+ if (descriptor.IsEmpty() || !descriptor->IsObject())
+ return v8::Local<v8::Object>();
+ return v8::Local<v8::Object>::Cast(descriptor);
+}
+
+inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle<v8::Object> object)
+{
+ return m_globalObject->GetPrototype()->StrictEquals(object);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/v8/qscriptshareddata_p.h b/src/declarative/qml/v8/qscriptshareddata_p.h
new file mode 100644
index 0000000000..6604b10e32
--- /dev/null
+++ b/src/declarative/qml/v8/qscriptshareddata_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QSCRIPTSHAREDDATA_P_H
+#define QSCRIPTSHAREDDATA_P_H
+
+#include "qglobal.h"
+#include "qshareddata.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ This class should have the same interface as the QSharedData, but implementation doesn't
+ need to be thread safe, so atomic ref count was replaced by normal integer value.
+*/
+class QScriptSharedData
+{
+public:
+ class ReferenceCounter {
+ // FIXME shouldn't it be uint or something longer?
+ mutable int m_ref;
+ ReferenceCounter(int ref) : m_ref(ref) {}
+ ~ReferenceCounter() { Q_ASSERT_X(!m_ref, Q_FUNC_INFO, "Memory problem found"); }
+ public:
+ bool ref() { return ++m_ref; }
+ bool deref() { return --m_ref; }
+ friend class QScriptSharedData;
+ };
+
+ ReferenceCounter ref;
+ inline QScriptSharedData() : ref(0) { }
+
+private:
+ Q_DISABLE_COPY(QScriptSharedData)
+};
+
+
+template <class T> class QScriptPassPointer;
+
+// FIXME: that could be reimplemented to not check for a null value.
+template<class T>
+class QScriptSharedDataPointer : public QExplicitlySharedDataPointer<T>
+{
+public:
+ inline QScriptSharedDataPointer() {}
+ explicit QScriptSharedDataPointer(QScriptPassPointer<T> data) : QExplicitlySharedDataPointer<T>(data.give()) {}
+ explicit QScriptSharedDataPointer(T *data) : QExplicitlySharedDataPointer<T>(data) {}
+
+ inline QScriptSharedDataPointer<T> &operator=(const QScriptPassPointer<T> &other)
+ {
+ this->QExplicitlySharedDataPointer<T>::operator =(other.give());
+ return *this;
+ }
+ inline QScriptSharedDataPointer<T> &operator=(T *other)
+ {
+ this->QExplicitlySharedDataPointer<T>::operator =(other);
+ return *this;
+ }
+};
+
+// FIXME: that could be reimplemented to not check for a null value.
+template <class T>
+class QScriptPassPointer {
+public:
+ QScriptPassPointer(T *data) : m_ptr(data) {}
+ inline QScriptPassPointer() { m_ptr = 0; }
+ inline QScriptPassPointer(const QScriptPassPointer<T> &other) : m_ptr(other.give()) {}
+ inline ~QScriptPassPointer() { Q_ASSERT_X(!m_ptr, Q_FUNC_INFO, "Ownership of the QScriptPassPointer hasn't been taken"); }
+
+ inline T &operator*() const { return *m_ptr; }
+ inline T *operator->() { return m_ptr; }
+ inline T *operator->() const { return m_ptr; }
+ inline T *data() const { return m_ptr; }
+ inline const T *constData() const { return m_ptr; }
+
+ inline bool operator==(const QScriptPassPointer<T> &other) const { return m_ptr == other.m_ptr; }
+ inline bool operator!=(const QScriptPassPointer<T> &other) const { return m_ptr != other.m_ptr; }
+ inline bool operator==(const QScriptSharedDataPointer<T> &other) const { return m_ptr == other.m_ptr; }
+ inline bool operator!=(const QScriptSharedDataPointer<T> &other) const { return m_ptr != other.m_ptr; }
+ inline bool operator==(const T *ptr) const { return m_ptr == ptr; }
+ inline bool operator!=(const T *ptr) const { return m_ptr != ptr; }
+
+ inline operator bool () const { return m_ptr != 0; }
+ inline bool operator!() const { return !m_ptr; }
+
+ inline QScriptPassPointer<T> & operator=(const QScriptPassPointer<T> &other)
+ {
+ if (other.m_ptr != m_ptr) {
+ if (m_ptr)
+ delete m_ptr;
+ m_ptr = other.give();
+ }
+ return *this;
+ }
+
+ inline QScriptPassPointer &operator=(T *other)
+ {
+ if (other != m_ptr) {
+ if (m_ptr)
+ delete m_ptr;
+ m_ptr = other;
+ }
+ return *this;
+ }
+
+ inline T* give() const
+ {
+ T* result = m_ptr;
+ m_ptr = 0;
+ return result;
+ }
+
+private:
+ mutable T* m_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSCRIPTSHAREDDATA_P_H
diff --git a/src/declarative/qml/v8/qscripttools_p.h b/src/declarative/qml/v8/qscripttools_p.h
new file mode 100644
index 0000000000..f74fbab83f
--- /dev/null
+++ b/src/declarative/qml/v8/qscripttools_p.h
@@ -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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+
+#ifndef QSCRIPTTOOLS_P_H
+#define QSCRIPTTOOLS_P_H
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+template<class T>
+class QScriptBagContainer;
+
+/*!
+ \internal
+ \interface
+ Helper class for a container. The purpuse of it is to add two pointer properties to a class
+ inheriting this class without bloating an interface.
+
+ This class exist only as a memory storage implementation. The only way to use it is to inherit it.
+*/
+class QScriptLinkedNode
+{
+protected:
+ QScriptLinkedNode()
+ : m_next(0)
+ , m_prev(0)
+ {}
+
+ ~QScriptLinkedNode()
+ {
+ Q_ASSERT_X(!isUsed(), Q_FUNC_INFO, "Destorying QScriptLinkedNode instance that still is in a container");
+ }
+
+private:
+ bool isUsed() const
+ {
+ return m_next || m_prev;
+ }
+
+#if defined(Q_NO_TEMPLATE_FRIENDS)
+public:
+#else
+ template<class T>
+ friend class QScriptBagContainer;
+#endif
+ QScriptLinkedNode *m_next;
+ QScriptLinkedNode *m_prev;
+};
+
+/*!
+ \internal
+ The QScriptBagContainer is a simple, low level, set like container for a pointer type castable to
+ QScriptLinkedNode*.
+ Algorithms complexity:
+ put: O(1)
+ get: O(1)
+ forEach: O(n)
+ \note This container doesn't take ownership of pointed values.
+ \attention All values have to be unique.
+*/
+template<class T>
+class QScriptBagContainer
+{
+public:
+ QScriptBagContainer()
+ : m_first(0)
+ {}
+
+ /*!
+ \internal
+ Add a this \a value to this container
+ */
+ void insert(T* value)
+ {
+ //dump(Q_FUNC_INFO, value);
+ Q_ASSERT_X(!contains(value), Q_FUNC_INFO, "Can't insert a value which is in the bag already");
+ QScriptLinkedNode* v = static_cast<QScriptLinkedNode*>(value);
+ Q_ASSERT(v);
+ Q_ASSERT_X(!v->m_next && !v->m_prev, Q_FUNC_INFO, "Can't insert a value which is in an another bag");
+
+ if (m_first)
+ m_first->m_prev = v;
+
+ v->m_next = m_first;
+ v->m_prev = 0;
+ m_first = v;
+ }
+
+ /*!
+ \internal
+ Remove this \a value from this container
+ */
+ void remove(T* value)
+ {
+ //dump(Q_FUNC_INFO, value);
+ QScriptLinkedNode* v = static_cast<QScriptLinkedNode*>(value);
+ Q_ASSERT(v);
+
+ if (!v->m_next && !v->m_prev && m_first != v) {
+ // ignore that value as it is not registered at all
+ // FIXME: That may be optimized out if unregister call is removed from ~QtDataBase
+ return;
+ }
+
+ Q_ASSERT_X(contains(value), Q_FUNC_INFO, "Can't remove a value which is not in the bag");
+ Q_ASSERT(v->m_prev || (m_first == v && !v->m_prev));
+
+ if (v->m_next)
+ v->m_next->m_prev= v->m_prev;
+
+ if (v->m_prev)
+ v->m_prev->m_next = v->m_next;
+ else
+ m_first = v->m_next;
+ // reset removed value
+ v->m_next = v->m_prev = 0;
+ }
+
+ /*!
+ \internal
+ Call \a fun for each element in this container. Fun should accept T* as a parameter.
+ \note In general it is not allowed to change this container by calling put() or get() unless
+ given value is the same as currently procceded by forEach.
+ */
+ template<class Functor>
+ void forEach(Functor fun)
+ {
+ //dump(Q_FUNC_INFO);
+ QScriptLinkedNode *i = m_first;
+ QScriptLinkedNode *tmp;
+ while (i) {
+ tmp = i;
+ i = i->m_next;
+ fun(static_cast<T*>(tmp));
+ }
+ }
+
+ /*!
+ \internal
+ Clear this container.
+ */
+ void clear()
+ {
+ m_first = 0;
+ }
+
+ /*!
+ \internal
+ Returns true if this container is empty; false otherwise.
+ */
+ bool isEmpty() const
+ {
+ return !m_first;
+ }
+
+// void dump(const char* msg, T* obj = 0) const
+// {
+// qDebug() << msg << obj;
+// qDebug() << m_first;
+// QScriptLinkedNode *i = m_first;
+// while (i) {
+// qDebug() <<" - " << i << "(" << i->m_prev << ", " << i->m_next <<")";
+// i = i->m_next;
+// }
+// }
+
+private:
+ bool contains(T *value) const
+ {
+ QScriptLinkedNode *i = m_first;
+ while (i) {
+ if (static_cast<T*>(i) == value)
+ return true;
+ i = i->m_next;
+ }
+ return false;
+ }
+ QScriptLinkedNode *m_first;
+};
+
+QT_END_NAMESPACE
+
+#endif //QSCRIPTTOOLS_P_H
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
index 4f5543e690..c45274a97f 100644
--- a/src/declarative/qml/v8/qv8bindings.cpp
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -129,7 +129,7 @@ void QV8BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags
ep->referenceScarceResources();
v8::HandleScope handle_scope;
- v8::Context::Scope scope(ep->v8engine.context());
+ v8::Context::Scope scope(ep->v8engine()->context());
v8::Local<v8::Value> result = evaluate(v8::Handle<v8::Function>::Cast(parent->functions->Get(index)),
&isUndefined);
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
index 0294a60871..acbfb92b15 100644
--- a/src/declarative/qml/v8/qv8engine.cpp
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -49,6 +49,7 @@
#include <private/qdeclarativeengine_p.h>
#include <private/qdeclarativecomponent_p.h>
#include <private/qdeclarativestringconverters_p.h>
+#include <private/qdeclarativeapplication_p.h>
#include <QtDeclarative/qdeclarativecomponent.h>
@@ -58,10 +59,15 @@
#include <QtCore/qnumeric.h>
#include <QtGui/qdesktopservices.h>
#include <QtGui/qfontdatabase.h>
-#include <private/qdeclarativeapplication_p.h>
#include <private/qdeclarativexmlhttprequest_p.h>
#include <private/qdeclarativesqldatabase_p.h>
+#include "qscript_impl_p.h"
+
+Q_DECLARE_METATYPE(QJSValue)
+Q_DECLARE_METATYPE(QList<int>)
+
+
// XXX TODO: Need to check all the global functions will also work in a worker script where the
// QDeclarativeEngine is not available
QT_BEGIN_NAMESPACE
@@ -94,9 +100,41 @@ static bool ObjectComparisonCallback(v8::Local<v8::Object> lhs, v8::Local<v8::Ob
return false;
}
-QV8Engine::QV8Engine()
-: m_xmlHttpRequestData(0), m_sqlDatabaseData(0), m_listModelData(0)
+QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
+ : q(qq)
+ , m_engine(0)
+ , m_ownsV8Context(ownership == QJSEngine::CreateNewContext)
+ , m_context((ownership == QJSEngine::CreateNewContext) ? v8::Context::New() : v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()))
+ , m_originalGlobalObject(this, m_context)
+ , m_xmlHttpRequestData(0)
+ , m_sqlDatabaseData(0)
+ , m_listModelData(0)
{
+ qMetaTypeId<QJSValue>();
+ qMetaTypeId<QList<int> >();
+
+ QByteArray v8args = qgetenv("V8ARGS");
+ if (!v8args.isEmpty())
+ v8::V8::SetFlagsFromString(v8args.constData(), v8args.length());
+
+ v8::HandleScope handle_scope;
+ qPersistentRegister(m_context);
+ v8::Context::Scope context_scope(m_context);
+
+ v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback);
+
+ m_stringWrapper.init();
+ m_contextWrapper.init(this);
+ m_qobjectWrapper.init(this);
+ m_typeWrapper.init(this);
+ m_listWrapper.init(this);
+ m_variantWrapper.init(this);
+ m_valueTypeWrapper.init(this);
+
+ {
+ v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames"));
+ m_getOwnPropertyNames = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(v));
+ }
}
QV8Engine::~QV8Engine()
@@ -114,6 +152,10 @@ QV8Engine::~QV8Engine()
qPersistentDispose(m_freezeObject);
qPersistentDispose(m_getOwnPropertyNames);
+
+ invalidateAllValues();
+ clearExceptions();
+
m_valueTypeWrapper.destroy();
m_variantWrapper.destroy();
m_listWrapper.destroy();
@@ -121,39 +163,11 @@ QV8Engine::~QV8Engine()
m_qobjectWrapper.destroy();
m_contextWrapper.destroy();
m_stringWrapper.destroy();
- qPersistentDispose(m_context);
-}
-
-void QV8Engine::init(QDeclarativeEngine *engine)
-{
- m_engine = engine;
-
- QByteArray v8args = qgetenv("V8ARGS");
- if (!v8args.isEmpty())
- v8::V8::SetFlagsFromString(v8args.constData(), v8args.length());
-
- v8::HandleScope handle_scope;
- m_context = v8::Context::New();
- qPersistentRegister(m_context);
- v8::Context::Scope context_scope(m_context);
-
- v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback);
- m_stringWrapper.init();
- m_contextWrapper.init(this);
- m_qobjectWrapper.init(this);
- m_typeWrapper.init(this);
- m_listWrapper.init(this);
- m_variantWrapper.init(this);
- m_valueTypeWrapper.init(this);
+ m_originalGlobalObject.destroy();
- {
- v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames"));
- m_getOwnPropertyNames = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(v));
- }
-
- initializeGlobal(m_context->Global());
- freezeObject(m_context->Global());
+ if (m_ownsV8Context)
+ qPersistentDispose(m_context);
}
QString QV8Engine::toStringStatic(v8::Handle<v8::Value> jsstr)
@@ -357,8 +371,10 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
break;
}
- if (QDeclarativeValueType *vt = QDeclarativeEnginePrivate::get(m_engine)->valueTypes[type])
- return m_valueTypeWrapper.newValueType(variant, vt);
+ if (m_engine) {
+ if (QDeclarativeValueType *vt = QDeclarativeEnginePrivate::get(m_engine)->valueTypes[type])
+ return m_valueTypeWrapper.newValueType(variant, vt);
+ }
} else {
if (type == qMetaTypeId<QDeclarativeListReference>()) {
@@ -386,7 +402,7 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
}
// XXX TODO: To be compatible, we still need to handle:
- // + QScriptValue
+ // + QJSValue
// + QObjectList
// + QList<int>
@@ -420,6 +436,7 @@ const QSet<QString> &QV8Engine::illegalNames() const
// Requires a handle scope
v8::Local<v8::Array> QV8Engine::getOwnPropertyNames(v8::Handle<v8::Object> o)
{
+ // FIXME Newer v8 have API for this function
v8::TryCatch tc;
v8::Handle<v8::Value> args[] = { o };
v8::Local<v8::Value> r = m_getOwnPropertyNames->Call(global(), 1, args);
@@ -531,9 +548,6 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
}
}
- if (m_engine)
- qt->Set(v8::String::New("application"), newQObject(new QDeclarativeApplication(m_engine)));
-
qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this));
qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this));
qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this));
@@ -543,12 +557,6 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
qt->Set(v8::String::New("size"), V8FUNCTION(size, this));
qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this));
- if (m_engine) {
- qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this));
- qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this));
- qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this));
- }
-
qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this));
qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this));
qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this));
@@ -561,6 +569,10 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
if (m_engine) {
+ qt->Set(v8::String::New("application"), newQObject(new QDeclarativeApplication(m_engine)));
+ qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this));
+ qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this));
+ qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this));
qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this));
qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this));
qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this));
@@ -1658,5 +1670,652 @@ v8::Handle<v8::Value> QV8Engine::qsTrIdNoOp(const v8::Arguments &args)
return args[0];
}
+void QV8Engine::initDeclarativeGlobalObject()
+{
+ v8::HandleScope handels;
+ v8::Context::Scope contextScope(m_context);
+ initializeGlobal(m_context->Global());
+ freezeObject(m_context->Global());
+}
+
+void QV8Engine::setEngine(QDeclarativeEngine *engine)
+{
+ m_engine = engine;
+ initDeclarativeGlobalObject();
+}
+
+void QV8Engine::setException(v8::Handle<v8::Value> value, v8::Handle<v8::Message> msg)
+{
+ m_exception.set(value, msg);
+}
+
+v8::Handle<v8::Value> QV8Engine::throwException(v8::Handle<v8::Value> value)
+{
+ setException(value);
+ v8::ThrowException(value);
+ return value;
+}
+
+void QV8Engine::clearExceptions()
+{
+ m_exception.clear();
+}
+
+v8::Handle<v8::Value> QV8Engine::uncaughtException() const
+{
+ if (!hasUncaughtException())
+ return v8::Handle<v8::Value>();
+ return m_exception;
+}
+
+bool QV8Engine::hasUncaughtException() const
+{
+ return m_exception;
+}
+
+int QV8Engine::uncaughtExceptionLineNumber() const
+{
+ return m_exception.lineNumber();
+}
+
+QStringList QV8Engine::uncaughtExceptionBacktrace() const
+{
+ return m_exception.backtrace();
+}
+
+/*!
+ \internal
+ Save the current exception on stack so it can be set again later.
+ \sa QV8Engine::restoreException
+*/
+void QV8Engine::saveException()
+{
+ m_exception.push();
+}
+
+/*!
+ \internal
+ Load a saved exception from stack. Current exception, if exists will be dropped
+ \sa QV8Engine::saveException
+*/
+void QV8Engine::restoreException()
+{
+ m_exception.pop();
+}
+
+QV8Engine::Exception::Exception() {}
+
+QV8Engine::Exception::~Exception()
+{
+ Q_ASSERT_X(m_stack.isEmpty(), Q_FUNC_INFO, "Some saved exceptions left. Asymetric pop/push found.");
+ clear();
+}
+
+void QV8Engine::Exception::set(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message)
+{
+ Q_ASSERT_X(!value.IsEmpty(), Q_FUNC_INFO, "Throwing an empty value handle is highly suspected");
+ clear();
+ m_value = v8::Persistent<v8::Value>::New(value);
+ m_message = v8::Persistent<v8::Message>::New(message);
+}
+
+void QV8Engine::Exception::clear()
+{
+ m_value.Dispose();
+ m_value.Clear();
+ m_message.Dispose();
+ m_message.Clear();
+}
+
+QV8Engine::Exception::operator bool() const
+{
+ return !m_value.IsEmpty();
+}
+
+QV8Engine::Exception::operator v8::Handle<v8::Value>() const
+{
+ Q_ASSERT(*this);
+ return m_value;
+}
+
+int QV8Engine::Exception::lineNumber() const
+{
+ if (m_message.IsEmpty())
+ return -1;
+ return m_message->GetLineNumber();
+}
+
+QStringList QV8Engine::Exception::backtrace() const
+{
+ if (m_message.IsEmpty())
+ return QStringList();
+
+ QStringList backtrace;
+ v8::Handle<v8::StackTrace> trace = m_message->GetStackTrace();
+ if (trace.IsEmpty())
+ // FIXME it should not happen (SetCaptureStackTraceForUncaughtExceptions is called).
+ return QStringList();
+
+ for (int i = 0; i < trace->GetFrameCount(); ++i) {
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(i);
+ backtrace.append(QJSConverter::toString(frame->GetFunctionName()));
+ backtrace.append(QJSConverter::toString(frame->GetFunctionName()));
+ backtrace.append(QString::fromAscii("()@"));
+ backtrace.append(QJSConverter::toString(frame->GetScriptName()));
+ backtrace.append(QString::fromAscii(":"));
+ backtrace.append(QString::number(frame->GetLineNumber()));
+ }
+ return backtrace;
+}
+
+void QV8Engine::Exception::push()
+{
+ m_stack.push(qMakePair(m_value, m_message));
+ m_value.Clear();
+ m_message.Clear();
+}
+
+void QV8Engine::Exception::pop()
+{
+ Q_ASSERT_X(!m_stack.empty(), Q_FUNC_INFO, "Attempt to load unsaved exception found");
+ ValueMessagePair pair = m_stack.pop();
+ clear();
+ m_value = pair.first;
+ m_message = pair.second;
+}
+
+QScriptPassPointer<QJSValuePrivate> QV8Engine::newRegExp(const QString &pattern, const QString &flags)
+{
+ int f = v8::RegExp::kNone;
+
+ QString::const_iterator i = flags.constBegin();
+ for (; i != flags.constEnd(); ++i) {
+ switch (i->unicode()) {
+ case 'i':
+ f |= v8::RegExp::kIgnoreCase;
+ break;
+ case 'm':
+ f |= v8::RegExp::kMultiline;
+ break;
+ case 'g':
+ f |= v8::RegExp::kGlobal;
+ break;
+ default:
+ {
+ // ignore a Syntax Error.
+ }
+ }
+ }
+
+ v8::Handle<v8::RegExp> regexp = v8::RegExp::New(QJSConverter::toString(pattern), static_cast<v8::RegExp::Flags>(f));
+ return new QJSValuePrivate(this, regexp);
+}
+
+QScriptPassPointer<QJSValuePrivate> QV8Engine::newRegExp(const QRegExp &regexp)
+{
+ return new QJSValuePrivate(this, QJSConverter::toRegExp(regexp));
+}
+
+
+// Converts a QVariantList to JS.
+// The result is a new Array object with length equal to the length
+// of the QVariantList, and the elements being the QVariantList's
+// elements converted to JS, recursively.
+v8::Handle<v8::Array> QV8Engine::variantListToJS(const QVariantList &lst)
+{
+ v8::Handle<v8::Array> result = v8::Array::New(lst.size());
+ for (int i = 0; i < lst.size(); ++i)
+ result->Set(i, variantToJS(lst.at(i)));
+ return result;
+}
+
+// Converts a JS Array object to a QVariantList.
+// The result is a QVariantList with length equal to the length
+// of the JS Array, and elements being the JS Array's elements
+// converted to QVariants, recursively.
+QVariantList QV8Engine::variantListFromJS(v8::Handle<v8::Array> jsArray)
+{
+ QVariantList result;
+ int hash = jsArray->GetIdentityHash();
+ if (visitedConversionObjects.contains(hash))
+ return result; // Avoid recursion.
+ v8::HandleScope handleScope;
+ visitedConversionObjects.insert(hash);
+ uint32_t length = jsArray->Length();
+ for (uint32_t i = 0; i < length; ++i)
+ result.append(variantFromJS(jsArray->Get(i)));
+ visitedConversionObjects.remove(hash);
+ return result;
+}
+
+// Converts a QVariantMap to JS.
+// The result is a new Object object with property names being
+// the keys of the QVariantMap, and values being the values of
+// the QVariantMap converted to JS, recursively.
+v8::Handle<v8::Object> QV8Engine::variantMapToJS(const QVariantMap &vmap)
+{
+ v8::Handle<v8::Object> result = v8::Object::New();
+ QVariantMap::const_iterator it;
+ for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
+ result->Set(QJSConverter::toString(it.key()), variantToJS(it.value()));
+ return result;
+}
+
+// Converts a JS Object to a QVariantMap.
+// The result is a QVariantMap with keys being the property names
+// of the object, and values being the values of the JS object's
+// properties converted to QVariants, recursively.
+QVariantMap QV8Engine::variantMapFromJS(v8::Handle<v8::Object> jsObject)
+{
+ QVariantMap result;
+ int hash = jsObject->GetIdentityHash();
+ if (visitedConversionObjects.contains(hash))
+ return result; // Avoid recursion.
+ visitedConversionObjects.insert(hash);
+ v8::HandleScope handleScope;
+ // TODO: Only object's own property names. Include non-enumerable properties.
+ v8::Handle<v8::Array> propertyNames = jsObject->GetPropertyNames();
+ uint32_t length = propertyNames->Length();
+ for (uint32_t i = 0; i < length; ++i) {
+ v8::Handle<v8::Value> name = propertyNames->Get(i);
+ result.insert(QJSConverter::toString(name->ToString()), variantFromJS(jsObject->Get(name)));
+ }
+ visitedConversionObjects.remove(hash);
+ return result;
+}
+
+// Converts the meta-type defined by the given type and data to JS.
+// Returns the value if conversion succeeded, an empty handle otherwise.
+v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data)
+{
+ Q_ASSERT(data != 0);
+ v8::Handle<v8::Value> result;
+
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Void:
+ return v8::Undefined();
+ case QMetaType::Bool:
+ return v8::Boolean::New(*reinterpret_cast<const bool*>(data));
+ case QMetaType::Int:
+ return v8::Int32::New(*reinterpret_cast<const int*>(data));
+ case QMetaType::UInt:
+ return v8::Uint32::New(*reinterpret_cast<const uint*>(data));
+ case QMetaType::LongLong:
+ return v8::Number::New(double(*reinterpret_cast<const qlonglong*>(data)));
+ case QMetaType::ULongLong:
+#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
+#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
+ return v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
+#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
+ return v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
+#else
+ return v8::Number::New(double(*reinterpret_cast<const qulonglong*>(data)));
+#endif
+ case QMetaType::Double:
+ return v8::Number::New(double(*reinterpret_cast<const double*>(data)));
+ case QMetaType::QString:
+ return QJSConverter::toString(*reinterpret_cast<const QString*>(data));
+ case QMetaType::Float:
+ return v8::Number::New(*reinterpret_cast<const float*>(data));
+ case QMetaType::Short:
+ return v8::Int32::New(*reinterpret_cast<const short*>(data));
+ case QMetaType::UShort:
+ return v8::Uint32::New(*reinterpret_cast<const unsigned short*>(data));
+ case QMetaType::Char:
+ return v8::Int32::New(*reinterpret_cast<const char*>(data));
+ case QMetaType::UChar:
+ return v8::Uint32::New(*reinterpret_cast<const unsigned char*>(data));
+ case QMetaType::QChar:
+ return v8::Uint32::New((*reinterpret_cast<const QChar*>(data)).unicode());
+ case QMetaType::QStringList:
+ result = QJSConverter::toStringList(*reinterpret_cast<const QStringList *>(data));
+ break;
+ case QMetaType::QVariantList:
+ result = variantListToJS(*reinterpret_cast<const QVariantList *>(data));
+ break;
+ case QMetaType::QVariantMap:
+ result = variantMapToJS(*reinterpret_cast<const QVariantMap *>(data));
+ break;
+ case QMetaType::QDateTime:
+ result = QJSConverter::toDateTime(*reinterpret_cast<const QDateTime *>(data));
+ break;
+ case QMetaType::QDate:
+ result = QJSConverter::toDateTime(QDateTime(*reinterpret_cast<const QDate *>(data)));
+ break;
+ case QMetaType::QRegExp:
+ result = QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(data));
+ break;
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ result = newQObject(*reinterpret_cast<QObject* const *>(data));
+ break;
+ case QMetaType::QVariant:
+ result = variantToJS(*reinterpret_cast<const QVariant*>(data));
+ break;
+ default:
+ if (type == qMetaTypeId<QJSValue>()) {
+ return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->asV8Value(this);
+ } else {
+ QByteArray typeName = QMetaType::typeName(type);
+ if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
+ return v8::Null();
+ } else {
+ // Fall back to wrapping in a QVariant.
+ result = newVariant(QVariant(type, data));
+ }
+ }
+ }
+ return result;
+}
+
+// Converts a JS value to a meta-type.
+// data must point to a place that can store a value of the given type.
+// Returns true if conversion succeeded, false otherwise.
+bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data) {
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(data) = value->ToBoolean()->Value();
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(data) = value->ToInt32()->Value();
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(data) = value->ToUint32()->Value();
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->ToInteger()->Value());
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->ToInteger()->Value());
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(data) = value->ToNumber()->Value();
+ return true;
+ case QMetaType::QString:
+ if (value->IsUndefined() || value->IsNull())
+ *reinterpret_cast<QString*>(data) = QString();
+ else
+ *reinterpret_cast<QString*>(data) = QJSConverter::toString(value->ToString());
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(data) = value->ToNumber()->Value();
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(data) = short(value->ToInt32()->Value());
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(data) = ushort(value->ToInt32()->Value()); // ### QScript::ToUInt16()
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(data) = char(value->ToInt32()->Value());
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->ToInt32()->Value());
+ return true;
+ case QMetaType::QChar:
+ if (value->IsString()) {
+ QString str = QJSConverter::toString(v8::Handle<v8::String>::Cast(value));
+ *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
+ } else {
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->ToInt32()->Value())); // ### QScript::ToUInt16()
+ }
+ return true;
+ case QMetaType::QDateTime:
+ if (value->IsDate()) {
+ *reinterpret_cast<QDateTime *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value));
+ return true;
+ } break;
+ case QMetaType::QDate:
+ if (value->IsDate()) {
+ *reinterpret_cast<QDate *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value)).date();
+ return true;
+ } break;
+ case QMetaType::QRegExp:
+ if (value->IsRegExp()) {
+ *reinterpret_cast<QRegExp *>(data) = QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
+ return true;
+ } break;
+ case QMetaType::QObjectStar:
+ if (isQObject(value) || value->IsNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
+ return true;
+ } break;
+ case QMetaType::QWidgetStar:
+ if (isQObject(value) || value->IsNull()) {
+ QObject *qo = qtObjectFromJS(value);
+ if (!qo || qo->isWidgetType()) {
+ *reinterpret_cast<QWidget* *>(data) = reinterpret_cast<QWidget*>(qo);
+ return true;
+ }
+ } break;
+ case QMetaType::QStringList:
+ if (value->IsArray()) {
+ *reinterpret_cast<QStringList *>(data) = QJSConverter::toStringList(v8::Handle<v8::Array>::Cast(value));
+ return true;
+ } break;
+ case QMetaType::QVariantList:
+ if (value->IsArray()) {
+ *reinterpret_cast<QVariantList *>(data) = variantListFromJS(v8::Handle<v8::Array>::Cast(value));
+ return true;
+ } break;
+ case QMetaType::QVariantMap:
+ if (value->IsObject()) {
+ *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(v8::Handle<v8::Object>::Cast(value));
+ return true;
+ } break;
+ case QMetaType::QVariant:
+ *reinterpret_cast<QVariant*>(data) = variantFromJS(value);
+ return true;
+ default:
+ ;
+ }
+
+#if 0
+ if (isQtVariant(value)) {
+ const QVariant &var = variantValue(value);
+ // ### Enable once constructInPlace() is in qt master.
+ if (var.userType() == type) {
+ QMetaType::constructInPlace(type, data, var.constData());
+ return true;
+ }
+ if (var.canConvert(QVariant::Type(type))) {
+ QVariant vv = var;
+ vv.convert(QVariant::Type(type));
+ Q_ASSERT(vv.userType() == type);
+ QMetaType::constructInPlace(type, data, vv.constData());
+ return true;
+ }
+
+ }
+#endif
+
+ // Try to use magic.
+
+ QByteArray name = QMetaType::typeName(type);
+ if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
+ return true;
+ if (isVariant(value) && name.endsWith('*')) {
+ int valueType = QMetaType::type(name.left(name.size()-1));
+ QVariant var = variantValue(value);
+ if (valueType == var.userType()) {
+ // We have T t, T* is requested, so return &t.
+ *reinterpret_cast<void* *>(data) = var.data();
+ return true;
+ } else {
+ // Look in the prototype chain.
+ v8::Handle<v8::Value> proto = value->ToObject()->GetPrototype();
+ while (proto->IsObject()) {
+ bool canCast = false;
+ if (isVariant(proto)) {
+ canCast = (type == variantValue(proto).userType())
+ || (valueType && (valueType == variantValue(proto).userType()));
+ }
+ else if (isQObject(proto)) {
+ QByteArray className = name.left(name.size()-1);
+ if (QObject *qobject = qtObjectFromJS(proto))
+ canCast = qobject->qt_metacast(className) != 0;
+ }
+ if (canCast) {
+ QByteArray varTypeName = QMetaType::typeName(var.userType());
+ if (varTypeName.endsWith('*'))
+ *reinterpret_cast<void* *>(data) = *reinterpret_cast<void* *>(var.data());
+ else
+ *reinterpret_cast<void* *>(data) = var.data();
+ return true;
+ }
+ proto = proto->ToObject()->GetPrototype();
+ }
+ }
+ } else if (value->IsNull() && name.endsWith('*')) {
+ *reinterpret_cast<void* *>(data) = 0;
+ return true;
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(this, value));
+ return true;
+ }
+
+ return false;
+}
+
+// Converts a QVariant to JS.
+v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value)
+{
+ return metaTypeToJS(value.userType(), value.constData());
+}
+
+// Converts a JS value to a QVariant.
+// Null, Undefined -> QVariant() (invalid)
+// Boolean -> QVariant(bool)
+// Number -> QVariant(double)
+// String -> QVariant(QString)
+// Array -> QVariantList(...)
+// Date -> QVariant(QDateTime)
+// RegExp -> QVariant(QRegExp)
+// [Any other object] -> QVariantMap(...)
+QVariant QV8Engine::variantFromJS(v8::Handle<v8::Value> value)
+{
+ Q_ASSERT(!value.IsEmpty());
+ if (value->IsNull() || value->IsUndefined())
+ return QVariant();
+ if (value->IsBoolean())
+ return value->ToBoolean()->Value();
+ else if (value->IsInt32())
+ return value->ToInt32()->Value();
+ else if (value->IsNumber())
+ return value->ToNumber()->Value();
+ if (value->IsString())
+ return QJSConverter::toString(value->ToString());
+ Q_ASSERT(value->IsObject());
+ if (value->IsArray())
+ return variantListFromJS(v8::Handle<v8::Array>::Cast(value));
+ if (value->IsDate())
+ return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value));
+ if (value->IsRegExp())
+ return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
+ if (isVariant(value))
+ return variantValue(value);
+ if (isQObject(value))
+ return qVariantFromValue(qtObjectFromJS(value));
+ return variantMapFromJS(value->ToObject());
+}
+
+bool QV8Engine::convertToNativeQObject(v8::Handle<v8::Value> value,
+ const QByteArray &targetType,
+ void **result)
+{
+ if (!targetType.endsWith('*'))
+ return false;
+ if (QObject *qobject = qtObjectFromJS(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;
+}
+
+QObject *QV8Engine::qtObjectFromJS(v8::Handle<v8::Value> value)
+{
+ if (!value->IsObject())
+ return 0;
+
+ QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource();
+ if (!r)
+ return 0;
+ QV8ObjectResource::ResourceType type = r->resourceType();
+ if (type == QV8ObjectResource::QObjectType)
+ return qobjectWrapper()->toQObject(r);
+ else if (type == QV8ObjectResource::VariantType) {
+ QVariant variant = variantWrapper()->toVariant(r);
+ int type = variant.userType();
+ if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar))
+ return *reinterpret_cast<QObject* const *>(variant.constData());
+ }
+ return 0;
+}
+
+
+QVariant QV8Engine::variantValue(v8::Handle<v8::Value> value)
+{
+ Q_ASSERT(isVariant(value));
+ return QV8Engine::toVariant(value, -1 /*whateever magic hint is*/);
+}
+
+// Creates a QVariant wrapper object.
+v8::Handle<v8::Object> QV8Engine::newVariant(const QVariant &value)
+{
+ v8::Handle<v8::Object> instance = variantWrapper()->newVariant(value);
+ return instance;
+}
+
+QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch)
+{
+ v8::HandleScope handleScope;
+
+ clearExceptions();
+ if (script.IsEmpty()) {
+ v8::Handle<v8::Value> exception = tryCatch.Exception();
+ if (exception.IsEmpty()) {
+ // This is possible on syntax errors like { a:12, b:21 } <- missing "(", ")" around expression.
+ return InvalidValue();
+ }
+ setException(exception, tryCatch.Message());
+ return new QJSValuePrivate(this, exception);
+ }
+ v8::Handle<v8::Value> result;
+ result = script->Run();
+ if (result.IsEmpty()) {
+ v8::Handle<v8::Value> exception = tryCatch.Exception();
+ // TODO: figure out why v8 doesn't always produce an exception value
+ //Q_ASSERT(!exception.IsEmpty());
+ if (exception.IsEmpty())
+ exception = v8::Exception::Error(v8::String::New("missing exception value"));
+ setException(exception, tryCatch.Message());
+ return new QJSValuePrivate(this, exception);
+ }
+ return new QJSValuePrivate(this, result);
+}
+
+QJSValue QV8Engine::scriptValueFromInternal(v8::Handle<v8::Value> value) const
+{
+ if (value.IsEmpty())
+ return QJSValuePrivate::get(InvalidValue());
+ return QJSValuePrivate::get(new QJSValuePrivate(const_cast<QV8Engine*>(this), value));
+}
+
+QScriptPassPointer<QJSValuePrivate> QV8Engine::newArray(uint length)
+{
+ return new QJSValuePrivate(this, v8::Array::New(length));
+}
+
+void QV8Engine::emitSignalHandlerException()
+{
+ emit q->signalHandlerException(scriptValueFromInternal(uncaughtException()));
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8engine_impl_p.h b/src/declarative/qml/v8/qv8engine_impl_p.h
new file mode 100644
index 0000000000..5c56efdf39
--- /dev/null
+++ b/src/declarative/qml/v8/qv8engine_impl_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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 QtDeclarative 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 QV8ENGINE_IMPL_P_H
+#define QV8ENGINE_IMPL_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 "qv8engine_p.h"
+#include "qjsvalue_p.h"
+#include "qjsconverter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(bool value)
+{
+ return value ? v8::True() : v8::False();
+}
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(int value)
+{
+ return v8::Integer::New(value);
+}
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(uint value)
+{
+ return v8::Integer::NewFromUnsigned(value);
+}
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(double value)
+{
+ return v8::Number::New(value);
+}
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(QJSValue::SpecialValue value) {
+ if (value == QJSValue::NullValue)
+ return v8::Null();
+ return v8::Undefined();
+}
+
+inline v8::Handle<v8::Value> QV8Engine::makeJSValue(const QString& value)
+{
+ return QJSConverter::toString(value);
+}
+
+class QtScriptBagCleaner
+{
+public:
+ template<class T>
+ void operator () (T* value) const
+ {
+ value->reinitialize();
+ }
+};
+
+inline void QV8Engine::registerValue(QJSValuePrivate *data)
+{
+ m_values.insert(data);
+}
+
+inline void QV8Engine::unregisterValue(QJSValuePrivate *data)
+{
+ m_values.remove(data);
+}
+
+inline void QV8Engine::invalidateAllValues()
+{
+ QtScriptBagCleaner invalidator;
+ m_values.forEach(invalidator);
+ m_values.clear();
+}
+
+/*!
+ \internal
+ \note property can be index (v8::Integer) or a property (v8::String) name, according to ECMA script
+ property would be converted to a string.
+*/
+inline QJSValue::PropertyFlags QV8Engine::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
+{
+ QJSValue::PropertyFlags flags = m_originalGlobalObject.getPropertyFlags(object, property);
+ return flags;
+}
+
+QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(const QString& program, const QString& fileName, int lineNumber)
+{
+ v8::TryCatch tryCatch;
+ v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1));
+ v8::Handle<v8::Script> script;
+ script = v8::Script::Compile(QJSConverter::toString(program), &scriptOrigin);
+ if (script.IsEmpty()) {
+ // TODO: Why don't we get the exception, as with Script::Compile()?
+ // Q_ASSERT(tryCatch.HasCaught());
+ v8::Handle<v8::Value> error = v8::Exception::SyntaxError(v8::String::New(""));
+ setException(error);
+ return new QJSValuePrivate(this, error);
+ }
+ return evaluate(script, tryCatch);
+}
+
+QT_END_NAMESPACE
+
+#endif // QV8ENGINE_IMPL_P_H
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
index 340945c6ee..b95e55002b 100644
--- a/src/declarative/qml/v8/qv8engine_p.h
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -57,7 +57,14 @@
#include <QtCore/qvariant.h>
#include <QtCore/qset.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qstringlist.h>
+
#include <private/qv8_p.h>
+#include <qjsengine.h>
+#include <qjsvalue.h>
+#include "qscriptoriginalglobalobject_p.h"
+#include "qscripttools_p.h"
#include <private/qdeclarativepropertycache_p.h>
@@ -210,18 +217,49 @@ class QDeclarativeContextData;
class Q_DECLARATIVE_EXPORT QV8Engine
{
public:
- QV8Engine();
+ static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
+ static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
+
+ QV8Engine(QJSEngine* qq,QJSEngine::ContextOwnership ownership = QJSEngine::CreateNewContext);
~QV8Engine();
struct Deletable {
virtual ~Deletable() {}
};
- void init(QDeclarativeEngine *);
+ class Exception
+ {
+ typedef QPair<v8::Persistent<v8::Value>, v8::Persistent<v8::Message> > ValueMessagePair;
+
+ v8::Persistent<v8::Value> m_value;
+ v8::Persistent<v8::Message> m_message;
+ QStack<ValueMessagePair> m_stack;
+
+ Q_DISABLE_COPY(Exception)
+ public:
+ inline Exception();
+ inline ~Exception();
+ inline void set(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message);
+ inline void clear();
+ inline operator bool() const;
+ inline operator v8::Handle<v8::Value>() const;
+ inline int lineNumber() const;
+ inline QStringList backtrace() const;
+
+ inline void push();
+ inline void pop();
+ };
+ void initDeclarativeGlobalObject();
+ void setEngine(QDeclarativeEngine *engine);
QDeclarativeEngine *engine() { return m_engine; }
v8::Local<v8::Object> global() { return m_context->Global(); }
- v8::Handle<v8::Context> context() { return m_context; }
+ v8::Handle<v8::Context> context() const { return m_context; }
+
+ inline void registerValue(QJSValuePrivate *data);
+ inline void unregisterValue(QJSValuePrivate *data);
+ inline void invalidateAllValues();
+
QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
@@ -237,6 +275,7 @@ public:
QDeclarativeContextData *callingContext();
v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
+ inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
void freezeObject(v8::Handle<v8::Value>);
inline QString toString(v8::Handle<v8::Value> string);
@@ -257,6 +296,9 @@ public:
// Return the QML global "scope" object for the \a ctxt context and \a scope object.
inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
+ QScriptPassPointer<QJSValuePrivate> newRegExp(const QRegExp &regexp);
+ QScriptPassPointer<QJSValuePrivate> newRegExp(const QString &pattern, const QString &flags);
+
// Return a JS wrapper for the given QObject \a object
inline v8::Handle<v8::Value> newQObject(QObject *object);
inline bool isQObject(v8::Handle<v8::Value>);
@@ -281,8 +323,19 @@ public:
// Return the list of illegal id names (the names of the properties on the global object)
const QSet<QString> &illegalNames() const;
+ inline void collectGarbage() { gc(); }
static void gc();
+ void clearExceptions();
+ void setException(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message = v8::Handle<v8::Message>());
+ v8::Handle<v8::Value> throwException(v8::Handle<v8::Value> value);
+ bool hasUncaughtException() const;
+ int uncaughtExceptionLineNumber() const;
+ QStringList uncaughtExceptionBacktrace() const;
+ v8::Handle<v8::Value> uncaughtException() const;
+ void saveException();
+ void restoreException();
+
#ifdef QML_GLOBAL_HANDLE_DEBUGGING
// Used for handle debugging
static void registerHandle(void *);
@@ -295,9 +348,50 @@ public:
inline Deletable *extensionData(int) const;
void setExtensionData(int, Deletable *);
-private:
+ inline v8::Handle<v8::Value> makeJSValue(bool value);
+ inline v8::Handle<v8::Value> makeJSValue(int value);
+ inline v8::Handle<v8::Value> makeJSValue(uint value);
+ inline v8::Handle<v8::Value> makeJSValue(double value);
+ inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
+ inline v8::Handle<v8::Value> makeJSValue(const QString& value);
+
+ inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+ QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
+
+ QScriptPassPointer<QJSValuePrivate> newArray(uint length);
+ v8::Handle<v8::Object> newVariant(const QVariant &variant);
+ QScriptPassPointer<QJSValuePrivate> newVariant(QJSValuePrivate* value, const QVariant &variant);
+
+ v8::Handle<v8::Array> variantListToJS(const QVariantList &lst);
+ QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray);
+
+ v8::Handle<v8::Object> variantMapToJS(const QVariantMap &vmap);
+ QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject);
+
+ v8::Handle<v8::Value> variantToJS(const QVariant &value);
+ QVariant variantFromJS(v8::Handle<v8::Value> value);
+
+ v8::Handle<v8::Value> metaTypeToJS(int type, const void *data);
+ bool metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data);
+
+ bool convertToNativeQObject(v8::Handle<v8::Value> value,
+ const QByteArray &targetType,
+ void **result);
+
+ QVariant variantValue(v8::Handle<v8::Value> value);
+
+ QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const;
+
+ void emitSignalHandlerException();
+
+ QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
+ QSet<int> visitedConversionObjects;
+protected:
+ QJSEngine* q;
QDeclarativeEngine *m_engine;
+ bool m_ownsV8Context;
v8::Persistent<v8::Context> m_context;
+ QScriptOriginalGlobalObject m_originalGlobalObject;
QV8StringWrapper m_stringWrapper;
QV8ContextWrapper m_contextWrapper;
@@ -318,6 +412,8 @@ private:
QSet<QString> m_illegalNames;
+ Exception m_exception;
+
QVariant toBasicVariant(v8::Handle<v8::Value>);
void initializeGlobal(v8::Handle<v8::Object>);
@@ -356,6 +452,10 @@ private:
double qtDateTimeToJsDate(const QDateTime &dt);
QDateTime qtDateTimeFromJsDate(double jsDate);
+private:
+ QScriptBagContainer<QJSValuePrivate> m_values;
+
+ Q_DISABLE_COPY(QV8Engine)
};
// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated
diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp
index e2161a9001..71937d0aad 100644
--- a/src/declarative/qml/v8/qv8include.cpp
+++ b/src/declarative/qml/v8/qv8include.cpp
@@ -41,7 +41,7 @@
#include "qv8include_p.h"
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
#include <QtCore/qfile.h>
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
index cc0380e684..f97f427ede 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -48,15 +48,17 @@
#include <private/qdeclarativeengine_p.h>
#include <private/qdeclarativevmemetaobject_p.h>
#include <private/qdeclarativebinding_p.h>
+#include <private/qjsvalue_p.h>
+#include <private/qscript_impl_p.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
QT_BEGIN_NAMESPACE
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QJSValue);
Q_DECLARE_METATYPE(QDeclarativeV8Handle);
#if defined(__GNUC__)
@@ -137,7 +139,7 @@ private:
QString *qstringPtr;
QVariant *qvariantPtr;
QList<QObject *> *qlistPtr;
- QScriptValue *qscriptValuePtr;
+ QJSValue *qjsValuePtr;
QDeclarativeV8Handle *handlePtr;
};
@@ -691,7 +693,9 @@ v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info
QStringList result;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine());
+ QDeclarativeEnginePrivate *ep = resource->engine->engine()
+ ? QDeclarativeEnginePrivate::get(resource->engine->engine())
+ : 0;
QDeclarativePropertyCache *cache = 0;
QDeclarativeData *ddata = QDeclarativeData::get(object);
@@ -699,7 +703,7 @@ v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info
cache = ddata->propertyCache;
if (!cache) {
- cache = ep->cache(object);
+ cache = ep ? ep->cache(object) : 0;
if (cache) {
if (ddata) { cache->addref(); ddata->propertyCache = cache; }
} else {
@@ -1837,8 +1841,8 @@ void MetaCallArgument::cleanup()
qstringPtr->~QString();
} else if (type == -1 || type == QMetaType::QVariant) {
qvariantPtr->~QVariant();
- } else if (type == qMetaTypeId<QScriptValue>()) {
- qscriptValuePtr->~QScriptValue();
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr->~QJSValue();
} else if (type == qMetaTypeId<QList<QObject *> >()) {
qlistPtr->~QList<QObject *>();
}
@@ -1857,8 +1861,8 @@ void MetaCallArgument::initAsType(int callType)
if (type != 0) { cleanup(); type = 0; }
if (callType == 0) return;
- if (callType == qMetaTypeId<QScriptValue>()) {
- qscriptValuePtr = new (&allocData) QScriptValue();
+ if (callType == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr = new (&allocData) QJSValue();
type = callType;
} else if (callType == QMetaType::Int ||
callType == QMetaType::UInt ||
@@ -1891,9 +1895,9 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
{
if (type != 0) { cleanup(); type = 0; }
- if (callType == qMetaTypeId<QScriptValue>()) {
- qscriptValuePtr = new (&allocData) QScriptValue();
- type = qMetaTypeId<QScriptValue>();
+ if (callType == qMetaTypeId<QJSValue>()) {
+ qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value)));
+ type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value->Int32Value());
type = callType;
@@ -1939,7 +1943,7 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
qvariantPtr = new (&allocData) QVariant();
type = -1;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QDeclarativeEnginePrivate *ep = engine->engine() ? QDeclarativeEnginePrivate::get(engine->engine()) : 0;
QVariant v = engine->toVariant(value, -1);
if (v.userType() == callType) {
@@ -1947,7 +1951,7 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
} else if (v.canConvert((QVariant::Type)callType)) {
*qvariantPtr = v;
qvariantPtr->convert((QVariant::Type)callType);
- } else if (const QMetaObject *mo = ep->rawMetaObjectForType(callType)) {
+ } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) {
QObject *obj = ep->toQObject(v);
if (obj) {
@@ -1965,8 +1969,8 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
{
- if (type == qMetaTypeId<QScriptValue>()) {
- return v8::Undefined();
+ if (type == qMetaTypeId<QJSValue>()) {
+ return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
} else if (type == QMetaType::Int) {
return v8::Integer::New(int(intValue));
} else if (type == QMetaType::UInt) {
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
index 39d03dbeea..fe30670fc2 100644
--- a/src/declarative/qml/v8/qv8typewrapper.cpp
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -173,10 +173,12 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
return v8engine->typeWrapper()->newObject(object, d->type, resource->mode);
} else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) {
- // XXX TODO: Currently module APIs are implemented against QScriptValues. Consequently we
- // can't do anything for script module apis here until the QtScript/V8 binding is complete.
- if (moduleApi->qobjectCallback) {
- moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), 0);
+ if (moduleApi->scriptCallback) {
+ moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
+ moduleApi->scriptCallback = 0;
+ moduleApi->qobjectCallback = 0;
+ } else if (moduleApi->qobjectCallback) {
+ moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine());
moduleApi->scriptCallback = 0;
moduleApi->qobjectCallback = 0;
}
@@ -225,10 +227,12 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
QV8QObjectWrapper::IgnoreRevision);
} else if (resource->typeNamespace) {
if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi()) {
- // XXX TODO: Currently module APIs are implemented against QScriptValues. Consequently we
- // can't do anything for script module apis here until the QtScript/V8 binding is complete.
- if (moduleApi->qobjectCallback) {
- moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), 0);
+ if (moduleApi->scriptCallback) {
+ moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
+ moduleApi->scriptCallback = 0;
+ moduleApi->qobjectCallback = 0;
+ } else if (moduleApi->qobjectCallback) {
+ moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine());
moduleApi->scriptCallback = 0;
moduleApi->qobjectCallback = 0;
}
diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp
index a5602fbbad..d4097d7f74 100644
--- a/src/declarative/qml/v8/qv8variantwrapper.cpp
+++ b/src/declarative/qml/v8/qv8variantwrapper.cpp
@@ -71,6 +71,7 @@ void QV8VariantWrapper::init(QV8Engine *engine)
{
m_engine = engine;
m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction());
+ m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction());
{
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
@@ -80,6 +81,9 @@ void QV8VariantWrapper::init(QV8Engine *engine)
ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
m_toString, v8::DEFAULT,
v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
+ m_valueOf, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
}
{
@@ -98,6 +102,9 @@ void QV8VariantWrapper::init(QV8Engine *engine)
ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
m_toString, v8::DEFAULT,
v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
+ m_valueOf, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
m_scarceConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
}
@@ -105,6 +112,7 @@ void QV8VariantWrapper::init(QV8Engine *engine)
void QV8VariantWrapper::destroy()
{
+ qPersistentDispose(m_valueOf);
qPersistentDispose(m_toString);
qPersistentDispose(m_destroy);
qPersistentDispose(m_preserve);
@@ -185,6 +193,13 @@ v8::Handle<v8::Value> QV8VariantWrapper::ToStringGetter(v8::Local<v8::String> pr
return info.Data();
}
+v8::Handle<v8::Value> QV8VariantWrapper::ValueOfGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
v8::Handle<v8::Value> QV8VariantWrapper::Preserve(const v8::Arguments &args)
{
QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
@@ -217,4 +232,27 @@ v8::Handle<v8::Value> QV8VariantWrapper::ToString(const v8::Arguments &args)
}
}
+v8::Handle<v8::Value> QV8VariantWrapper::ValueOf(const v8::Arguments &args)
+{
+ QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
+ if (resource) {
+ QVariant v = resource->data;
+ switch (v.type()) {
+ case QVariant::Invalid:
+ return v8::Undefined();
+ case QVariant::String:
+ return resource->engine->toString(v.toString());
+ case QVariant::Int:
+ case QVariant::Double:
+ case QVariant::UInt:
+ return v8::Number::New(v.toDouble());
+ case QVariant::Bool:
+ return v8::Boolean::New(v.toBool());
+ default:
+ break;
+ }
+ }
+ return args.This();
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8variantwrapper_p.h b/src/declarative/qml/v8/qv8variantwrapper_p.h
index 9e165f37f4..de74bc9e12 100644
--- a/src/declarative/qml/v8/qv8variantwrapper_p.h
+++ b/src/declarative/qml/v8/qv8variantwrapper_p.h
@@ -87,9 +87,12 @@ private:
const v8::AccessorInfo &info);
static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property,
const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> ValueOfGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
static v8::Handle<v8::Value> Preserve(const v8::Arguments &args);
static v8::Handle<v8::Value> Destroy(const v8::Arguments &args);
static v8::Handle<v8::Value> ToString(const v8::Arguments &args);
+ static v8::Handle<v8::Value> ValueOf(const v8::Arguments &args);
QV8Engine *m_engine;
v8::Persistent<v8::Function> m_constructor;
@@ -97,6 +100,7 @@ private:
v8::Persistent<v8::Function> m_preserve;
v8::Persistent<v8::Function> m_destroy;
v8::Persistent<v8::Function> m_toString;
+ v8::Persistent<v8::Function> m_valueOf;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/script.pri b/src/declarative/qml/v8/script.pri
new file mode 100644
index 0000000000..04a23d1f2b
--- /dev/null
+++ b/src/declarative/qml/v8/script.pri
@@ -0,0 +1,20 @@
+
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qjsengine.cpp \
+ $$PWD/qjsvalue.cpp \
+ $$PWD/qjsvalueiterator.cpp \
+
+HEADERS += \
+ $$PWD/qjsengine.h \
+ $$PWD/qjsvalue.h \
+ $$PWD/qjsvalue_p.h \
+ $$PWD/qjsvalueiterator.h \
+ $$PWD/qjsvalue_impl_p.h \
+ $$PWD/qjsconverter_p.h \
+ $$PWD/qscriptisolate_p.h \
+ $$PWD/qscriptshareddata_p.h \
+ $$PWD/qscripttools_p.h \
+ $$PWD/qscript_impl_p.h \
+ $$PWD/qscriptoriginalglobalobject_p.h
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
index 61e0184884..97b3d679df 100644
--- a/src/declarative/qml/v8/v8.pri
+++ b/src/declarative/qml/v8/v8.pri
@@ -1,6 +1,8 @@
INCLUDEPATH += $$PWD/../../../3rdparty/javascriptcore
INCLUDEPATH += $$PWD
+include(script.pri)
+
HEADERS += \
$$PWD/qv8_p.h \
$$PWD/qv8stringwrapper_p.h \
@@ -16,6 +18,7 @@ HEADERS += \
$$PWD/qv8worker_p.h \
$$PWD/qv8bindings_p.h \
$$PWD/../../../3rdparty/javascriptcore/DateMath.h \
+ $$PWD/qv8engine_impl_p.h
SOURCES += \
$$PWD/qv8stringwrapper.cpp \
@@ -31,4 +34,3 @@ SOURCES += \
$$PWD/qv8worker.cpp \
$$PWD/qv8bindings.cpp \
$$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
-
diff --git a/src/declarative/util/qdeclarativebind.cpp b/src/declarative/util/qdeclarativebind.cpp
index 6038aca8d5..726adf96d4 100644
--- a/src/declarative/util/qdeclarativebind.cpp
+++ b/src/declarative/util/qdeclarativebind.cpp
@@ -52,9 +52,8 @@
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsvalue.h>
+#include <QtDeclarative/qjsengine.h>
#include <private/qobject_p.h>
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index d1496fc886..035502140b 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -485,7 +485,7 @@ ModelObject *ModelNode::object(const NestedListModel *model)
{
if (!objectCache) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(qmlEngine(model->m_listModel));
- objectCache = new ModelObject(this, const_cast<NestedListModel*>(model), &ep->v8engine);
+ objectCache = new ModelObject(this, const_cast<NestedListModel*>(model), ep->v8engine());
QHash<QString, ModelNode *>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
@@ -1451,7 +1451,7 @@ v8::Handle<v8::Value> NestedListModel::get(int index) const
if (!node)
return v8::Undefined();;
- return QDeclarativeEnginePrivate::get(eng)->v8engine.newQObject(node->object(this));
+ return QDeclarativeEnginePrivate::get(eng)->v8engine()->newQObject(node->object(this));
}
void NestedListModel::set(int index, v8::Handle<v8::Value> valuemap, QList<int> *roles)
diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro
index e55a5b2a29..31192fd764 100644
--- a/src/imports/folderlistmodel/folderlistmodel.pro
+++ b/src/imports/folderlistmodel/folderlistmodel.pro
@@ -2,7 +2,7 @@ TARGET = qmlfolderlistmodelplugin
TARGETPATH = Qt/labs/folderlistmodel
include(../qimportbase.pri)
-QT += declarative script
+QT += declarative
SOURCES += qdeclarativefolderlistmodel.cpp plugin.cpp
HEADERS += qdeclarativefolderlistmodel.h
diff --git a/src/imports/gestures/gestures.pro b/src/imports/gestures/gestures.pro
index 5c009dde51..d94b402f4c 100644
--- a/src/imports/gestures/gestures.pro
+++ b/src/imports/gestures/gestures.pro
@@ -2,7 +2,7 @@ TARGET = qmlgesturesplugin
TARGETPATH = Qt/labs/gestures
include(../qimportbase.pri)
-QT += core-private gui-private declarative-private script-private qtquick1 qtquick1-private
+QT += core-private gui-private declarative-private qtquick1 qtquick1-private
SOURCES += qdeclarativegesturearea.cpp plugin.cpp
HEADERS += qdeclarativegesturearea_p.h
diff --git a/src/imports/inputcontext/inputcontext.pro b/src/imports/inputcontext/inputcontext.pro
index 9c7ddf4e8b..cbad82c5b1 100755
--- a/src/imports/inputcontext/inputcontext.pro
+++ b/src/imports/inputcontext/inputcontext.pro
@@ -2,7 +2,7 @@ TARGET = qmlinputcontextplugin
TARGETPATH = Qt/labs/inputcontext
include(../qimportbase.pri)
-QT += declarative script
+QT += declarative
SOURCES += \
declarativeinputcontext.cpp \
diff --git a/src/imports/inputcontext/plugin.cpp b/src/imports/inputcontext/plugin.cpp
index 36de469f1f..5ce9e5b475 100644
--- a/src/imports/inputcontext/plugin.cpp
+++ b/src/imports/inputcontext/plugin.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-static QObject *createContext(QDeclarativeEngine *, QScriptEngine *)
+static QObject *createContext(QDeclarativeEngine *, QJSEngine *)
{
return new InputContextModule;
}
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index 5781b3ddf1..db0a029a9a 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -41,10 +41,8 @@
#include <QtDeclarative/qdeclarativeextensionplugin.h>
#include <QtDeclarative/qdeclarative.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptcontextinfo.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsvalue.h>
+#include <QtDeclarative/qjsengine.h>
#include "QtQuickTest/private/quicktestresult_p.h"
#include "QtQuickTest/private/quicktestevent_p.h"
#include "private/qtestoptions_p.h"
diff --git a/src/imports/testlib/testlib.pro b/src/imports/testlib/testlib.pro
index 9980a7551f..5adde2ae85 100644
--- a/src/imports/testlib/testlib.pro
+++ b/src/imports/testlib/testlib.pro
@@ -21,7 +21,7 @@ symbian {
}
-QT += declarative script qmltest qmltest-private declarative-private script-private core-private testlib
+QT += declarative qmltest qmltest-private declarative-private core-private testlib
SOURCES += main.cpp
HEADERS +=
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 6e79be0b09..418136aa0a 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -7,7 +7,7 @@ CONFIG += module
CONFIG += dll warn_on
MODULE_PRI += ../../modules/qt_qmltest.pri
-QT += testlib-private declarative script testlib qtquick1
+QT += testlib-private declarative testlib qtquick1
DEFINES += QT_BUILD_QUICK_TEST_LIB QT_NO_URL_CAST_FROM_STRING
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index a2c494513b..3f0c5325ed 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -52,9 +52,8 @@
#include <QtDeclarative/qsgview.h>
#define QUICK_TEST_SCENEGRAPH 1
#endif
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsvalue.h>
+#include <QtDeclarative/qjsengine.h>
#include <QtOpenGL/qgl.h>
#include <QtCore/qurl.h>
#include <QtCore/qfileinfo.h>
@@ -73,7 +72,7 @@ QT_BEGIN_NAMESPACE
class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper
{
public:
- static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine);
+ static QJSEngine *getScriptEngine(QDeclarativeEngine *engine);
static void setAnimationSlowDownFactor(qreal factor);
static void enableDebugging();
};
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
index d2bfc578dd..494ed46ad5 100644
--- a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
@@ -59,7 +59,7 @@
#include <QEvent>
#include <QGraphicsSceneMouseEvent>
#include <QtCore/qnumeric.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
#include <QtGui/qgraphicstransform.h>
#include <private/qv8engine_p.h>
diff --git a/src/qtquick1/qtquick1.pro b/src/qtquick1/qtquick1.pro
index e3dd0298cd..7fc670f801 100644
--- a/src/qtquick1/qtquick1.pro
+++ b/src/qtquick1/qtquick1.pro
@@ -7,7 +7,7 @@ CONFIG += module
CONFIG += dll warn_on
MODULE_PRI += ../../modules/qt_qtquick1.pri
-QT += testlib-private declarative script testlib declarative-private core-private gui-private script-private network
+QT += testlib-private declarative testlib declarative-private core-private gui-private network
DEFINES += QT_NO_URL_CAST_FROM_STRING
load(qt_module_config)
diff --git a/src/qtquick1/util/qdeclarativebind.cpp b/src/qtquick1/util/qdeclarativebind.cpp
index f6463be05d..50514234a3 100644
--- a/src/qtquick1/util/qdeclarativebind.cpp
+++ b/src/qtquick1/util/qdeclarativebind.cpp
@@ -49,9 +49,8 @@
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsvalue.h>
+#include <QtDeclarative/qjsengine.h>
#include <private/qobject_p.h>
diff --git a/src/qtquick1/util/qdeclarativelistmodel.cpp b/src/qtquick1/util/qdeclarativelistmodel.cpp
index 5d60ed9658..520d9ac388 100644
--- a/src/qtquick1/util/qdeclarativelistmodel.cpp
+++ b/src/qtquick1/util/qdeclarativelistmodel.cpp
@@ -52,7 +52,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qstack.h>
#include <QXmlStreamReader>
-#include <QtScript/qscriptvalueiterator.h>
+#include <QtDeclarative/qscriptvalueiterator.h>
Q_DECLARE_METATYPE(QListModelInterface *)
diff --git a/src/qtquick1/util/qdeclarativelistmodel_p.h b/src/qtquick1/util/qdeclarativelistmodel_p.h
index 21398f7213..1be5e6001a 100644
--- a/src/qtquick1/util/qdeclarativelistmodel_p.h
+++ b/src/qtquick1/util/qdeclarativelistmodel_p.h
@@ -51,7 +51,7 @@
#include <QtCore/QList>
#include <QtCore/QVariant>
#include <QtQuick1/private/qlistmodelinterface_p.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
QT_BEGIN_HEADER
diff --git a/src/qtquick1/util/qdeclarativelistmodel_p_p.h b/src/qtquick1/util/qdeclarativelistmodel_p_p.h
index e34f6d850d..ee39ba45b1 100644
--- a/src/qtquick1/util/qdeclarativelistmodel_p_p.h
+++ b/src/qtquick1/util/qdeclarativelistmodel_p_p.h
@@ -58,7 +58,7 @@
#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
#include <QtDeclarative/qdeclarative.h>
-#include <QtScript/private/qscriptdeclarativeclass_p.h>
+#include <QtDeclarative/private/qscriptdeclarativeclass_p.h>
QT_BEGIN_HEADER
diff --git a/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h b/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h
index f0979c4b31..a769185607 100644
--- a/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h
+++ b/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h
@@ -55,7 +55,7 @@
#include <QtDeclarative/qdeclarative.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qjsvalue.h>
#include <QtGui/qevent.h>
#include <QMutex>
#include <QWaitCondition>
diff --git a/src/qtquick1/util/qdeclarativeview.cpp b/src/qtquick1/util/qdeclarativeview.cpp
index 32f2183cad..d10d34fcd1 100644
--- a/src/qtquick1/util/qdeclarativeview.cpp
+++ b/src/qtquick1/util/qdeclarativeview.cpp
@@ -51,7 +51,6 @@
#include <QtDeclarative/private/qdeclarativedebugtrace_p.h>
#include <QtDeclarative/private/qdeclarativeinspectorservice_p.h>
-#include <qscriptvalueiterator.h>
#include <qdebug.h>
#include <qtimer.h>
#include <qevent.h>
diff --git a/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch b/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch
new file mode 100644
index 0000000000..6cd9294d31
--- /dev/null
+++ b/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch
@@ -0,0 +1,286 @@
+From 5719ba59309e85f3ca47da6b64df66e710f3016f Mon Sep 17 00:00:00 2001
+From: "ager@chromium.org" <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
+Date: Wed, 4 May 2011 13:03:08 +0000
+Subject: [PATCH] Add CallAsFunction method to the Object class in the API
+
+Patch by Peter Varga.
+
+BUG=v8:1336
+TEST=cctest/test-api/CallAsFunction
+
+Review URL: http://codereview.chromium.org/6883045
+
+git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
+---
+ include/v8.h | 8 +++
+ src/api.cc | 31 +++++++++++
+ src/execution.cc | 24 ++++++++
+ src/execution.h | 2 +
+ test/cctest/test-api.cc | 135 ++++++++++++++++++++++++++++++++++-------------
+ 5 files changed, 163 insertions(+), 37 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 4dcbf28..78ee7e6 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -1606,6 +1606,14 @@ class Object : public Value {
+ V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
+ V8EXPORT int GetIndexedPropertiesExternalArrayDataLength();
+
++ /**
++ * Call an Object as a function if a callback is set by the
++ * ObjectTemplate::SetCallAsFunctionHandler method.
++ */
++ V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv,
++ int argc,
++ Handle<Value> argv[]);
++
+ V8EXPORT static Local<Object> New();
+ static inline Object* Cast(Value* obj);
+ private:
+diff --git a/src/api.cc b/src/api.cc
+index 792e488..c72857d 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -3255,6 +3255,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
+ }
+
+
++Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
++ v8::Handle<v8::Value> argv[]) {
++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
++ ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
++ return Local<v8::Value>());
++ LOG_API(isolate, "Object::CallAsFunction");
++ ENTER_V8(isolate);
++ HandleScope scope;
++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
++ i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
++ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
++ i::Object*** args = reinterpret_cast<i::Object***>(argv);
++ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
++ if (obj->IsJSFunction()) {
++ fun = i::Handle<i::JSFunction>::cast(obj);
++ } else {
++ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> delegate =
++ i::Execution::TryGetFunctionDelegate(obj, &has_pending_exception);
++ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
++ fun = i::Handle<i::JSFunction>::cast(delegate);
++ recv_obj = obj;
++ }
++ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> returned =
++ i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
++ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
++ return scope.Close(Utils::ToLocal(returned));
++}
++
++
+ Local<v8::Object> Function::NewInstance() const {
+ return NewInstance(0, NULL);
+ }
+diff --git a/src/execution.cc b/src/execution.cc
+index eb26438..850dec5 100644
+--- a/src/execution.cc
++++ b/src/execution.cc
+@@ -234,6 +234,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
+ }
+
+
++Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
++ bool* has_pending_exception) {
++ ASSERT(!object->IsJSFunction());
++ Isolate* isolate = Isolate::Current();
++
++ // Objects created through the API can have an instance-call handler
++ // that should be used when calling the object as a function.
++ if (object->IsHeapObject() &&
++ HeapObject::cast(*object)->map()->has_instance_call_handler()) {
++ return Handle<JSFunction>(
++ isolate->global_context()->call_as_function_delegate());
++ }
++
++ // If the Object doesn't have an instance-call handler we should
++ // throw a non-callable exception.
++ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
++ "called_non_callable", i::HandleVector<i::Object>(&object, 1));
++ isolate->Throw(*error_obj);
++ *has_pending_exception = true;
++
++ return isolate->factory()->undefined_value();
++}
++
++
+ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
+ ASSERT(!object->IsJSFunction());
+ Isolate* isolate = Isolate::Current();
+diff --git a/src/execution.h b/src/execution.h
+index d4b80d2..e89d6ba 100644
+--- a/src/execution.h
++++ b/src/execution.h
+@@ -138,6 +138,8 @@ class Execution : public AllStatic {
+ // Get a function delegate (or undefined) for the given non-function
+ // object. Used for support calling objects as functions.
+ static Handle<Object> GetFunctionDelegate(Handle<Object> object);
++ static Handle<Object> TryGetFunctionDelegate(Handle<Object> object,
++ bool* has_pending_exception);
+
+ // Get a function delegate (or undefined) for the given non-function
+ // object. Used for support calling objects as constructors.
+diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
+index e2a7fb1..c6affe5 100644
+--- a/test/cctest/test-api.cc
++++ b/test/cctest/test-api.cc
+@@ -6962,50 +6962,111 @@ THREADED_TEST(CallAsFunction) {
+ v8::HandleScope scope;
+ LocalContext context;
+
+- Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+- Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+- instance_template->SetCallAsFunctionHandler(call_as_function);
+- Local<v8::Object> instance = t->GetFunction()->NewInstance();
+- context->Global()->Set(v8_str("obj"), instance);
+- v8::TryCatch try_catch;
+- Local<Value> value;
+- CHECK(!try_catch.HasCaught());
++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
++ Local<ObjectTemplate> instance_template = t->InstanceTemplate();
++ instance_template->SetCallAsFunctionHandler(call_as_function);
++ Local<v8::Object> instance = t->GetFunction()->NewInstance();
++ context->Global()->Set(v8_str("obj"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
+
+- value = CompileRun("obj(42)");
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(42, value->Int32Value());
++ value = CompileRun("obj(42)");
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(42, value->Int32Value());
+
+- value = CompileRun("(function(o){return o(49)})(obj)");
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(49, value->Int32Value());
++ value = CompileRun("(function(o){return o(49)})(obj)");
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(49, value->Int32Value());
+
+- // test special case of call as function
+- value = CompileRun("[obj]['0'](45)");
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(45, value->Int32Value());
++ // test special case of call as function
++ value = CompileRun("[obj]['0'](45)");
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(45, value->Int32Value());
+
+- value = CompileRun("obj.call = Function.prototype.call;"
+- "obj.call(null, 87)");
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(87, value->Int32Value());
++ value = CompileRun("obj.call = Function.prototype.call;"
++ "obj.call(null, 87)");
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(87, value->Int32Value());
+
+- // Regression tests for bug #1116356: Calling call through call/apply
+- // must work for non-function receivers.
+- const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
+- value = CompileRun(apply_99);
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(99, value->Int32Value());
++ // Regression tests for bug #1116356: Calling call through call/apply
++ // must work for non-function receivers.
++ const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
++ value = CompileRun(apply_99);
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(99, value->Int32Value());
+
+- const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
+- value = CompileRun(call_17);
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(17, value->Int32Value());
++ const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
++ value = CompileRun(call_17);
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(17, value->Int32Value());
+
+- // Check that the call-as-function handler can be called through
+- // new.
+- value = CompileRun("new obj(43)");
+- CHECK(!try_catch.HasCaught());
+- CHECK_EQ(-43, value->Int32Value());
++ // Check that the call-as-function handler can be called through
++ // new.
++ value = CompileRun("new obj(43)");
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(-43, value->Int32Value());
++
++ // Check that the call-as-function handler can be called through
++ // the API.
++ v8::Handle<Value> args[] = { v8_num(28) };
++ value = instance->CallAsFunction(instance, 1, args);
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(28, value->Int32Value());
++ }
++
++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
++ Local<ObjectTemplate> instance_template = t->InstanceTemplate();
++ Local<v8::Object> instance = t->GetFunction()->NewInstance();
++ context->Global()->Set(v8_str("obj2"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ // Call an object without call-as-function handler through the JS
++ value = CompileRun("obj2(28)");
++ CHECK(value.IsEmpty());
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value1(try_catch.Exception());
++ CHECK_EQ(*exception_value1,
++ "TypeError: Property 'obj2' of object "
++ "#<Object> is not a function");
++ try_catch.Reset();
++
++ // Call an object without call-as-function handler through the API
++ value = CompileRun("obj2(28)");
++ v8::Handle<Value> args[] = { v8_num(28) };
++ value = instance->CallAsFunction(instance, 1, args);
++ CHECK(value.IsEmpty());
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value2(try_catch.Exception());
++ CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function");
++ try_catch.Reset();
++ }
++
++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
++ Local<ObjectTemplate> instance_template = t->InstanceTemplate();
++ instance_template->SetCallAsFunctionHandler(ThrowValue);
++ Local<v8::Object> instance = t->GetFunction()->NewInstance();
++ context->Global()->Set(v8_str("obj3"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ // Catch the exception which is thrown by call-as-function handler
++ value = CompileRun("obj3(22)");
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value1(try_catch.Exception());
++ CHECK_EQ(*exception_value1, "22");
++ try_catch.Reset();
++
++ v8::Handle<Value> args[] = { v8_num(23) };
++ value = instance->CallAsFunction(instance, 1, args);
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value2(try_catch.Exception());
++ CHECK_EQ(*exception_value2, "23");
++ try_catch.Reset();
++ }
+ }
+
+
+--
+1.7.5.4
+
diff --git a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch
new file mode 100644
index 0000000000..7d90f0dfbd
--- /dev/null
+++ b/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch
@@ -0,0 +1,397 @@
+From fd2cc52576e8c89f3dffc2b4b5a9cc9c48a96f32 Mon Sep 17 00:00:00 2001
+From: "ager@chromium.org" <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
+Date: Fri, 6 May 2011 11:07:52 +0000
+Subject: [PATCH] Implement CallAsConstructor method for Object in the API
+
+Patch by Peter Varga.
+
+BUG=v8:1348
+TEST=cctest/test-api/ConstructorForObject
+
+Review URL: http://codereview.chromium.org/6902108
+
+git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7803 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
+---
+ include/v8.h | 8 ++
+ src/api.cc | 41 +++++++++-
+ src/execution.cc | 28 +++++++
+ src/execution.h | 2 +
+ test/cctest/test-api.cc | 205 +++++++++++++++++++++++++++++++++++++++++++++--
+ 5 files changed, 276 insertions(+), 8 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 4921823..5fc8059 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -1614,6 +1614,14 @@ class Object : public Value {
+ int argc,
+ Handle<Value> argv[]);
+
++ /**
++ * Call an Object as a consturctor if a callback is set by the
++ * ObjectTemplate::SetCallAsFunctionHandler method.
++ * Note: This method behaves like the Function::NewInstance method.
++ */
++ V8EXPORT Local<Value> CallAsConstructor(int argc,
++ Handle<Value> argv[]);
++
+ V8EXPORT static Local<Object> New();
+ static inline Object* Cast(Value* obj);
+ private:
+diff --git a/src/api.cc b/src/api.cc
+index c5c66a7..9194641 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -3262,7 +3262,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
+ return Local<v8::Value>());
+ LOG_API(isolate, "Object::CallAsFunction");
+ ENTER_V8(isolate);
+- HandleScope scope;
++ i::HandleScope scope(isolate);
+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+ i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+@@ -3282,7 +3282,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
+ i::Handle<i::Object> returned =
+ i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+- return scope.Close(Utils::ToLocal(returned));
++ return Utils::ToLocal(scope.CloseAndEscape(returned));
++}
++
++
++Local<v8::Value> Object::CallAsConstructor(int argc,
++ v8::Handle<v8::Value> argv[]) {
++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
++ ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
++ return Local<v8::Object>());
++ LOG_API(isolate, "Object::CallAsConstructor");
++ ENTER_V8(isolate);
++ i::HandleScope scope(isolate);
++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
++ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
++ i::Object*** args = reinterpret_cast<i::Object***>(argv);
++ if (obj->IsJSFunction()) {
++ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
++ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> returned =
++ i::Execution::New(fun, argc, args, &has_pending_exception);
++ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
++ return Utils::ToLocal(scope.CloseAndEscape(
++ i::Handle<i::JSObject>::cast(returned)));
++ }
++ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> delegate =
++ i::Execution::TryGetConstructorDelegate(obj, &has_pending_exception);
++ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
++ if (!delegate->IsUndefined()) {
++ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
++ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> returned =
++ i::Execution::Call(fun, obj, argc, args, &has_pending_exception);
++ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
++ ASSERT(!delegate->IsUndefined());
++ return Utils::ToLocal(scope.CloseAndEscape(returned));
++ }
++ return Local<v8::Object>();
+ }
+
+
+diff --git a/src/execution.cc b/src/execution.cc
+index 4ab3e78..db74492 100644
+--- a/src/execution.cc
++++ b/src/execution.cc
+@@ -277,6 +277,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
+ }
+
+
++Handle<Object> Execution::TryGetConstructorDelegate(
++ Handle<Object> object,
++ bool* has_pending_exception) {
++ ASSERT(!object->IsJSFunction());
++ Isolate* isolate = Isolate::Current();
++
++ // If you return a function from here, it will be called when an
++ // attempt is made to call the given object as a constructor.
++
++ // Objects created through the API can have an instance-call handler
++ // that should be used when calling the object as a function.
++ if (object->IsHeapObject() &&
++ HeapObject::cast(*object)->map()->has_instance_call_handler()) {
++ return Handle<JSFunction>(
++ isolate->global_context()->call_as_constructor_delegate());
++ }
++
++ // If the Object doesn't have an instance-call handler we should
++ // throw a non-callable exception.
++ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
++ "called_non_callable", i::HandleVector<i::Object>(&object, 1));
++ isolate->Throw(*error_obj);
++ *has_pending_exception = true;
++
++ return isolate->factory()->undefined_value();
++}
++
++
+ bool StackGuard::IsStackOverflow() {
+ ExecutionAccess access(isolate_);
+ return (thread_local_.jslimit_ != kInterruptLimit &&
+diff --git a/src/execution.h b/src/execution.h
+index 74189a2..7b6a48c 100644
+--- a/src/execution.h
++++ b/src/execution.h
+@@ -146,6 +146,8 @@ class Execution : public AllStatic {
+ // Get a function delegate (or undefined) for the given non-function
+ // object. Used for support calling objects as constructors.
+ static Handle<Object> GetConstructorDelegate(Handle<Object> object);
++ static Handle<Object> TryGetConstructorDelegate(Handle<Object> object,
++ bool* has_pending_exception);
+ };
+
+
+diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
+index 1bcc232..f48d5b4 100644
+--- a/test/cctest/test-api.cc
++++ b/test/cctest/test-api.cc
+@@ -6747,6 +6747,200 @@ THREADED_TEST(Constructor) {
+ CHECK(value->BooleanValue());
+ }
+
++
++static Handle<Value> ConstructorCallback(const Arguments& args) {
++ ApiTestFuzzer::Fuzz();
++ Local<Object> This;
++
++ if (args.IsConstructCall()) {
++ Local<Object> Holder = args.Holder();
++ This = Object::New();
++ Local<Value> proto = Holder->GetPrototype();
++ if (proto->IsObject()) {
++ This->SetPrototype(proto);
++ }
++ } else {
++ This = args.This();
++ }
++
++ This->Set(v8_str("a"), args[0]);
++ return This;
++}
++
++
++static Handle<Value> FakeConstructorCallback(const Arguments& args) {
++ ApiTestFuzzer::Fuzz();
++ return args[0];
++}
++
++
++THREADED_TEST(ConstructorForObject) {
++ v8::HandleScope handle_scope;
++ LocalContext context;
++
++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ instance_template->SetCallAsFunctionHandler(ConstructorCallback);
++ Local<Object> instance = instance_template->NewInstance();
++ context->Global()->Set(v8_str("obj"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ // Call the Object's constructor with a 32-bit signed integer.
++ value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsInt32());
++ CHECK_EQ(28, value->Int32Value());
++
++ Local<Value> args1[] = { v8_num(28) };
++ Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
++ CHECK(value_obj1->IsObject());
++ Local<Object> object1 = Local<Object>::Cast(value_obj1);
++ value = object1->Get(v8_str("a"));
++ CHECK(value->IsInt32());
++ CHECK(!try_catch.HasCaught());
++ CHECK_EQ(28, value->Int32Value());
++
++ // Call the Object's constructor with a String.
++ value = CompileRun(
++ "(function() { var o = new obj('tipli'); return o.a; })()");
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsString());
++ String::AsciiValue string_value1(value->ToString());
++ CHECK_EQ("tipli", *string_value1);
++
++ Local<Value> args2[] = { v8_str("tipli") };
++ Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
++ CHECK(value_obj2->IsObject());
++ Local<Object> object2 = Local<Object>::Cast(value_obj2);
++ value = object2->Get(v8_str("a"));
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsString());
++ String::AsciiValue string_value2(value->ToString());
++ CHECK_EQ("tipli", *string_value2);
++
++ // Call the Object's constructor with a Boolean.
++ value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsBoolean());
++ CHECK_EQ(true, value->BooleanValue());
++
++ Handle<Value> args3[] = { v8::Boolean::New(true) };
++ Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
++ CHECK(value_obj3->IsObject());
++ Local<Object> object3 = Local<Object>::Cast(value_obj3);
++ value = object3->Get(v8_str("a"));
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsBoolean());
++ CHECK_EQ(true, value->BooleanValue());
++
++ // Call the Object's constructor with undefined.
++ Handle<Value> args4[] = { v8::Undefined() };
++ Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
++ CHECK(value_obj4->IsObject());
++ Local<Object> object4 = Local<Object>::Cast(value_obj4);
++ value = object4->Get(v8_str("a"));
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsUndefined());
++
++ // Call the Object's constructor with null.
++ Handle<Value> args5[] = { v8::Null() };
++ Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
++ CHECK(value_obj5->IsObject());
++ Local<Object> object5 = Local<Object>::Cast(value_obj5);
++ value = object5->Get(v8_str("a"));
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsNull());
++ }
++
++ // Check exception handling when there is no constructor set for the Object.
++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ Local<Object> instance = instance_template->NewInstance();
++ context->Global()->Set(v8_str("obj2"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ value = CompileRun("new obj2(28)");
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value1(try_catch.Exception());
++ CHECK_EQ("TypeError: object is not a function", *exception_value1);
++ try_catch.Reset();
++
++ Local<Value> args[] = { v8_num(29) };
++ value = instance->CallAsConstructor(1, args);
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value2(try_catch.Exception());
++ CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
++ try_catch.Reset();
++ }
++
++ // Check the case when constructor throws exception.
++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ instance_template->SetCallAsFunctionHandler(ThrowValue);
++ Local<Object> instance = instance_template->NewInstance();
++ context->Global()->Set(v8_str("obj3"), instance);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ value = CompileRun("new obj3(22)");
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value1(try_catch.Exception());
++ CHECK_EQ("22", *exception_value1);
++ try_catch.Reset();
++
++ Local<Value> args[] = { v8_num(23) };
++ value = instance->CallAsConstructor(1, args);
++ CHECK(try_catch.HasCaught());
++ String::AsciiValue exception_value2(try_catch.Exception());
++ CHECK_EQ("23", *exception_value2);
++ try_catch.Reset();
++ }
++
++ // Check whether constructor returns with an object or non-object.
++ { Local<FunctionTemplate> function_template =
++ FunctionTemplate::New(FakeConstructorCallback);
++ Local<Function> function = function_template->GetFunction();
++ Local<Object> instance1 = function;
++ context->Global()->Set(v8_str("obj4"), instance1);
++ v8::TryCatch try_catch;
++ Local<Value> value;
++ CHECK(!try_catch.HasCaught());
++
++ CHECK(instance1->IsObject());
++ CHECK(instance1->IsFunction());
++
++ value = CompileRun("new obj4(28)");
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsObject());
++
++ Local<Value> args1[] = { v8_num(28) };
++ value = instance1->CallAsConstructor(1, args1);
++ CHECK(!try_catch.HasCaught());
++ CHECK(value->IsObject());
++
++ Local<ObjectTemplate> instance_template = ObjectTemplate::New();
++ instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
++ Local<Object> instance2 = instance_template->NewInstance();
++ context->Global()->Set(v8_str("obj5"), instance2);
++ CHECK(!try_catch.HasCaught());
++
++ CHECK(instance2->IsObject());
++ CHECK(!instance2->IsFunction());
++
++ value = CompileRun("new obj5(28)");
++ CHECK(!try_catch.HasCaught());
++ CHECK(!value->IsObject());
++
++ Local<Value> args2[] = { v8_num(28) };
++ value = instance2->CallAsConstructor(1, args2);
++ CHECK(!try_catch.HasCaught());
++ CHECK(!value->IsObject());
++ }
++}
++
++
+ THREADED_TEST(FunctionDescriptorException) {
+ v8::HandleScope handle_scope;
+ LocalContext context;
+@@ -7029,9 +7223,8 @@ THREADED_TEST(CallAsFunction) {
+ CHECK(value.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ String::AsciiValue exception_value1(try_catch.Exception());
+- CHECK_EQ(*exception_value1,
+- "TypeError: Property 'obj2' of object "
+- "#<Object> is not a function");
++ CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
++ *exception_value1);
+ try_catch.Reset();
+
+ // Call an object without call-as-function handler through the API
+@@ -7041,7 +7234,7 @@ THREADED_TEST(CallAsFunction) {
+ CHECK(value.IsEmpty());
+ CHECK(try_catch.HasCaught());
+ String::AsciiValue exception_value2(try_catch.Exception());
+- CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function");
++ CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
+ try_catch.Reset();
+ }
+
+@@ -7058,14 +7251,14 @@ THREADED_TEST(CallAsFunction) {
+ value = CompileRun("obj3(22)");
+ CHECK(try_catch.HasCaught());
+ String::AsciiValue exception_value1(try_catch.Exception());
+- CHECK_EQ(*exception_value1, "22");
++ CHECK_EQ("22", *exception_value1);
+ try_catch.Reset();
+
+ v8::Handle<Value> args[] = { v8_num(23) };
+ value = instance->CallAsFunction(instance, 1, args);
+ CHECK(try_catch.HasCaught());
+ String::AsciiValue exception_value2(try_catch.Exception());
+- CHECK_EQ(*exception_value2, "23");
++ CHECK_EQ("23", *exception_value2);
+ try_catch.Reset();
+ }
+ }
+--
+1.7.5.4
+
diff --git a/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch b/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch
new file mode 100644
index 0000000000..0558ce19f6
--- /dev/null
+++ b/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch
@@ -0,0 +1,63 @@
+From 859c452847317efe1131e337fcd51514de616ea2 Mon Sep 17 00:00:00 2001
+From: Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
+Date: Tue, 7 Dec 2010 11:56:42 +0100
+Subject: [PATCH] QtScript/V8: Add new v8 api to check if a value is an error.
+
+New function v8::Value::IsError was created.
+
+This API is experimental and added only for the purposes of our
+research.
+---
+ include/v8.h | 5 +++++
+ src/api.cc | 6 ++++++
+ src/heap.h | 1 +
+ 3 files changed, 12 insertions(+), 0 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 303cb7a..f992cb2 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -937,6 +937,11 @@ class Value : public Data {
+ */
+ V8EXPORT bool IsRegExp() const;
+
++ /**
++ * Returns true if this value is an Error.
++ */
++ V8EXPORT bool IsError() const;
++
+ V8EXPORT Local<Boolean> ToBoolean() const;
+ V8EXPORT Local<Number> ToNumber() const;
+ V8EXPORT Local<String> ToString() const;
+diff --git a/src/api.cc b/src/api.cc
+index fd4a76b..5ada246 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -2108,6 +2108,12 @@ bool Value::IsRegExp() const {
+ return obj->IsJSRegExp();
+ }
+
++bool Value::IsError() const {
++ if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsError()")) return false;
++ i::Handle<i::Object> obj = Utils::OpenHandle(this);
++ return obj->HasSpecificClassOf(HEAP->Error_symbol());
++}
++
+
+ Local<String> Value::ToString() const {
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+diff --git a/src/heap.h b/src/heap.h
+index 8cbf378..db90bb9 100644
+--- a/src/heap.h
++++ b/src/heap.h
+@@ -169,6 +169,7 @@ inline Heap* _inline_get_heap_();
+ V(string_symbol, "string") \
+ V(String_symbol, "String") \
+ V(Date_symbol, "Date") \
++ V(Error_symbol, "Error") \
+ V(this_symbol, "this") \
+ V(to_string_symbol, "toString") \
+ V(char_at_symbol, "CharAt") \
+--
+1.7.4.15.g7811d
+