aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2012-04-11 14:56:22 +0200
committerLars Knoll <lars.knoll@nokia.com>2012-04-11 16:05:03 +0200
commita896d4b39ec3d45ba708d9b36ea9c864b1df2136 (patch)
tree45cfe153cce6114c2c76c48dc0bdabde2a8cf3e3 /src/qml
parent24fb8dc27eddfdd62bd2c3a6e863cbf433762cd6 (diff)
parent65bfc35429e845cf6b76d58107360a1360a654fc (diff)
Merge remote-tracking branch 'origin/master' into api_changes
Conflicts: src/qml/debugger/qqmlprofilerservice_p.h src/qml/qml/qqmlboundsignal.cpp src/qml/qml/v4/qv4bindings.cpp src/quick/items/qquickshadereffect.cpp src/quick/particles/qquickcustomparticle.cpp src/quick/qtquick2.cpp Change-Id: Ia9c6517035ae912fa75e77473a452bd3383def56
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/animations/qanimationgroupjob.cpp16
-rw-r--r--src/qml/debugger/qqmldebug.h4
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp7
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp16
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h1
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp4
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h37
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h2
-rw-r--r--src/qml/qml/qqmlaccessors_p.h2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp184
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h88
-rw-r--r--src/qml/qml/qqmlcompiler.cpp31
-rw-r--r--src/qml/qml/qqmlcomponent.cpp3
-rw-r--r--src/qml/qml/qqmldata_p.h14
-rw-r--r--src/qml/qml/qqmldirparser.cpp12
-rw-r--r--src/qml/qml/qqmlengine.cpp14
-rw-r--r--src/qml/qml/qqmlexpression.cpp33
-rw-r--r--src/qml/qml/qqmlexpression_p.h7
-rw-r--r--src/qml/qml/qqmlimport.cpp36
-rw-r--r--src/qml/qml/qqmlinstruction.cpp3
-rw-r--r--src/qml/qml/qqmlinstruction_p.h2
-rw-r--r--src/qml/qml/qqmlproperty.cpp37
-rw-r--r--src/qml/qml/qqmlproperty_p.h8
-rw-r--r--src/qml/qml/qqmlrewrite.cpp17
-rw-r--r--src/qml/qml/qqmlrewrite_p.h29
-rw-r--r--src/qml/qml/qqmlscript.cpp5
-rw-r--r--src/qml/qml/qqmlvme.cpp86
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp456
-rw-r--r--src/qml/qml/v4/qv4bindings_p.h6
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp267
-rw-r--r--src/qml/qml/v4/qv4compiler_p_p.h16
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp130
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h85
-rw-r--r--src/qml/qml/v4/qv4ir.cpp37
-rw-r--r--src/qml/qml/v4/qv4ir_p.h6
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp30
-rw-r--r--src/qml/qml/v4/qv4irbuilder_p.h4
-rw-r--r--src/qml/qml/v4/qv4program_p.h4
-rw-r--r--src/qml/qml/v8/qjsvalue_p.h2
-rw-r--r--src/qml/qml/v8/qv8bindings.cpp23
-rw-r--r--src/qml/qml/v8/qv8bindings_p.h20
-rw-r--r--src/qml/qml/v8/qv8contextwrapper.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp43
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp29
-rw-r--r--src/qml/qml/v8/v8.pri6
45 files changed, 997 insertions, 867 deletions
diff --git a/src/qml/animations/qanimationgroupjob.cpp b/src/qml/animations/qanimationgroupjob.cpp
index 83b2192313..59bceaaf4e 100644
--- a/src/qml/animations/qanimationgroupjob.cpp
+++ b/src/qml/animations/qanimationgroupjob.cpp
@@ -51,8 +51,7 @@ QAnimationGroupJob::QAnimationGroupJob()
QAnimationGroupJob::~QAnimationGroupJob()
{
- while (firstChild() != 0)
- delete firstChild();
+ clear();
}
void QAnimationGroupJob::topLevelAnimationLoopChanged()
@@ -123,9 +122,16 @@ void QAnimationGroupJob::removeAnimation(QAbstractAnimationJob *animation)
void QAnimationGroupJob::clear()
{
- //### should this remove and delete, or just remove?
- while (firstChild() != 0)
- delete firstChild(); //removeAnimation(firstChild());
+ QAbstractAnimationJob *child = firstChild();
+ QAbstractAnimationJob *nextSibling = 0;
+ while (child != 0) {
+ child->m_group = 0;
+ nextSibling = child->nextSibling();
+ delete child;
+ child = nextSibling;
+ }
+ m_firstChild = 0;
+ m_lastChild = 0;
}
void QAnimationGroupJob::resetUncontrolledAnimationsFinishTime()
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 318e0bd71f..115f3cbc3a 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -55,9 +55,9 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
};
// Execute code in constructor before first QQmlEngine is instantiated
-#if defined(QT_DECLARATIVE_DEBUG_NO_WARNING)
+#if defined(QT_QML_DEBUG_NO_WARNING)
static QQmlDebuggingEnabler qmlEnableDebuggingHelper(false);
-#elif defined(QT_DECLARATIVE_DEBUG)
+#elif defined(QT_QML_DEBUG) || defined(QT_DECLARATIVE_DEBUG)
static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true);
#endif
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index dcf93b400e..468b653a1f 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -255,7 +255,7 @@ QQmlDebugServer *QQmlDebugServer::instance()
commandLineTested = true;
QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QQML_NO_DEBUG_PROTOCOL
+#ifndef QT_QML_NO_DEBUGGER
// ### remove port definition when protocol is changed
int port = 0;
bool block = false;
@@ -398,7 +398,6 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
iter.value()->stateChanged(newState);
}
- qDebug("QML Debugger: Connection established.");
d->messageArrivedCondition.wakeAll();
} else if (op == 1) {
@@ -458,14 +457,14 @@ void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
QList<QQmlDebugService*> QQmlDebugServer::services() const
{
- const Q_D(QQmlDebugServer);
+ Q_D(const QQmlDebugServer);
QReadLocker(&d->pluginsLock);
return d->plugins.values();
}
QStringList QQmlDebugServer::serviceNames() const
{
- const Q_D(QQmlDebugServer);
+ Q_D(const QQmlDebugServer);
QReadLocker(&d->pluginsLock);
return d->plugins.keys();
}
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index cd09b69e48..d8997fd587 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -67,7 +67,7 @@ QQmlEngineDebugService *QQmlEngineDebugService::instance()
}
QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QmlDebugger"), 1, parent),
+ : QQmlDebugService(QStringLiteral("QmlDebugger"), 2, parent),
m_watch(new QQmlWatcher(this)),
m_statesDelegate(0)
{
@@ -86,7 +86,8 @@ QDataStream &operator<<(QDataStream &ds,
const QQmlEngineDebugService::QQmlObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
- << data.objectName << data.objectType << data.objectId << data.contextId;
+ << data.objectName << data.objectType << data.objectId << data.contextId
+ << data.parentId;
return ds;
}
@@ -94,7 +95,8 @@ QDataStream &operator>>(QDataStream &ds,
QQmlEngineDebugService::QQmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
- >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId
+ >> data.parentId;
return ds;
}
@@ -264,7 +266,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
QQmlObjectProperty prop;
prop.type = QQmlObjectProperty::SignalProperty;
prop.hasNotifySignal = false;
- QQmlExpression *expr = signalHandler->expression();
+ QQmlBoundSignalExpression *expr = signalHandler->expression();
if (expr) {
prop.value = expr->expression();
QObject *scope = expr->scopeObject();
@@ -376,7 +378,7 @@ QQmlEngineDebugService::objectData(QObject *object)
rv.objectName = object->objectName();
rv.objectId = QQmlDebugService::idForObject(object);
rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
-
+ rv.parentId = QQmlDebugService::idForObject(object->parent());
QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
if (type) {
QString typeName = type->qmlTypeName();
@@ -603,9 +605,9 @@ bool QQmlEngineDebugService::setBinding(int objectId,
if (isLiteralValue) {
property.write(expression);
} else if (hasValidSignal(object, propertyName)) {
- QQmlExpression *qmlExpression = new QQmlExpression(context, object, expression.toString());
+ QQmlBoundSignalExpression *qmlExpression = new QQmlBoundSignalExpression(QQmlContextData::get(context), object, expression.toString(),
+ false, filename, line, column);
QQmlPropertyPrivate::setSignalExpression(property, qmlExpression);
- qmlExpression->setSourceLocation(filename, line, column);
} else if (property.isProperty()) {
QQmlBinding *binding = new QQmlBinding(expression.toString(), false, object, QQmlContextData::get(context), filename, line, column);;
binding->setTarget(property);
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
index 19a5776e27..3b855cb602 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/qml/debugger/qqmlenginedebugservice_p.h
@@ -83,6 +83,7 @@ public:
QString objectType;
int objectId;
int contextId;
+ int parentId;
};
struct QQmlObjectProperty {
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index c643073308..7109286197 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -195,7 +195,7 @@ void QQmlProfilerService::rangeData(RangeType range, const QUrl &rData)
if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
return;
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
+ QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(), -1, -1, 0, 0};
processMessage(rd);
}
@@ -213,7 +213,7 @@ void QQmlProfilerService::rangeLocation(RangeType range, const QUrl &fileName, i
if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
return;
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
+ QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(), line, column, 0, 0};
processMessage(rd);
}
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 2e351792cc..8662abb52e 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -54,7 +54,7 @@
//
#include <private/qqmldebugservice_p.h>
-#include "qqmlexpression.h"
+#include <private/qqmlboundsignal_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@@ -201,20 +201,20 @@ struct QQmlBindingProfiler {
};
struct QQmlHandlingSignalProfiler {
- QQmlHandlingSignalProfiler(const QMetaMethod &signal, QQmlExpression *expression)
+ QQmlHandlingSignalProfiler(const QMetaMethod &signal, QQmlBoundSignalExpression *expression)
{
enabled = QQmlProfilerService::instance
? QQmlProfilerService::instance->profilingEnabled() : false;
- if (enabled)
- init(signal, expression);
- }
-
- QQmlHandlingSignalProfiler(QObject *object, int index, QQmlExpression *expression)
- {
- enabled = QQmlProfilerService::instance
- ? QQmlProfilerService::instance->profilingEnabled() : false;
- if (enabled)
- init(object->metaObject()->method(index), expression);
+ if (enabled) {
+ QQmlProfilerService *service = QQmlProfilerService::instance;
+ service->startRange(QQmlProfilerService::HandlingSignal);
+ service->rangeData(QQmlProfilerService::HandlingSignal,
+ QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ")
+ + expression->expression());
+ service->rangeLocation(QQmlProfilerService::HandlingSignal,
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber());
+ }
}
~QQmlHandlingSignalProfiler()
@@ -224,19 +224,6 @@ struct QQmlHandlingSignalProfiler {
}
bool enabled;
-
-private:
- void init(const QMetaMethod &signal, QQmlExpression *expression)
- {
- QQmlProfilerService *service = QQmlProfilerService::instance;
- service->startRange(QQmlProfilerService::HandlingSignal);
- service->rangeData(QQmlProfilerService::HandlingSignal,
- QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ")
- + expression->expression());
- service->rangeLocation(QQmlProfilerService::HandlingSignal,
- expression->sourceFile(), expression->lineNumber(),
- expression->columnNumber());
- }
};
struct QQmlObjectCreatingProfiler {
diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h
index fe2ee1762b..1d5ecac08e 100644
--- a/src/qml/qml/qqmlabstractexpression_p.h
+++ b/src/qml/qml/qqmlabstractexpression_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
-class QQmlAbstractExpression
+class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression
{
public:
QQmlAbstractExpression();
diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h
index 8e67a58511..7558ab3e35 100644
--- a/src/qml/qml/qqmlaccessors_p.h
+++ b/src/qml/qml/qqmlaccessors_p.h
@@ -47,7 +47,7 @@
#include <QtCore/qhash.h>
#include <QtCore/QReadWriteLock>
-#ifdef Q_OS_QNX
+#if defined(Q_OS_QNX) || defined(Q_OS_LINUX)
#include <stdint.h>
#endif
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 3a3bf403e6..b77484c7e5 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -49,6 +49,7 @@
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
+#include "qqmlrewrite_p.h"
#include <private/qqmlprofilerservice_p.h>
#include <private/qv8debugservice_p.h>
@@ -59,6 +60,105 @@ Q_DECLARE_METATYPE(QJSValue)
QT_BEGIN_NAMESPACE
+static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = {
+ QQmlBoundSignalExpression::expressionIdentifier,
+ QQmlBoundSignalExpression::expressionChanged
+};
+
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression,
+ bool isRewritten, const QString &fileName, int line, int column)
+ : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable)
+{
+ setNotifyOnValueChanged(false);
+ setContext(ctxt);
+ setScopeObject(scope);
+ m_expression = QString::fromUtf8(expression);
+ m_expressionFunctionValid = false;
+ m_expressionFunctionRewritten = isRewritten;
+ m_fileName = fileName;
+ m_line = line;
+ m_column = column;
+}
+
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression,
+ bool isRewritten, const QString &fileName, int line, int column)
+ : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable)
+{
+ setNotifyOnValueChanged(false);
+ setContext(ctxt);
+ setScopeObject(scope);
+ m_expression = expression;
+ m_expressionFunctionValid = false;
+ m_expressionFunctionRewritten = isRewritten;
+ m_fileName = fileName;
+ m_line = line;
+ m_column = column;
+}
+
+QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
+{
+ qPersistentDispose(m_v8function);
+ qPersistentDispose(m_v8qmlscope);
+}
+
+QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e)
+{
+ QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e);
+ return QLatin1String("\"") + This->m_expression + QLatin1String("\"");
+}
+
+void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *)
+{
+ // bound signals do not notify on change.
+}
+
+// This mirrors code in QQmlExpressionPrivate::value() and v8value().
+// Any change made here should be made there and vice versa.
+void QQmlBoundSignalExpression::evaluate(QObject *secondaryScope)
+{
+ Q_ASSERT (context() && engine());
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
+
+ ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
+ {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope context_scope(ep->v8engine()->context());
+ if (!m_expressionFunctionValid) {
+ bool ok = true;
+ QString code;
+ if (m_expressionFunctionRewritten) {
+ code = m_expression;
+ } else {
+ QQmlRewrite::RewriteSignalHandler rewriteSignalHandler;
+ code = rewriteSignalHandler(m_expression, m_functionName, &ok);
+ }
+
+ if (ok)
+ m_v8function = evalFunction(context(), scopeObject(), code, m_fileName, m_line, &m_v8qmlscope);
+
+ if (m_v8function.IsEmpty() || m_v8function->IsNull()) {
+ ep->dereferenceScarceResources();
+ return; // could not evaluate function. Not valid.
+ }
+
+ setUseSharedContext(false);
+ m_expressionFunctionValid = true;
+ }
+
+ if (secondaryScope) {
+ QObject *restoreSecondaryScope = 0;
+ restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, secondaryScope);
+ QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0);
+ ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, restoreSecondaryScope);
+ } else {
+ QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0);
+ }
+ }
+ ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
+}
+
+////////////////////////////////////////////////////////////////////////
+
class QQmlBoundSignalParameters : public QObject
{
Q_OBJECT
@@ -104,10 +204,9 @@ QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
}
}
-void QQmlAbstractBoundSignal::addToObject()
+void QQmlAbstractBoundSignal::addToObject(QObject *obj)
{
Q_ASSERT(!m_prevSignal);
- QObject *obj = object();
Q_ASSERT(obj);
QQmlData *data = QQmlData::get(obj, true);
@@ -120,13 +219,15 @@ void QQmlAbstractBoundSignal::addToObject()
QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal,
QObject *owner)
-: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), m_owner(owner)
+: m_expression(0), m_params(0), m_scope(scope), m_signal(signal), m_paramsValid(false), m_isEvaluating(false)
{
// This is thread safe. Although it may be updated by two threads, they
// will both set it to the same value - so the worst thing that can happen
// is that they both do the work to figure it out. Boo hoo.
if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+ addToObject(owner);
+
QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
}
@@ -144,7 +245,7 @@ int QQmlBoundSignal::index() const
/*!
Returns the signal expression.
*/
-QQmlExpression *QQmlBoundSignal::expression() const
+QQmlBoundSignalExpression *QQmlBoundSignal::expression() const
{
return m_expression;
}
@@ -156,9 +257,9 @@ QQmlExpression *QQmlBoundSignal::expression() const
The QQmlBoundSignal instance takes ownership of \a e. The caller is
assumes ownership of the returned QQmlExpression.
*/
-QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e)
+QQmlBoundSignalExpression *QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e)
{
- QQmlExpression *rv = m_expression;
+ QQmlBoundSignalExpression *rv = m_expression;
m_expression = e;
if (m_expression) m_expression->setNotifyOnValueChanged(false);
return rv;
@@ -183,8 +284,8 @@ int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
}
if (m_params) m_params->setValues(a);
- if (m_expression && m_expression->engine()) {
- QQmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_expression && m_expression->context() && m_expression->engine()) {
+ m_expression->evaluate(m_params);
if (m_expression && m_expression->hasError())
QQmlEnginePrivate::warning(m_expression->engine(), m_expression->error());
}
@@ -247,7 +348,7 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
if (scope == "Qt")
meta = &QObject::staticQtMetaObject;
else
- meta = static_cast<QQmlBoundSignal*>(parent)->object()->metaObject();
+ meta = static_cast<QQmlBoundSignal*>(parent)->scope()->metaObject();
for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
QMetaEnum m = meta->enumerator(i);
if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
@@ -300,71 +401,6 @@ int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
}
}
-////////////////////////////////////////////////////////////////////////
-
-QQmlBoundSignalNoParams::QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal,
- QObject *owner)
-: m_expression(0), m_owner(owner), m_index(signal.methodIndex()), m_isEvaluating(false)
-{
- callback = &subscriptionCallback;
- QQmlNotifierEndpoint::connect(scope, m_index);
-}
-
-QQmlBoundSignalNoParams::~QQmlBoundSignalNoParams()
-{
- delete m_expression;
- m_expression = 0;
-}
-
-int QQmlBoundSignalNoParams::index() const
-{
- return m_index;
-}
-
-/*!
- Returns the signal expression.
-*/
-QQmlExpression *QQmlBoundSignalNoParams::expression() const
-{
- return m_expression;
-}
-
-/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
-
- The QQmlBoundSignalNoParams instance takes ownership of \a e. The caller is
- assumes ownership of the returned QQmlExpression.
-*/
-QQmlExpression *QQmlBoundSignalNoParams::setExpression(QQmlExpression *e)
-{
- QQmlExpression *rv = m_expression;
- m_expression = e;
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
-}
-
-void QQmlBoundSignalNoParams::subscriptionCallback(QQmlNotifierEndpoint *e)
-{
- QQmlBoundSignalNoParams *s = static_cast<QQmlBoundSignalNoParams*>(e);
- if (!s->m_expression)
- return;
-
- if (QQmlDebugService::isDebuggingEnabled())
- QV8DebugService::instance()->signalEmitted(QString::fromAscii(s->m_owner->metaObject()->method(s->m_index).methodSignature()));
-
- QQmlHandlingSignalProfiler prof(s->m_owner, s->m_index, s->m_expression);
-
- s->m_isEvaluating = true;
-
- if (s->m_expression && s->m_expression->engine()) {
- QQmlExpressionPrivate::get(s->m_expression)->value();
- if (s->m_expression && s->m_expression->hasError())
- QQmlEnginePrivate::warning(s->m_expression->engine(), s->m_expression->error());
- }
- s->m_isEvaluating = false;
-}
-
QT_END_NAMESPACE
#include <qqmlboundsignal.moc>
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 5fc8c3522f..c6ce875d07 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -53,15 +53,51 @@
// We mean it.
//
-#include "qqmlexpression.h"
-
#include <QtCore/qmetaobject.h>
-#include <private/qqmlnotifier_p.h>
+#include <private/qqmlabstractexpression_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression
+{
+public:
+ QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression,
+ bool isRewritten, const QString &fileName, int line, int column);
+ QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression,
+ bool isRewritten, const QString &fileName, int line, int column);
+ ~QQmlBoundSignalExpression();
+
+ // "inherited" from QQmlJavaScriptExpression.
+ static QString expressionIdentifier(QQmlJavaScriptExpression *);
+ static void expressionChanged(QQmlJavaScriptExpression *);
+
+ // evaluation of a bound signal expression doesn't return any value
+ void evaluate(QObject *secondaryScope = 0);
+
+ QString sourceFile() const { return m_fileName; }
+ int lineNumber() const { return m_line; }
+ int columnNumber() const { return m_column; }
+ QString expression() const { return m_expression; }
+
+ QQmlEngine *engine() const { return context() ? context()->engine : 0; }
+
+private:
+ v8::Persistent<v8::Object> m_v8qmlscope;
+ v8::Persistent<v8::Function> m_v8function;
+
+ QString m_expression;
+ QString m_functionName; // hint for debugger
+ QString m_fileName;
+ int m_line;
+ int m_column;
+
+ bool m_expressionFunctionValid:1;
+ bool m_expressionFunctionRewritten:1;
+};
+
class Q_QML_EXPORT QQmlAbstractBoundSignal
{
public:
@@ -69,11 +105,12 @@ public:
virtual ~QQmlAbstractBoundSignal();
virtual int index() const = 0;
- virtual QQmlExpression *expression() const = 0;
- virtual QQmlExpression *setExpression(QQmlExpression *) = 0;
- virtual QObject *object() = 0;
+ virtual QQmlBoundSignalExpression *expression() const = 0;
+ virtual QQmlBoundSignalExpression *setExpression(QQmlBoundSignalExpression *) = 0;
+ virtual QObject *scope() = 0;
- void addToObject();
+protected:
+ void addToObject(QObject *owner);
private:
friend class QQmlData;
@@ -93,9 +130,9 @@ public:
int index() const;
- QQmlExpression *expression() const;
- QQmlExpression *setExpression(QQmlExpression *);
- QObject *object() { return m_owner; }
+ QQmlBoundSignalExpression *expression() const;
+ QQmlBoundSignalExpression *setExpression(QQmlBoundSignalExpression *);
+ QObject *scope() { return m_scope; }
bool isEvaluating() const { return m_isEvaluating; }
@@ -103,39 +140,14 @@ protected:
virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
private:
- QQmlExpression *m_expression;
+ QQmlBoundSignalExpression *m_expression;
+ QQmlBoundSignalParameters *m_params;
+ QObject *m_scope;
QMetaMethod m_signal;
bool m_paramsValid : 1;
bool m_isEvaluating : 1;
- QQmlBoundSignalParameters *m_params;
- QObject *m_owner;
-};
-
-class Q_QML_EXPORT QQmlBoundSignalNoParams : public QQmlAbstractBoundSignal,
- public QQmlNotifierEndpoint
-{
-public:
- QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, QObject *owner);
- virtual ~QQmlBoundSignalNoParams();
-
- int index() const;
-
- QQmlExpression *expression() const;
- QQmlExpression *setExpression(QQmlExpression *);
- QObject *object() { return m_owner; }
-
- static void subscriptionCallback(QQmlNotifierEndpoint *e);
-
- bool isEvaluating() const { return m_isEvaluating; }
-
-private:
- QQmlExpression *m_expression;
- QObject *m_owner;
- int m_index;
- bool m_isEvaluating;
};
-
QT_END_NAMESPACE
#endif // QQMLBOUNDSIGNAL_P_H
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index dec9911481..54577f9b92 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -3468,6 +3468,7 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
store.value = js.compiledIndex;
store.context = js.bindingContext.stack;
store.owner = js.bindingContext.owner;
+ store.isAlias = prop->isAlias;
if (valueTypeProperty) {
store.isRoot = (compileState->root == valueTypeProperty->parent);
} else {
@@ -3488,30 +3489,29 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
} else if (ref.dataType == BindingReference::QtScript) {
const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
- QQmlInstruction store;
- store.assignBinding.value = output->indexForString(js.rewrittenExpression);
- store.assignBinding.context = js.bindingContext.stack;
- store.assignBinding.owner = js.bindingContext.owner;
- store.assignBinding.line = binding->location.start.line;
- store.assignBinding.column = binding->location.start.column;
+ Instruction::StoreBinding store;
+ store.value = output->indexForString(js.rewrittenExpression);
+ store.context = js.bindingContext.stack;
+ store.owner = js.bindingContext.owner;
+ store.line = binding->location.start.line;
+ store.column = binding->location.start.column;
+ store.isAlias = prop->isAlias;
if (valueTypeProperty) {
- store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent);
+ store.isRoot = (compileState->root == valueTypeProperty->parent);
} else {
- store.assignBinding.isRoot = (compileState->root == obj);
+ store.isRoot = (compileState->root == obj);
}
Q_ASSERT(js.bindingContext.owner == 0 ||
(js.bindingContext.owner != 0 && valueTypeProperty));
if (js.bindingContext.owner) {
- store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ store.property = genValueTypeData(prop, valueTypeProperty);
} else {
- store.assignBinding.property = prop->core;
+ store.property = prop->core;
}
- output->addInstructionHelper(
- !prop->isAlias ? QQmlInstruction::StoreBinding
- : QQmlInstruction::StoreBindingOnAlias
- , store);
+
+ output->addInstruction(store);
} else {
Q_ASSERT(!"Unhandled BindingReference::DataType type");
}
@@ -3588,8 +3588,7 @@ bool QQmlCompiler::completeComponentBuild()
bool isSharable = false;
binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
- if (isSharable && !binding.property->isAlias /* See above re alias */ &&
- binding.property->type != qMetaTypeId<QQmlBinding*>()) {
+ if (isSharable && binding.property->type != qMetaTypeId<QQmlBinding*>()) {
binding.dataType = BindingReference::V8;
sharedBindings.append(b);
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 7bddaadcd0..2e46192246 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1396,7 +1396,8 @@ void QV8IncubatorResource::statusChanged(Status s)
{
if (s == Ready) {
Q_ASSERT(QQmlData::get(object()));
- QQmlData::get(object())->setImplicitDestructible();
+ QQmlData::get(object())->explicitIndestructibleSet = false;
+ QQmlData::get(object())->indestructible = false;
}
if (!me.IsEmpty()) { // Will be false in synchronous mode
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index e7e001c4f2..3dd1c3ccba 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -181,11 +181,25 @@ public:
QQmlNotifier *objectNameNotifier() const;
QHash<int, QObject *> *attachedProperties() const;
+ static inline bool wasDeleted(QObject *);
private:
// For objectNameNotifier and attachedProperties
mutable QQmlDataExtended *extendedData;
};
+bool QQmlData::wasDeleted(QObject *object)
+{
+ if (!object)
+ return true;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+ if (priv->wasDeleted)
+ return true;
+
+ return priv->declarativeData &&
+ static_cast<QQmlData *>(priv->declarativeData)->isQueuedForDeletion;
+}
+
QQmlNotifierEndpoint *QQmlData::notify(int index)
{
Q_ASSERT(index <= 0xFFFF);
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index df5f7f8ee9..82289311c9 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -297,16 +297,16 @@ QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- return debug << qPrintable(QString("{%1 %2.%3}").arg(component.typeName)
- .arg(component.majorVersion)
- .arg(component.minorVersion));
+ const QString output = QString::fromLatin1("{%1 %2.%3}").
+ arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
+ return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- return debug << qPrintable(QString("{%1 %2.%3}").arg(script.nameSpace)
- .arg(script.majorVersion)
- .arg(script.minorVersion));
+ const QString output = QString::fromLatin1("{%1 %2.%3}").
+ arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
+ return debug << qPrintable(output);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 955c8ce414..153d6b325a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -598,9 +598,17 @@ QQmlEngine::~QQmlEngine()
/*!
Clears the engine's internal component cache.
- Normally the QQmlEngine caches components loaded from qml
- files. This method clears this cache and forces the component to be
- reloaded.
+ This function causes the property metadata of all components previously
+ loaded by the engine to be destroyed. All previously loaded components and
+ the property bindings for all extant objects created from those components will
+ cease to function.
+
+ This function returns the engine to a state where it does not contain any loaded
+ component data. This may be useful in order to reload a smaller subset of the
+ previous component set, or to load a new version of a previously loaded component.
+
+ Once the component cache has been cleared, components must be loaded before
+ any new objects can be created.
*/
void QQmlEngine::clearComponentCache()
{
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index d760486605..940b3c8354 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -60,7 +60,7 @@ static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
QQmlExpressionPrivate::QQmlExpressionPrivate()
: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
expressionFunctionValid(true), expressionFunctionRewritten(false),
- extractExpressionFromFunction(false), line(-1), dataRef(0)
+ line(-1)
{
}
@@ -68,8 +68,6 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate()
{
qPersistentDispose(v8qmlscope);
qPersistentDispose(v8function);
- if (dataRef) dataRef->release();
- dataRef = 0;
}
void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me)
@@ -321,13 +319,7 @@ QQmlContext *QQmlExpression::context() const
QString QQmlExpression::expression() const
{
Q_D(const QQmlExpression);
- if (d->extractExpressionFromFunction && context()->engine()) {
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(context()->engine());
- v8::HandleScope handle_scope;
- v8::Context::Scope scope(v8engine->context());
-
- return v8engine->toString(v8::Handle<v8::Value>(d->v8function));
- } else if (!d->expressionUtf8.isEmpty()) {
+ if (!d->expressionUtf8.isEmpty()) {
return QString::fromUtf8(d->expressionUtf8);
} else {
return d->expression;
@@ -351,7 +343,7 @@ void QQmlExpression::setExpression(const QString &expression)
}
// Must be called with a valid handle scope
-v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QQmlExpressionPrivate::v8value(bool *isUndefined)
{
if (!expressionFunctionValid) {
bool ok = true;
@@ -369,21 +361,10 @@ v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, boo
expressionFunctionValid = true;
}
-
- if (secondaryScope) {
- v8::Local<v8::Value> result;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QObject *restoreSecondaryScope = 0;
- restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
- result = evaluate(context(), v8function, isUndefined);
- ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
- return result;
- } else {
- return evaluate(context(), v8function, isUndefined);
- }
+ return evaluate(context(), v8function, isUndefined);
}
-QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
Q_Q(QQmlExpression);
@@ -400,7 +381,7 @@ QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined
{
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(ep->v8engine()->context());
- v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
+ v8::Local<v8::Value> result = v8value(isUndefined);
rv = ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
@@ -421,7 +402,7 @@ QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined
QVariant QQmlExpression::evaluate(bool *valueIsUndefined)
{
Q_D(QQmlExpression);
- return d->value(0, valueIsUndefined);
+ return d->value(valueIsUndefined);
}
/*!
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index 186e3aebf9..d32e2d314c 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -82,9 +82,9 @@ public:
void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, int, int);
void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, int, int);
- QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ QVariant value(bool *isUndefined = 0);
- v8::Local<v8::Value> v8value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ v8::Local<v8::Value> v8value(bool *isUndefined = 0);
static inline QQmlExpressionPrivate *get(QQmlExpression *expr);
static inline QQmlExpression *get(QQmlExpressionPrivate *expr);
@@ -96,7 +96,6 @@ public:
bool expressionFunctionValid:1;
bool expressionFunctionRewritten:1;
- bool extractExpressionFromFunction:1;
// "Inherited" from QQmlJavaScriptExpression
static QString expressionIdentifier(QQmlJavaScriptExpression *);
@@ -113,8 +112,6 @@ public:
int line;
int column;
QString name; //function name, hint for the debugger
-
- QQmlRefCount *dataRef;
};
QQmlExpressionPrivate *QQmlExpressionPrivate::get(QQmlExpression *expr)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 1224efdaac..be870cad4c 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -545,27 +545,27 @@ QString QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork
}
}
- // TODO: Should this search be omitted if found == true?
-
- // step 2: search for extension with encoded version major
- foreach (const QString &p, database->fileImportPath) {
- dir = p+Slash+url;
+ if (!found) {
+ // step 2: search for extension with encoded version major
+ foreach (const QString &p, database->fileImportPath) {
+ dir = p+Slash+url;
- QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
- const QString absoluteFilePath = fi.absoluteFilePath();
+ QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
+ const QString absoluteFilePath = fi.absoluteFilePath();
- if (fi.isFile()) {
- found = true;
+ if (fi.isFile()) {
+ found = true;
- const QString absolutePath = fi.absolutePath();
- if (absolutePath.at(0) == QLatin1Char(':'))
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(fi.absolutePath()).toString();
- uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return QString();
- break;
+ const QString absolutePath = fi.absolutePath();
+ if (absolutePath.at(0) == QLatin1Char(':'))
+ url = QLatin1String("qrc://") + absolutePath.mid(1);
+ else
+ url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+ uri = resolvedUri(dir, database);
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
+ return QString();
+ break;
+ }
}
}
diff --git a/src/qml/qml/qqmlinstruction.cpp b/src/qml/qml/qqmlinstruction.cpp
index b37117e69b..82cf235712 100644
--- a/src/qml/qml/qqmlinstruction.cpp
+++ b/src/qml/qml/qqmlinstruction.cpp
@@ -210,9 +210,6 @@ void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
case QQmlInstruction::StoreBinding:
qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
- case QQmlInstruction::StoreBindingOnAlias:
- qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
- break;
case QQmlInstruction::StoreV4Binding:
qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignV4Binding.property << "\t" << instr->assignV4Binding.value << "\t" << instr->assignV4Binding.context;
break;
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index b7533aca68..cfc530df04 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -114,7 +114,6 @@ QT_BEGIN_NAMESPACE
F(BeginObject, begin) \
F(InitV8Bindings, initV8Bindings) \
F(StoreBinding, assignBinding) \
- F(StoreBindingOnAlias, assignBinding) \
F(StoreV8Binding, assignBinding) \
F(StoreV4Binding, assignV4Binding) \
F(StoreValueSource, assignValueSource) \
@@ -251,6 +250,7 @@ union QQmlInstruction
short context;
short owner;
bool isRoot;
+ bool isAlias;
ushort line;
ushort column;
};
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index f68c345f3a..075c1f6c4f 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -920,7 +920,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
Returns the expression associated with this signal property, or 0 if no
signal expression exists.
*/
-QQmlExpression *
+QQmlBoundSignalExpression *
QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
{
if (!(that.type() & QQmlProperty::SignalProperty))
@@ -948,9 +948,9 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
Ownership of \a expr transfers to QML. Ownership of the return value is
assumed by the caller.
*/
-QQmlExpression *
+QQmlBoundSignalExpression *
QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
- QQmlExpression *expr)
+ QQmlBoundSignalExpression *expr)
{
if (!(that.type() & QQmlProperty::SignalProperty)) {
delete expr;
@@ -970,13 +970,8 @@ QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
return signalHandler->setExpression(expr);
if (expr) {
- QQmlAbstractBoundSignal *signal = 0;
- if (that.method().parameterTypes().count())
- signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object);
- else
- signal = new QQmlBoundSignalNoParams(that.d->object, that.method(), that.d->object);
- QQmlExpression *oldExpr = signal->setExpression(expr);
- signal->addToObject();
+ QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object);
+ QQmlBoundSignalExpression *oldExpr = signal->setExpression(expr);
return oldExpr;
} else {
return 0;
@@ -1531,13 +1526,29 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
return true;
const char *valueType = 0;
- if (value.userType() == QVariant::Invalid) valueType = "null";
- else valueType = QMetaType::typeName(value.userType());
+ const char *propertyType = 0;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ if (QObject *o = *(QObject **)value.constData()) {
+ valueType = o->metaObject()->className();
+
+ if (const QMetaObject *propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type)) {
+ propertyType = propertyMetaObject->className();
+ }
+ }
+ } else if (value.userType() != QVariant::Invalid) {
+ valueType = QMetaType::typeName(value.userType());
+ }
+
+ if (!valueType)
+ valueType = "null";
+ if (!propertyType)
+ propertyType = QMetaType::typeName(type);
expression->delayedError()->error.setDescription(QLatin1String("Unable to assign ") +
QLatin1String(valueType) +
QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(type)));
+ QLatin1String(propertyType));
return false;
}
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index f4a9ced53b..e33c95ae41 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -64,7 +64,7 @@
QT_BEGIN_NAMESPACE
class QQmlContext;
-class QQmlExpression;
+class QQmlBoundSignalExpression;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
@@ -140,9 +140,9 @@ public:
static QQmlAbstractBinding *setBinding(const QQmlProperty &that,
QQmlAbstractBinding *,
WriteFlags flags = DontRemoveBinding);
- static QQmlExpression *signalExpression(const QQmlProperty &that);
- static QQmlExpression *setSignalExpression(const QQmlProperty &that,
- QQmlExpression *) ;
+ static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that);
+ static QQmlBoundSignalExpression *setSignalExpression(const QQmlProperty &that,
+ QQmlBoundSignalExpression *) ;
static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
static bool writeBinding(QObject *, const QQmlPropertyData &,
QQmlContextData *context,
diff --git a/src/qml/qml/qqmlrewrite.cpp b/src/qml/qml/qqmlrewrite.cpp
index 72bd23955b..bbb17b631d 100644
--- a/src/qml/qml/qqmlrewrite.cpp
+++ b/src/qml/qml/qqmlrewrite.cpp
@@ -51,6 +51,8 @@ DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
namespace QQmlRewrite {
+QString SharedBindingTester::evalString("eval");
+
static void rewriteStringLiteral(AST::StringLiteral *ast, const QString *code, int startPosition, TextWriter *writer)
{
const unsigned position = ast->firstSourceLocation().begin() - startPosition + 1;
@@ -419,6 +421,21 @@ QString RewriteSignalHandler::operator()(QQmlJS::AST::Node *node, const QString
return rewritten;
}
+QString RewriteSignalHandler::operator()(const QString &code, const QString &name, bool *ok)
+{
+ Engine engine;
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ if (!parser.statement()) {
+ if (ok) *ok = false;
+ return QString();
+ }
+ if (ok) *ok = true;
+ return operator()(parser.statement(), code, name);
+}
+
} // namespace QQmlRewrite
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlrewrite_p.h b/src/qml/qml/qqmlrewrite_p.h
index 1d69839878..efa10ce316 100644
--- a/src/qml/qml/qqmlrewrite_p.h
+++ b/src/qml/qml/qqmlrewrite_p.h
@@ -70,9 +70,11 @@ public:
bool isSharable(const QString &code);
bool isSharable(AST::Node *Node);
- virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; }
- virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; }
- virtual bool visit(AST::CallExpression *) { _sharable = false; return false; }
+ inline virtual bool visit(AST::FunctionDeclaration *);
+ inline virtual bool visit(AST::FunctionExpression *);
+ inline virtual bool visit(AST::IdentifierExpression *);
+
+ static QString evalString;
};
class RewriteBinding: protected AST::Visitor
@@ -133,6 +135,7 @@ class RewriteSignalHandler: protected AST::Visitor
public:
RewriteSignalHandler();
QString operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name);
+ QString operator()(const QString &code, const QString &name, bool *ok = 0);
protected:
void rewriteMultilineStrings(QString &code);
@@ -142,6 +145,26 @@ protected:
virtual bool visit(AST::StringLiteral *ast);
};
+bool SharedBindingTester::visit(AST::FunctionDeclaration *)
+{
+ _sharable = false;
+ return false;
+}
+
+bool SharedBindingTester::visit(AST::FunctionExpression *)
+{
+ _sharable = false;
+ return false;
+}
+
+bool SharedBindingTester::visit(AST::IdentifierExpression *e)
+{
+ if (e->name == evalString)
+ _sharable = false;
+
+ return false; // IdentifierExpression is a leaf node anyway
+}
+
} // namespace QQmlRewrite
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index e1925eb238..37c0fb44a4 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -66,6 +66,11 @@ QQmlScript::Object::Object()
: type(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1),
componentCompileState(0), nextAliasingObject(0), nextIdObject(0)
{
+ // initialize the members in the meta object
+ extObject.d.superdata = 0;
+ extObject.d.stringdata = 0;
+ extObject.d.data = 0;
+ extObject.d.extradata = 0;
}
QQmlScript::Object::~Object()
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 5412315d31..985d291a8e 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -204,13 +204,19 @@ inline bool fastHasBinding(QObject *o, int index)
{
QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(o)->declarativeData);
+ index &= 0xFFFFFF; // To handle value types
+
return ddata && (ddata->bindingBitsSize > index) &&
(ddata->bindingBits[index / 32] & (1 << (index % 32)));
}
static void removeBindingOnProperty(QObject *o, int index)
{
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, index, -1, 0);
+ int coreIndex = index & 0xFFFFFF;
+ int valueTypeIndex = index & 0xFF000000;
+ if (!valueTypeIndex) valueTypeIndex = -1;
+
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
if (binding) binding->destroy();
}
@@ -724,15 +730,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
- QQmlAbstractBoundSignal *bs = 0;
- if (signal.parameterTypes().count())
- bs = new QQmlBoundSignal(target, signal, target);
- else
- bs = new QQmlBoundSignalNoParams(target, signal, target);
- QQmlExpression *expr =
- new QQmlExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column, *new QQmlExpressionPrivate);
+ QQmlBoundSignal *bs = new QQmlBoundSignal(target, signal, target);
+ QQmlBoundSignalExpression *expr =
+ new QQmlBoundSignalExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column);
bs->setExpression(expr);
- bs->addToObject();
QML_END_INSTR(StoreSignal)
QML_BEGIN_INSTR(StoreImportedScript)
@@ -788,35 +789,23 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
bind->m_mePtr = &bindValues.top();
bind->setTarget(target, instr.property, CTXT);
- typedef QQmlPropertyPrivate QDPP;
- Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property));
- Q_ASSERT(bind->object() == target);
-
- bind->addToObject();
- QML_END_INSTR(StoreBinding)
-
- QML_BEGIN_INSTR(StoreBindingOnAlias)
- QObject *target =
- objects.at(objects.count() - 1 - instr.owner);
- QObject *context =
- objects.at(objects.count() - 1 - instr.context);
+ if (instr.isAlias) {
+ QQmlAbstractBinding *old =
+ QQmlPropertyPrivate::setBindingNoEnable(target,
+ instr.property.coreIndex,
+ instr.property.getValueTypeCoreIndex(),
+ bind);
+ if (old) { old->destroy(); }
+ } else {
+ typedef QQmlPropertyPrivate QDPP;
+ Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property));
+ Q_ASSERT(bind->object() == target);
- if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
- QML_NEXT_INSTR(StoreBindingOnAlias);
+ CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
- QQmlBinding *bind = new QQmlBinding(PRIMITIVES.at(instr.value), true,
- context, CTXT, COMP->name, instr.line,
- instr.column);
- bindValues.push(bind);
- bind->m_mePtr = &bindValues.top();
- bind->setTarget(target, instr.property, CTXT);
-
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(target, instr.property.coreIndex,
- instr.property.getValueTypeCoreIndex(),
- bind);
- if (old) { old->destroy(); }
- QML_END_INSTR(StoreBindingOnAlias)
+ bind->addToObject();
+ }
+ QML_END_INSTR(StoreBinding)
QML_BEGIN_INSTR(StoreV4Binding)
QObject *target =
@@ -837,6 +826,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
Q_ASSERT(binding->propertyIndex() == (property & 0xFF00FFFF));
Q_ASSERT(binding->object() == target);
+ CLEAN_PROPERTY(target, property & 0xFF00FFFF);
+
binding->addToObject();
QML_END_INSTR(StoreV4Binding)
@@ -855,11 +846,22 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
bindValues.push(binding);
binding->m_mePtr = &bindValues.top();
- typedef QQmlPropertyPrivate QDPP;
- Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property));
- Q_ASSERT(binding->object() == target);
+ if (instr.isAlias) {
+ QQmlAbstractBinding *old =
+ QQmlPropertyPrivate::setBindingNoEnable(target,
+ instr.property.coreIndex,
+ instr.property.getValueTypeCoreIndex(),
+ binding);
+ if (old) { old->destroy(); }
+ } else {
+ typedef QQmlPropertyPrivate QDPP;
+ Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property));
+ Q_ASSERT(binding->object() == target);
+
+ CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
- binding->addToObject();
+ binding->addToObject();
+ }
}
QML_END_INSTR(StoreV8Binding)
@@ -1242,9 +1244,9 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
while (!bindValues.isEmpty()) {
QQmlAbstractBinding *b = bindValues.pop();
- if(b) {
+ if (b) {
b->m_mePtr = 0;
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+ b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
}
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 0cd6ffd082..4c92598c32 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -52,6 +52,7 @@
#include <private/qqmlmetatype_p.h>
#include <private/qqmltrace_p.h>
#include <private/qqmlstringconverters_p.h>
+#include <private/qqmlproperty_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtCore/qnumeric.h>
@@ -66,46 +67,53 @@ namespace {
struct Register {
typedef QQmlRegisterType Type;
- void setUndefined() { dataType = UndefinedType; }
- void setNull() { dataType = NullType; }
- void setNaN() { setqreal(qSNaN()); }
- bool isUndefined() const { return dataType == UndefinedType; }
+ inline void setUndefined() { dataType = UndefinedType; }
+ inline void setNull() { dataType = NullType; }
+ inline void setNaN() { setnumber(qSNaN()); }
+ inline bool isUndefined() const { return dataType == UndefinedType; }
- void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
- QObject *getQObject() const { return qobjectValue; }
+ inline void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
+ inline QObject *getQObject() const { return qobjectValue; }
- void setqreal(qreal v) { qrealValue = v; dataType = QRealType; }
- qreal getqreal() const { return qrealValue; }
- qreal &getqrealref() { return qrealValue; }
+ inline void setnumber(double v) { numberValue = v; dataType = NumberType; }
+ inline double getnumber() const { return numberValue; }
+ inline double &getnumberref() { return numberValue; }
- void setint(int v) { intValue = v; dataType = IntType; }
- int getint() const { return intValue; }
- int &getintref() { return intValue; }
+ inline void setfloat(float v) { floatValue = v; dataType = FloatType; }
+ inline float getfloat() const { return floatValue; }
+ inline float &getfloatref() { return floatValue; }
- void setbool(bool v) { boolValue = v; dataType = BoolType; }
- bool getbool() const { return boolValue; }
- bool &getboolref() { return boolValue; }
+ inline void setint(int v) { intValue = v; dataType = IntType; }
+ inline int getint() const { return intValue; }
+ inline int &getintref() { return intValue; }
- QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
- QString *getstringptr() { return (QString *)typeDataPtr(); }
- QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
- const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
- const QString *getstringptr() const { return (QString *)typeDataPtr(); }
- const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+ inline void setbool(bool v) { boolValue = v; dataType = BoolType; }
+ inline bool getbool() const { return boolValue; }
+ inline bool &getboolref() { return boolValue; }
+
+ inline QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
+ inline QString *getstringptr() { return (QString *)typeDataPtr(); }
+ inline QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
+ inline QColor *getcolorptr() { return (QColor *)typeDataPtr(); }
+ inline const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
+ inline const QString *getstringptr() const { return (QString *)typeDataPtr(); }
+ inline const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+ inline const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); }
size_t dataSize() { return sizeof(data); }
- void *typeDataPtr() { return (void *)&data; }
- void *typeMemory() { return (void *)data; }
- const void *typeDataPtr() const { return (void *)&data; }
- const void *typeMemory() const { return (void *)data; }
+ inline void *typeDataPtr() { return (void *)&data; }
+ inline void *typeMemory() { return (void *)data; }
+ inline const void *typeDataPtr() const { return (void *)&data; }
+ inline const void *typeMemory() const { return (void *)data; }
- Type gettype() const { return dataType; }
- void settype(Type t) { dataType = t; }
+ inline Type gettype() const { return dataType; }
+ inline void settype(Type t) { dataType = t; }
Type dataType; // Type of data
union {
QObject *qobjectValue;
- qreal qrealValue;
+ double numberValue;
+ float floatValue;
int intValue;
bool boolValue;
void *data[sizeof(QVariant)];
@@ -387,85 +395,6 @@ void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
sub->disconnect();
}
-// Conversion functions - these MUST match the QtScript expression path
-inline static qreal toReal(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return reg->getqreal();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toReal();
- } else {
- if (ok) *ok = false;
- return 0;
- }
-}
-
-inline static QString toString(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return QString::number(reg->getqreal());
- } else if (type == QMetaType::Int) {
- return QString::number(reg->getint());
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toString();
- } else if (type == QMetaType::QString) {
- return *reg->getstringptr();
- } else {
- if (ok) *ok = false;
- return QString();
- }
-}
-
-inline static bool toBool(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::Bool) {
- return reg->getbool();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toBool();
- } else {
- if (ok) *ok = false;
- return false;
- }
-}
-
-inline static QUrl toUrl(Register *reg, int type, QQmlContextData *context, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- QUrl base;
- if (type == qMetaTypeId<QVariant>()) {
- QVariant *var = reg->getvariantptr();
- int vt = var->type();
- if (vt == QVariant::Url) {
- base = var->toUrl();
- } else if (vt == QVariant::ByteArray) {
- // Preserve any valid percent-encoded octets supplied by the source
- base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode);
- } else if (vt == QVariant::String) {
- base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode);
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
- } else if (type == QMetaType::QString) {
- base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode);
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
-
- if (!base.isEmpty() && base.isRelative())
- return context->url.resolved(base);
- else
- return base;
-}
-
static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
{
QVariant qtscript = qtscriptRaw;
@@ -529,10 +458,29 @@ static void testBindingResult(const QString &binding, int line, int column,
if (expression.hasError()) {
iserror = true;
qtscriptResult = "exception";
- } else {
- qtscriptResult = testResultToString(value, isUndefined);
+ } else if (value.userType() != resultType) {
+ // Override the QMetaType conversions to make them more JS friendly.
+ if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
+ resultType == QMetaType::QUrl)) {
+ // number to string-like conversion.
+ value = QVariant::fromValue<QString>(QString::number(value.toDouble(), 'g', 16));
+ } else if (value.userType() == QMetaType::QUrl && resultType == QMetaType::Bool) {
+ // url to bool conversion
+ value = QVariant::fromValue<bool>(!value.toUrl().isEmpty());
+ }
+
+ if (!value.isNull() && !value.convert(resultType)) {
+ iserror = true;
+ qtscriptResult = "exception";
+ } else if (resultType == QMetaType::QUrl) {
+ // a V8 value was converted to QUrl.
+ value = QVariant::fromValue<QUrl>(context->resolvedUrl(value.toUrl()));
+ }
}
+ if (! iserror)
+ qtscriptResult = testResultToString(value, isUndefined);
+
if (isUndefined && result.isUndefined()) {
return;
} else if(isUndefined != result.isUndefined()) {
@@ -557,8 +505,8 @@ static void testBindingResult(const QString &binding, int line, int column,
case QMetaType::Int:
v4value = result.getint();
break;
- case QMetaType::QReal:
- v4value = result.getqreal();
+ case QMetaType::Double:
+ v4value = result.getnumber();
break;
default:
if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
@@ -621,15 +569,15 @@ static void throwException(int id, QQmlDelayedError *error,
QQmlEnginePrivate::warning(context->engine, error->error);
}
-const qreal QV4Bindings::D32 = 4294967296.0;
+const double QV4Bindings::D32 = 4294967296.0;
-qint32 QV4Bindings::toInt32(qreal n)
+qint32 QV4Bindings::toInt32(double n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qreal abs_n = fabs(n);
+ double abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
const double D31 = D32 / 2.0;
@@ -643,13 +591,13 @@ qint32 QV4Bindings::toInt32(qreal n)
return qint32 (n);
}
-inline quint32 QV4Bindings::toUint32(qreal n)
+inline quint32 QV4Bindings::toUint32(double n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qreal abs_n = fabs(n);
+ double abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
@@ -665,6 +613,11 @@ inline quint32 QV4Bindings::toUint32(qreal n)
goto exceptionExit; \
}
+#define THROW_VALUE_EXCEPTION_STR(id, str) { \
+ throwException((id), error, program, context, (str)); \
+ goto exceptionExit; \
+}
+
#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
@@ -791,13 +744,21 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
sub->bindings = this;
sub->method = subIdx;
}
- reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
+
+ const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType;
+ reg.init(valueType);
if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
MARK_REGISTER(instr->fetchAndSubscribe.reg);
QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
reg.typeDataPtr());
+ if (valueType == FloatType) {
+ // promote floats
+ const double v = reg.getfloat();
+ reg.setnumber(v);
+ }
+
if (accessors->notifier) {
QQmlNotifier *notifier = 0;
accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, &notifier);
@@ -868,11 +829,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(UnaryNot, unaryop)
- QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop)
+ QML_V4_BEGIN_INSTR(UnaryMinusNumber, unaryop)
{
- registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal());
+ registers[instr->unaryop.output].setnumber(-registers[instr->unaryop.src].getnumber());
}
- QML_V4_END_INSTR(UnaryMinusReal, unaryop)
+ QML_V4_END_INSTR(UnaryMinusNumber, unaryop)
QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
{
@@ -880,11 +841,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(UnaryMinusInt, unaryop)
- QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop)
+ QML_V4_BEGIN_INSTR(UnaryPlusNumber, unaryop)
{
- registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal());
+ registers[instr->unaryop.output].setnumber(+registers[instr->unaryop.src].getnumber());
}
- QML_V4_END_INSTR(UnaryPlusReal, unaryop)
+ QML_V4_END_INSTR(UnaryPlusNumber, unaryop)
QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
{
@@ -901,14 +862,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertBoolToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(src.getbool());
+ else output.setnumber(src.getbool());
}
- QML_V4_END_INSTR(ConvertBoolToReal, unaryop)
+ QML_V4_END_INSTR(ConvertBoolToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
{
@@ -932,14 +893,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertIntToBool, unaryop)
- QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertIntToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qreal(src.getint()));
+ else output.setnumber(double(src.getint()));
}
- QML_V4_END_INSTR(ConvertIntToReal, unaryop)
+ QML_V4_END_INSTR(ConvertIntToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
{
@@ -954,25 +915,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertIntToString, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setbool(src.getqreal() != 0);
+ else output.setbool(src.getnumber() != 0);
}
- QML_V4_END_INSTR(ConvertRealToBool, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToBool, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToInt, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(toInt32(src.getqreal()));
+ else output.setint(toInt32(src.getnumber()));
}
- QML_V4_END_INSTR(ConvertRealToInt, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToString, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
@@ -980,11 +941,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (src.isUndefined()) {
output.setUndefined();
} else {
- new (output.getstringptr()) QString(QString::number(src.getqreal()));
+ new (output.getstringptr()) QString(QString::number(src.getnumber(), 'g', 16));
STRING_REGISTER(instr->unaryop.output);
}
}
- QML_V4_END_INSTR(ConvertRealToString, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToString, unaryop)
QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
{
@@ -1026,7 +987,7 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertStringToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertStringToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
@@ -1041,10 +1002,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
output.cleanupString();
MARK_CLEAN_REGISTER(instr->unaryop.output);
}
- output.setqreal(tmp.toNumber());
+ output.setnumber(tmp.toNumber());
}
}
- QML_V4_END_INSTR(ConvertStringToReal, unaryop)
+ QML_V4_END_INSTR(ConvertStringToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
{
@@ -1190,75 +1151,75 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ResolveUrl, unaryop)
- QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathSinNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qSin(src.getqreal()));
+ else output.setnumber(qSin(src.getnumber()));
}
- QML_V4_END_INSTR(MathSinReal, unaryop)
+ QML_V4_END_INSTR(MathSinNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathCosReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathCosNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qCos(src.getqreal()));
+ else output.setnumber(qCos(src.getnumber()));
}
- QML_V4_END_INSTR(MathCosReal, unaryop)
+ QML_V4_END_INSTR(MathCosNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathAbsReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathAbsNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qAbs(src.getqreal()));
+ else output.setnumber(qAbs(src.getnumber()));
}
- QML_V4_END_INSTR(MathAbsReal, unaryop)
+ QML_V4_END_INSTR(MathAbsNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathRoundReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathRoundNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qRound(src.getqreal()));
+ else output.setint(qRound(src.getnumber()));
}
- QML_V4_END_INSTR(MathRoundReal, unaryop)
+ QML_V4_END_INSTR(MathRoundNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathFloorReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathFloorNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qFloor(src.getqreal()));
+ else output.setint(qFloor(src.getnumber()));
}
- QML_V4_END_INSTR(MathFloorReal, unaryop)
+ QML_V4_END_INSTR(MathFloorNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathCeilReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathCeilNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qCeil(src.getqreal()));
+ else output.setint(qCeil(src.getnumber()));
}
- QML_V4_END_INSTR(MathCeilReal, unaryop)
+ QML_V4_END_INSTR(MathCeilNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathPINumber, unaryop)
{
- static const qreal qmlPI = 2.0 * qAsin(1.0);
+ static const double qmlPI = 2.0 * qAsin(1.0);
Register &output = registers[instr->unaryop.output];
- output.setqreal(qmlPI);
+ output.setnumber(qmlPI);
}
- QML_V4_END_INSTR(MathPIReal, unaryop)
+ QML_V4_END_INSTR(MathPINumber, unaryop)
QML_V4_BEGIN_INSTR(LoadNull, null_value)
registers[instr->null_value.reg].setNull();
QML_V4_END_INSTR(LoadNull, null_value)
- QML_V4_BEGIN_INSTR(LoadReal, real_value)
- registers[instr->real_value.reg].setqreal(instr->real_value.value);
- QML_V4_END_INSTR(LoadReal, real_value)
+ QML_V4_BEGIN_INSTR(LoadNumber, number_value)
+ registers[instr->number_value.reg].setnumber(instr->number_value.value);
+ QML_V4_END_INSTR(LoadNumber, number_value)
QML_V4_BEGIN_INSTR(LoadInt, int_value)
registers[instr->int_value.reg].setint(instr->int_value.value);
@@ -1305,12 +1266,12 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(BitXorInt, binaryop)
- QML_V4_BEGIN_INSTR(AddReal, binaryop)
+ QML_V4_BEGIN_INSTR(AddNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() +
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() +
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(AddReal, binaryop)
+ QML_V4_END_INSTR(AddNumber, binaryop)
QML_V4_BEGIN_INSTR(AddString, binaryop)
{
@@ -1324,36 +1285,33 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(AddString, binaryop)
- QML_V4_BEGIN_INSTR(SubReal, binaryop)
+ QML_V4_BEGIN_INSTR(SubNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() -
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() -
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(SubReal, binaryop)
+ QML_V4_END_INSTR(SubNumber, binaryop)
- QML_V4_BEGIN_INSTR(MulReal, binaryop)
+ QML_V4_BEGIN_INSTR(MulNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() *
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() *
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(MulReal, binaryop)
+ QML_V4_END_INSTR(MulNumber, binaryop)
- QML_V4_BEGIN_INSTR(DivReal, binaryop)
+ QML_V4_BEGIN_INSTR(DivNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() /
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() /
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(DivReal, binaryop)
+ QML_V4_END_INSTR(DivNumber, binaryop)
- QML_V4_BEGIN_INSTR(ModReal, binaryop)
+ QML_V4_BEGIN_INSTR(ModNumber, binaryop)
{
Register &target = registers[instr->binaryop.output];
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
- if (QMetaType::QReal == QMetaType::Float)
- target.setqreal(::fmodf(left.getqreal(), right.getqreal()));
- else
- target.setqreal(::fmod(left.getqreal(), right.getqreal()));
+ target.setnumber(::fmod(left.getnumber(), right.getnumber()));
}
QML_V4_END_INSTR(ModInt, binaryop)
@@ -1378,61 +1336,61 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(URShiftInt, binaryop)
- QML_V4_BEGIN_INSTR(GtReal, binaryop)
+ QML_V4_BEGIN_INSTR(GtNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(GtReal, binaryop)
+ QML_V4_END_INSTR(GtNumber, binaryop)
- QML_V4_BEGIN_INSTR(LtReal, binaryop)
+ QML_V4_BEGIN_INSTR(LtNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(LtReal, binaryop)
+ QML_V4_END_INSTR(LtNumber, binaryop)
- QML_V4_BEGIN_INSTR(GeReal, binaryop)
+ QML_V4_BEGIN_INSTR(GeNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(GeReal, binaryop)
+ QML_V4_END_INSTR(GeNumber, binaryop)
- QML_V4_BEGIN_INSTR(LeReal, binaryop)
+ QML_V4_BEGIN_INSTR(LeNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(LeReal, binaryop)
+ QML_V4_END_INSTR(LeNumber, binaryop)
- QML_V4_BEGIN_INSTR(EqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(EqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(EqualReal, binaryop)
+ QML_V4_END_INSTR(EqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(NotEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(NotEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(NotEqualReal, binaryop)
+ QML_V4_END_INSTR(NotEqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(StrictEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(StrictEqualReal, binaryop)
+ QML_V4_END_INSTR(StrictEqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(StrictNotEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(StrictNotEqualReal, binaryop)
+ QML_V4_END_INSTR(StrictNotEqualNumber, binaryop)
QML_V4_BEGIN_INSTR(GtString, binaryop)
{
@@ -1578,25 +1536,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(StrictNotEqualObject, binaryop)
- QML_V4_BEGIN_INSTR(MathMaxReal, binaryop)
+ QML_V4_BEGIN_INSTR(MathMaxNumber, binaryop)
{
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
Register &output = registers[instr->binaryop.output];
if (left.isUndefined() || right.isUndefined()) output.setUndefined();
- else output.setqreal(qMax(left.getqreal(), right.getqreal()));
+ else output.setnumber(qMax(left.getnumber(), right.getnumber()));
}
- QML_V4_END_INSTR(MathMaxReal, binaryop)
+ QML_V4_END_INSTR(MathMaxNumber, binaryop)
- QML_V4_BEGIN_INSTR(MathMinReal, binaryop)
+ QML_V4_BEGIN_INSTR(MathMinNumber, binaryop)
{
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
Register &output = registers[instr->binaryop.output];
if (left.isUndefined() || right.isUndefined()) output.setUndefined();
- else output.setqreal(qMin(left.getqreal(), right.getqreal()));
+ else output.setnumber(qMin(left.getnumber(), right.getnumber()));
}
- QML_V4_END_INSTR(MathMinReal, binaryop)
+ QML_V4_END_INSTR(MathMinNumber, binaryop)
QML_V4_BEGIN_INSTR(NewString, construct)
{
@@ -1625,11 +1583,17 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (!object) {
THROW_EXCEPTION(instr->fetch.exceptionId);
} else {
- reg.init((Register::Type)instr->fetch.valueType);
+ const Register::Type valueType = (Register::Type)instr->fetch.valueType;
+ reg.init(valueType);
if (instr->fetch.valueType >= FirstCleanupType)
MARK_REGISTER(instr->fetch.reg);
void *argv[] = { reg.typeDataPtr(), 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
+ if (valueType == FloatType) {
+ // promote floats
+ const double v = reg.getfloat();
+ reg.setnumber(v);
+ }
}
}
QML_V4_END_INSTR(Fetch, fetch)
@@ -1649,6 +1613,30 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (data.isUndefined())
THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
+ if (data.gettype() == QObjectStarType) {
+ if (QObject *dataObject = data.getQObject()) {
+ const QMetaObject *dataMo = dataObject->metaObject();
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ QMetaProperty receiver = output->metaObject()->property(instr->store.index);
+ const QMetaObject *receiverMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, receiver.userType());
+
+ // Verify that these types are compatible
+ if (!QQmlPropertyPrivate::canConvert(dataMo, receiverMo)) {
+ THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") +
+ QLatin1String(dataMo->className()) +
+ QLatin1String(" to ") +
+ QLatin1String(receiverMo->className()));
+ }
+ }
+ }
+
+ if (instr->store.valueType == FloatType) {
+ // cast numbers to floats
+ const float v = (float) data.getnumber();
+ data.setfloat(v);
+ }
+
int status = -1;
void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
QMetaObject::metacall(output, QMetaObject::WriteProperty,
@@ -1687,22 +1675,14 @@ void QV4Bindings::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));
-
-// QString str = QString::fromRawData(strdata, len);
-
-// // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
-// }
- QML_V4_END_INSTR(InitString, initstring)
-
QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
registers[instr->cleanup.reg].cleanup();
QML_V4_END_INSTR(CleanupRegister, cleanup)
+ QML_V4_BEGIN_INSTR(Throw, throwop)
+ THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr());
+ QML_V4_END_INSTR(Throw, throwop)
+
#ifdef QML_THREADED_INTERPRETER
// nothing to do
#else
diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h
index 1824fa4ee9..3a7d175d7b 100644
--- a/src/qml/qml/v4/qv4bindings_p.h
+++ b/src/qml/qml/v4/qv4bindings_p.h
@@ -141,9 +141,9 @@ private:
inline void subscribeId(QQmlContextData *p, int idIndex, int subIndex);
inline void subscribe(QObject *o, int notifyIndex, int subIndex);
- inline static qint32 toInt32(qreal n);
- static const qreal D32;
- static quint32 toUint32(qreal n);
+ inline static qint32 toInt32(double n);
+ static const double D32;
+ static quint32 toUint32(double n);
};
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index c9495e8987..045a14fbb5 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -62,7 +62,9 @@ static bool qmlEnableV4 = true;
using namespace QQmlJS;
QV4CompilerPrivate::QV4CompilerPrivate()
- : _function(0) , _block(0) , _discarded(false), registerCount(0)
+ : subscriptionOffset(0)
+ , _function(0) , _block(0) , _discarded(false), registerCount(0)
+ , bindingLine(0), bindingColumn(0)
{
}
@@ -73,6 +75,8 @@ void QV4CompilerPrivate::trace(int line, int column)
{
bytecode.clear();
+ this->bindingLine = line;
+ this->bindingColumn = column;
this->currentReg = _function->tempCount;
this->registerCount = qMax(this->registerCount, this->currentReg);
@@ -226,8 +230,9 @@ void QV4CompilerPrivate::visitConst(IR::Const *e)
gen(i);
} break;
- case IR::RealType: {
- Instr::LoadReal i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::LoadNumber i;
i.reg = currentReg;
i.value = e->value;
gen(i);
@@ -316,7 +321,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
Instr::LoadAttached attached;
attached.output = currentReg;
attached.reg = currentReg;
- attached.exceptionId = exceptionId(e->line, e->column);
+ attached.exceptionId = exceptionId(bindingLine, bindingColumn);
if (e->declarativeType->attachedPropertiesId() == -1)
discard();
attached.id = e->declarativeType->attachedPropertiesId();
@@ -351,8 +356,11 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
QQmlRegisterType regType;
switch (propTy) {
- case QMetaType::QReal:
- regType = QRealType;
+ case QMetaType::Float:
+ regType = FloatType;
+ break;
+ case QMetaType::Double:
+ regType = NumberType;
break;
case QMetaType::Bool:
regType = BoolType;
@@ -373,7 +381,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
default:
if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
regType = PODValueType;
- } else if (QQmlMetaType::isQObject(propTy)) {
+ } else if (engine->metaObjectForType(propTy)) {
regType = QObjectStarType;
} else {
if (qmlVerboseCompiler())
@@ -458,14 +466,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
} break;
case IR::OpUMinus:
- if (e->expr->type == IR::RealType) {
- Instr::UnaryMinusReal i;
+ if (IR::isRealType(e->expr->type)) {
+ Instr::UnaryMinusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
- convertToReal(e->expr, currentReg);
- Instr::UnaryMinusReal i;
+ convertToNumber(e->expr, currentReg);
+ Instr::UnaryMinusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
@@ -475,14 +483,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
break;
case IR::OpUPlus:
- if (e->expr->type == IR::RealType) {
- Instr::UnaryPlusReal i;
+ if (IR::isRealType(e->expr->type)) {
+ Instr::UnaryPlusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
- convertToReal(e->expr, currentReg);
- Instr::UnaryPlusReal i;
+ convertToNumber(e->expr, currentReg);
+ Instr::UnaryPlusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
@@ -522,25 +530,26 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
} // switch
}
-void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg)
+void QV4CompilerPrivate::convertToNumber(IR::Expr *expr, int reg)
{
- if (expr->type == IR::RealType)
+ if (expr->type == IR::NumberType)
return;
switch (expr->type) {
case IR::BoolType: {
- Instr::ConvertBoolToReal i;
+ Instr::ConvertBoolToNumber i;
i.output = i.src = reg;
gen(i);
} break;
case IR::IntType: {
- Instr::ConvertIntToReal i;
+ Instr::ConvertIntToNumber i;
i.output = i.src = reg;
gen(i);
} break;
- case IR::RealType:
+ case IR::FloatType:
+ case IR::NumberType:
// nothing to do
return;
@@ -566,8 +575,9 @@ void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg)
// nothing to do
return;
- case IR::RealType: {
- Instr::ConvertRealToInt i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::ConvertNumberToInt i;
i.output = i.src = reg;
gen(i);
} break;
@@ -594,8 +604,9 @@ void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg)
gen(i);
} break;
- case IR::RealType: {
- Instr::ConvertRealToBool i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::ConvertNumberToBool i;
i.output = i.src = reg;
gen(i);
} return;
@@ -643,19 +654,19 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
case IR::OpAdd:
if (e->type == IR::StringType)
return V4Instr::AddString;
- return V4Instr::AddReal;
+ return V4Instr::AddNumber;
case IR::OpSub:
- return V4Instr::SubReal;
+ return V4Instr::SubNumber;
case IR::OpMul:
- return V4Instr::MulReal;
+ return V4Instr::MulNumber;
case IR::OpDiv:
- return V4Instr::DivReal;
+ return V4Instr::DivNumber;
case IR::OpMod:
- return V4Instr::ModReal;
+ return V4Instr::ModNumber;
case IR::OpLShift:
return V4Instr::LShiftInt;
@@ -669,50 +680,50 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
case IR::OpGt:
if (e->left->type == IR::StringType)
return V4Instr::GtString;
- return V4Instr::GtReal;
+ return V4Instr::GtNumber;
case IR::OpLt:
if (e->left->type == IR::StringType)
return V4Instr::LtString;
- return V4Instr::LtReal;
+ return V4Instr::LtNumber;
case IR::OpGe:
if (e->left->type == IR::StringType)
return V4Instr::GeString;
- return V4Instr::GeReal;
+ return V4Instr::GeNumber;
case IR::OpLe:
if (e->left->type == IR::StringType)
return V4Instr::LeString;
- return V4Instr::LeReal;
+ return V4Instr::LeNumber;
case IR::OpEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::EqualObject;
if (e->left->type == IR::StringType)
return V4Instr::EqualString;
- return V4Instr::EqualReal;
+ return V4Instr::EqualNumber;
case IR::OpNotEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::NotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::NotEqualString;
- return V4Instr::NotEqualReal;
+ return V4Instr::NotEqualNumber;
case IR::OpStrictEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::StrictEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictEqualString;
- return V4Instr::StrictEqualReal;
+ return V4Instr::StrictEqualNumber;
case IR::OpStrictNotEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::StrictNotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictNotEqualString;
- return V4Instr::StrictNotEqualReal;
+ return V4Instr::StrictNotEqualNumber;
case IR::OpAnd:
case IR::OpOr:
@@ -733,12 +744,26 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
int left = currentReg;
int right = currentReg + 1;
- traceExpression(e->left, left);
- traceExpression(e->right, right);
+ if (e->left->asTemp() && e->type != IR::StringType)
+ left = e->left->asTemp()->index;
+ else
+ traceExpression(e->left, left);
- // At this point it is possible that the type of the
- // subexpressions is different. This can happen because
- // we keep BINOP expressions in HIR.
+ if (IR::Temp *t = e->right->asTemp())
+ right = t->index;
+ else
+ traceExpression(e->right, right);
+
+ if (e->left->type != e->right->type) {
+ if (qmlVerboseCompiler())
+ qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op)
+ << "(`" << IR::binaryOperator(e->left->type)
+ << "' and `"
+ << IR::binaryOperator(e->right->type)
+ << "'";
+ discard();
+ return;
+ }
switch (e->op) {
case IR::OpInvalid:
@@ -766,8 +791,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpAdd:
if (e->type != IR::StringType) {
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
}
break;
@@ -775,8 +800,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpMul:
case IR::OpDiv:
case IR::OpMod:
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
break;
case IR::OpGt:
@@ -788,8 +813,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpStrictEqual:
case IR::OpStrictNotEqual:
if (e->left->type >= IR::FirstNumberType) {
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
}
break;
@@ -813,7 +838,7 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
{
if (IR::Name *name = call->base->asName()) {
IR::Expr *arg = call->onlyArgument();
- if (arg != 0 && arg->type == IR::RealType) {
+ if (arg != 0 && IR::isRealType(arg->type)) {
traceExpression(arg, currentReg);
switch (name->builtin) {
@@ -821,37 +846,37 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
break;
case IR::MathSinBultinFunction: {
- Instr::MathSinReal i;
+ Instr::MathSinNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathCosBultinFunction: {
- Instr::MathCosReal i;
+ Instr::MathCosNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathAbsBuiltinFunction: {
- Instr::MathAbsReal i;
+ Instr::MathAbsNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathRoundBultinFunction: {
- Instr::MathRoundReal i;
+ Instr::MathRoundNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathFloorBultinFunction: {
- Instr::MathFloorReal i;
+ Instr::MathFloorNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathCeilBuiltinFunction: {
- Instr::MathCeilReal i;
+ Instr::MathCeilNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
@@ -869,21 +894,21 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
IR::Expr *arg1 = call->args->expr;
IR::Expr *arg2 = call->args->next->expr;
- if (arg1 != 0 && arg1->type == IR::RealType &&
- arg2 != 0 && arg2->type == IR::RealType) {
+ if (arg1 != 0 && IR::isRealType(arg1->type) &&
+ arg2 != 0 && IR::isRealType(arg2->type)) {
traceExpression(arg1, currentReg);
traceExpression(arg2, currentReg + 1);
if (name->builtin == IR::MathMaxBuiltinFunction) {
- Instr::MathMaxReal i;
+ Instr::MathMaxNumber i;
i.left = currentReg;
i.right = currentReg + 1;
i.output = currentReg;
gen(i);
return;
} else if (name->builtin == IR::MathMinBuiltinFunction) {
- Instr::MathMinReal i;
+ Instr::MathMinNumber i;
i.left = currentReg;
i.right = currentReg + 1;
i.output = currentReg;
@@ -917,7 +942,17 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
quint8 dest = target->index;
- if (target->type != s->source->type) {
+ IR::Type targetTy = s->target->type;
+ IR::Type sourceTy = s->source->type;
+
+ // promote the floats
+ if (sourceTy == IR::FloatType)
+ sourceTy = IR::NumberType;
+
+ if (targetTy == IR::FloatType)
+ targetTy = IR::NumberType;
+
+ if (sourceTy != targetTy) {
quint8 src = dest;
if (IR::Temp *t = s->source->asTemp())
@@ -926,8 +961,6 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
traceExpression(s->source, dest);
V4Instr::Type opcode = V4Instr::Noop;
- IR::Type targetTy = s->target->type;
- IR::Type sourceTy = s->source->type;
if (sourceTy == IR::UrlType) {
switch (targetTy) {
@@ -937,13 +970,22 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
// url-to-xxx conversions.
break;
default: {
+ if (s->isMoveForReturn) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
// generate a UrlToString conversion and fix
// the type of the source expression.
V4Instr conv;
- conv.unaryop.output = V4Instr::ConvertUrlToString;
+ conv.unaryop.output = src;
conv.unaryop.src = src;
- gen(opcode, conv);
-
+ gen(V4Instr::ConvertUrlToString, conv);
sourceTy = IR::StringType;
break;
}
@@ -953,7 +995,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
if (targetTy == IR::BoolType) {
switch (sourceTy) {
case IR::IntType: opcode = V4Instr::ConvertIntToBool; break;
- case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
+ case IR::NumberType: opcode = V4Instr::ConvertNumberToBool; break;
case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
@@ -963,33 +1005,44 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
} else if (targetTy == IR::IntType) {
switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break;
- case IR::RealType: {
+ case IR::NumberType: {
if (s->isMoveForReturn)
- opcode = V4Instr::MathRoundReal;
+ opcode = V4Instr::MathRoundNumber;
else
- opcode = V4Instr::ConvertRealToInt;
+ opcode = V4Instr::ConvertNumberToInt;
break;
}
case IR::StringType: opcode = V4Instr::ConvertStringToInt; break;
default: break;
} // switch
- } else if (targetTy == IR::RealType) {
+ } else if (IR::isRealType(targetTy)) {
switch (sourceTy) {
- case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break;
- case IR::IntType: opcode = V4Instr::ConvertIntToReal; break;
- case IR::StringType: opcode = V4Instr::ConvertStringToReal; break;
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToNumber; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToNumber; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToNumber; break;
default: break;
} // switch
} else if (targetTy == IR::StringType) {
switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break;
case IR::IntType: opcode = V4Instr::ConvertIntToString; break;
- case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
+ case IR::NumberType: opcode = V4Instr::ConvertNumberToString; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToString; break;
default: break;
} // switch
} else if (targetTy == IR::UrlType) {
+ if (s->isMoveForReturn && sourceTy != IR::StringType) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
+
V4Instr convToString;
convToString.unaryop.output = dest;
convToString.unaryop.src = src;
@@ -998,7 +1051,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
switch (sourceTy) {
case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break;
case IR::IntType: gen(V4Instr::ConvertIntToString, convToString); sourceTy = IR::StringType; break;
- case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break;
+ case IR::NumberType: gen(V4Instr::ConvertNumberToString, convToString); sourceTy = IR::StringType; break;
case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break;
default: break;
} // switch
@@ -1094,8 +1147,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
case IR::IntType:
test.regType = QMetaType::Int;
break;
- case IR::RealType:
- test.regType = QMetaType::QReal;
+ case IR::FloatType:
+ case IR::NumberType:
+ test.regType = QMetaType::Double;
break;
default:
discard();
@@ -1108,6 +1162,7 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
store.output = 0;
store.index = expression->property->index;
store.reg = storeReg;
+ store.valueType = s->type == IR::FloatType ? FloatType : 0;
store.exceptionId = exceptionId(s->line, s->column);
gen(store);
}
@@ -1119,7 +1174,6 @@ void QV4Compiler::dump(const QByteArray &programData)
qWarning() << "Program.bindings:" << program->bindings;
qWarning() << "Program.dataLength:" << program->dataLength;
qWarning() << "Program.subscriptions:" << program->subscriptions;
- qWarning() << "Program.indentifiers:" << program->identifiers;
const int programSize = program->instructionCount;
const char *start = program->instructions();
@@ -1137,8 +1191,8 @@ void QV4CompilerPrivate::resetInstanceState()
data = committed.data;
exceptions = committed.exceptions;
usedSubscriptionIds.clear();
- subscriptionIds = committed.subscriptionIds;
- registeredStrings = committed.registeredStrings;
+ subscriptionIds.clear();
+ subscriptionOffset = committed.subscriptionCount;
bytecode.clear();
patches.clear();
pool.clear();
@@ -1159,8 +1213,9 @@ int QV4CompilerPrivate::commitCompile()
committed.bytecode.append(bytecode.constData(), bytecode.size());
committed.data = data;
committed.exceptions = exceptions;
- committed.subscriptionIds = subscriptionIds;
- committed.registeredStrings = registeredStrings;
+ committed.subscriptionCount = subscriptionOffset + subscriptionIds.count();
+ if (bindingsDump())
+ committed.subscriptions.append(subscriptionIds);
return rv;
}
@@ -1212,7 +1267,7 @@ bool QV4CompilerPrivate::compile(QQmlJS::AST::Node *node)
qerr << endl;
}
- if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31)
+ if (discarded || subscriptionIds.count() > 0xFFFF || registerCount > 31)
return false;
return true;
@@ -1236,32 +1291,6 @@ int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str)
return reg;
}
-// Returns an identifier offset
-int QV4CompilerPrivate::registerString(const QString &string)
-{
- Q_ASSERT(!string.isEmpty());
-
- QPair<int, int> *iter = registeredStrings.value(string);
-
- if (!iter) {
- quint32 len = string.length();
- QByteArray lendata((const char *)&len, sizeof(quint32));
- QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar));
- strdata.prepend(lendata);
- int rv = data.count();
- data += strdata;
-
- iter = &registeredStrings[string];
- *iter = qMakePair(registeredStrings.count(), rv);
- }
-
- Instr::InitString reg;
- reg.offset = iter->first;
- reg.dataIdx = iter->second;
- gen(reg);
- return reg.offset;
-}
-
/*!
Returns true if the current expression has not already subscribed to \a sub in currentBlockMask.
*/
@@ -1285,7 +1314,7 @@ int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub)
QString str = sub.join(QLatin1String("."));
int *iter = subscriptionIds.value(str);
if (!iter) {
- int count = subscriptionIds.count();
+ int count = subscriptionOffset + subscriptionIds.count();
iter = &subscriptionIds[str];
*iter = count;
}
@@ -1384,8 +1413,8 @@ QByteArray QV4CompilerPrivate::buildSignalTable() const
QVector<quint32> header;
QVector<quint32> data;
- for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
- header.append(committed.subscriptionIds.count() + data.count());
+ for (int ii = 0; ii < committed.subscriptionCount; ++ii) {
+ header.append(committed.subscriptionCount + data.count());
const QList<QPair<int, quint32> > &bindings = table[ii];
data.append(bindings.count());
for (int jj = 0; jj < bindings.count(); ++jj) {
@@ -1443,8 +1472,7 @@ QByteArray QV4Compiler::program() const
data += d->buildExceptionData();
prog.dataLength = 4 * ((data.size() + 3) / 4);
- prog.subscriptions = d->committed.subscriptionIds.count();
- prog.identifiers = d->committed.registeredStrings.count();
+ prog.subscriptions = d->committed.subscriptionCount;
prog.instructionCount = bytecode.count();
int size = sizeof(QV4Program) + bytecode.count();
size += prog.dataLength;
@@ -1461,12 +1489,13 @@ QByteArray QV4Compiler::program() const
if (bindingsDump()) {
qWarning().nospace() << "Subscription slots:";
- for (QQmlAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin();
- iter != d->committed.subscriptionIds.end();
- ++iter) {
- qWarning().nospace() << " " << iter->first << "\t-> " << iter->second;
+ QQmlAssociationList<QString, int> subscriptionIds;
+ foreach (subscriptionIds, d->committed.subscriptions) {
+ for (QQmlAssociationList<QString, int>::ConstIterator iter = subscriptionIds.begin();
+ iter != subscriptionIds.end(); ++iter) {
+ qWarning().nospace() << " " << iter->first << "\t-> " << iter->second;
+ }
}
-
QV4Compiler::dump(programData);
}
diff --git a/src/qml/qml/v4/qv4compiler_p_p.h b/src/qml/qml/v4/qv4compiler_p_p.h
index a9209d978f..0c06ade87f 100644
--- a/src/qml/qml/v4/qv4compiler_p_p.h
+++ b/src/qml/qml/v4/qv4compiler_p_p.h
@@ -128,8 +128,6 @@ public:
bool compile(QQmlJS::AST::Node *);
int registerLiteralString(quint8 reg, const QStringRef &);
- int registerString(const QString &);
- QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
QByteArray data;
bool blockNeedsSubscription(const QStringList &);
@@ -141,7 +139,7 @@ public:
QVector<quint64> exceptions;
QQmlAssociationList<int, quint32> usedSubscriptionIds;
-
+ int subscriptionOffset;
QQmlAssociationList<QString, int> subscriptionIds;
QQmlJS::Bytecode bytecode;
@@ -156,17 +154,17 @@ public:
QQmlPool pool;
// Committed binding data
- struct {
+ struct Committed {
+ Committed(): subscriptionCount(0) {}
QList<int> offsets;
QList<QQmlAssociationList<int, quint32> > dependencies;
//QQmlJS::Bytecode bytecode;
QByteArray bytecode;
QByteArray data;
- QQmlAssociationList<QString, int> subscriptionIds;
QVector<quint64> exceptions;
-
- QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
+ int subscriptionCount;
+ QList<QQmlAssociationList<QString, int> > subscriptions;
int count() const { return offsets.count(); }
} committed;
@@ -174,7 +172,7 @@ public:
QByteArray buildSignalTable() const;
QByteArray buildExceptionData() const;
- void convertToReal(QQmlJS::IR::Expr *expr, int reg);
+ void convertToNumber(QQmlJS::IR::Expr *expr, int reg);
void convertToInt(QQmlJS::IR::Expr *expr, int reg);
void convertToBool(QQmlJS::IR::Expr *expr, int reg);
quint8 instructionOpcode(QQmlJS::IR::Binop *e);
@@ -235,6 +233,8 @@ private:
bool usedSubscriptionIdsChanged;
quint32 currentBlockMask;
+ int bindingLine;
+ int bindingColumn;
};
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index cb6ff40589..ecd4f01ef3 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -123,14 +123,14 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::UnaryNot:
INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::UnaryMinusReal:
- INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::UnaryMinusNumber:
+ INSTR_DUMP << "\t" << "UnaryMinusNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::UnaryMinusInt:
INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::UnaryPlusReal:
- INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::UnaryPlusNumber:
+ INSTR_DUMP << "\t" << "UnaryPlusNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::UnaryPlusInt:
INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -138,8 +138,8 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertBoolToInt:
INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertBoolToReal:
- INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertBoolToNumber:
+ INSTR_DUMP << "\t" << "ConvertBoolToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertBoolToString:
INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -147,20 +147,20 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertIntToBool:
INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertIntToReal:
- INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertIntToNumber:
+ INSTR_DUMP << "\t" << "ConvertIntToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertIntToString:
INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToBool:
- INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToBool:
+ INSTR_DUMP << "\t" << "ConvertNumberToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToInt:
- INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToInt:
+ INSTR_DUMP << "\t" << "ConvertNumberToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToString:
- INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToString:
+ INSTR_DUMP << "\t" << "ConvertNumberToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertStringToBool:
INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -168,8 +168,8 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertStringToInt:
INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertStringToReal:
- INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertStringToNumber:
+ INSTR_DUMP << "\t" << "ConvertStringToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertStringToUrl:
INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -198,32 +198,32 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ResolveUrl:
INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathSinReal:
- INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathSinNumber:
+ INSTR_DUMP << "\t" << "MathSinNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathCosReal:
- INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathCosNumber:
+ INSTR_DUMP << "\t" << "MathCosNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathAbsReal:
- INSTR_DUMP << "\t" << "MathAbsReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathAbsNumber:
+ INSTR_DUMP << "\t" << "MathAbsNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathRoundReal:
- INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathRoundNumber:
+ INSTR_DUMP << "\t" << "MathRoundNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathFloorReal:
- INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathFloorNumber:
+ INSTR_DUMP << "\t" << "MathFloorNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathCeilReal:
- INSTR_DUMP << "\t" << "MathCeilReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathCeilNumber:
+ INSTR_DUMP << "\t" << "MathCeilNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathPIReal:
- INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathPINumber:
+ INSTR_DUMP << "\t" << "MathPINumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::LoadNull:
INSTR_DUMP << "\t" << "LoadNull" << "\t\t" << "Constant(null) -> Output_Reg(" << i->null_value.reg << ")";
break;
- case V4Instr::LoadReal:
- INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
+ case V4Instr::LoadNumber:
+ INSTR_DUMP << "\t" << "LoadNumber" << "\t\t" << "Constant(" << i->number_value.value << ") -> Output_Reg(" << i->number_value.reg << ")";
break;
case V4Instr::LoadInt:
INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")";
@@ -249,23 +249,23 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::BitXorInt:
INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::AddReal:
- INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::AddNumber:
+ INSTR_DUMP << "\t" << "AddNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::AddString:
INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::SubReal:
- INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::SubNumber:
+ INSTR_DUMP << "\t" << "SubNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MulReal:
- INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MulNumber:
+ INSTR_DUMP << "\t" << "MulNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::DivReal:
- INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::DivNumber:
+ INSTR_DUMP << "\t" << "DivNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::ModReal:
- INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::ModNumber:
+ INSTR_DUMP << "\t" << "ModNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::LShiftInt:
INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
@@ -276,29 +276,29 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::URShiftInt:
INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::GtReal:
- INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::GtNumber:
+ INSTR_DUMP << "\t" << "GtNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::LtReal:
- INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::LtNumber:
+ INSTR_DUMP << "\t" << "LtNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::GeReal:
- INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::GeNumber:
+ INSTR_DUMP << "\t" << "GeNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::LeReal:
- INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::LeNumber:
+ INSTR_DUMP << "\t" << "LeNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::EqualReal:
- INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::EqualNumber:
+ INSTR_DUMP << "\t" << "EqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::NotEqualReal:
- INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::NotEqualNumber:
+ INSTR_DUMP << "\t" << "NotEqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::StrictEqualReal:
- INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::StrictEqualNumber:
+ INSTR_DUMP << "\t" << "StrictEqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::StrictNotEqualReal:
- INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::StrictNotEqualNumber:
+ INSTR_DUMP << "\t" << "StrictNotEqualNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::GtString:
INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
@@ -336,11 +336,11 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::StrictNotEqualObject:
INSTR_DUMP << "\t" << "StrictNotEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MathMaxReal:
- INSTR_DUMP << "\t" << "MathMaxReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MathMaxNumber:
+ INSTR_DUMP << "\t" << "MathMaxNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MathMinReal:
- INSTR_DUMP << "\t" << "MathMinReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MathMinNumber:
+ INSTR_DUMP << "\t" << "MathMinNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::NewString:
INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")";
@@ -376,12 +376,12 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::Branch:
INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")";
break;
- case V4Instr::InitString:
- INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")";
- break;
case V4Instr::Block:
INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")";
break;
+ case V4Instr::Throw:
+ INSTR_DUMP << "\t" << "Throw" << "\t\t\t" << "InputReg(" << i->throwop.message << ")";
+ break;
default:
INSTR_DUMP << "\t" << "Unknown";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index 239cb362cc..310bfbaff5 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -76,22 +76,22 @@ QT_BEGIN_NAMESPACE
F(LoadModuleObject, load) \
F(LoadAttached, attached) \
F(UnaryNot, unaryop) \
- F(UnaryMinusReal, unaryop) \
+ F(UnaryMinusNumber, unaryop) \
F(UnaryMinusInt, unaryop) \
- F(UnaryPlusReal, unaryop) \
+ F(UnaryPlusNumber, unaryop) \
F(UnaryPlusInt, unaryop) \
F(ConvertBoolToInt, unaryop) \
- F(ConvertBoolToReal, unaryop) \
+ F(ConvertBoolToNumber, unaryop) \
F(ConvertBoolToString, unaryop) \
F(ConvertIntToBool, unaryop) \
- F(ConvertIntToReal, unaryop) \
+ F(ConvertIntToNumber, unaryop) \
F(ConvertIntToString, unaryop) \
- F(ConvertRealToBool, unaryop) \
- F(ConvertRealToInt, unaryop) \
- F(ConvertRealToString, unaryop) \
+ F(ConvertNumberToBool, unaryop) \
+ F(ConvertNumberToInt, unaryop) \
+ F(ConvertNumberToString, unaryop) \
F(ConvertStringToBool, unaryop) \
F(ConvertStringToInt, unaryop) \
- F(ConvertStringToReal, unaryop) \
+ F(ConvertStringToNumber, unaryop) \
F(ConvertStringToUrl, unaryop) \
F(ConvertStringToColor, unaryop) \
F(ConvertUrlToBool, unaryop) \
@@ -101,15 +101,15 @@ QT_BEGIN_NAMESPACE
F(ConvertObjectToBool, unaryop) \
F(ConvertNullToObject, unaryop) \
F(ResolveUrl, unaryop) \
- F(MathSinReal, unaryop) \
- F(MathCosReal, unaryop) \
- F(MathAbsReal, unaryop) \
- F(MathRoundReal, unaryop) \
- F(MathFloorReal, unaryop) \
- F(MathCeilReal, unaryop) \
- F(MathPIReal, unaryop) \
+ F(MathSinNumber, unaryop) \
+ F(MathCosNumber, unaryop) \
+ F(MathAbsNumber, unaryop) \
+ F(MathRoundNumber, unaryop) \
+ F(MathFloorNumber, unaryop) \
+ F(MathCeilNumber, unaryop) \
+ F(MathPINumber, unaryop) \
F(LoadNull, null_value) \
- F(LoadReal, real_value) \
+ F(LoadNumber, number_value) \
F(LoadInt, int_value) \
F(LoadBool, bool_value) \
F(LoadString, string_value) \
@@ -118,23 +118,23 @@ QT_BEGIN_NAMESPACE
F(BitAndInt, binaryop) \
F(BitOrInt, binaryop) \
F(BitXorInt, binaryop) \
- F(AddReal, binaryop) \
+ F(AddNumber, binaryop) \
F(AddString, binaryop) \
- F(SubReal, binaryop) \
- F(MulReal, binaryop) \
- F(DivReal, binaryop) \
- F(ModReal, binaryop) \
+ F(SubNumber, binaryop) \
+ F(MulNumber, binaryop) \
+ F(DivNumber, binaryop) \
+ F(ModNumber, binaryop) \
F(LShiftInt, binaryop) \
F(RShiftInt, binaryop) \
F(URShiftInt, binaryop) \
- F(GtReal, binaryop) \
- F(LtReal, binaryop) \
- F(GeReal, binaryop) \
- F(LeReal, binaryop) \
- F(EqualReal, binaryop) \
- F(NotEqualReal, binaryop) \
- F(StrictEqualReal, binaryop) \
- F(StrictNotEqualReal, binaryop) \
+ F(GtNumber, binaryop) \
+ F(LtNumber, binaryop) \
+ F(GeNumber, binaryop) \
+ F(LeNumber, binaryop) \
+ F(EqualNumber, binaryop) \
+ F(NotEqualNumber, binaryop) \
+ F(StrictEqualNumber, binaryop) \
+ F(StrictNotEqualNumber, binaryop) \
F(GtString, binaryop) \
F(LtString, binaryop) \
F(GeString, binaryop) \
@@ -147,8 +147,8 @@ QT_BEGIN_NAMESPACE
F(NotEqualObject, binaryop) \
F(StrictEqualObject, binaryop) \
F(StrictNotEqualObject, binaryop) \
- F(MathMaxReal, binaryop) \
- F(MathMinReal, binaryop) \
+ F(MathMaxNumber, binaryop) \
+ F(MathMinNumber, binaryop) \
F(NewString, construct) \
F(NewUrl, construct) \
F(CleanupRegister, cleanup) \
@@ -160,8 +160,7 @@ QT_BEGIN_NAMESPACE
F(BranchFalse, branchop) \
F(Branch, branchop) \
F(Block, blockop) \
- /* Speculative property resolution */ \
- F(InitString, initstring)
+ F(Throw, throwop)
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
# define QML_THREADED_INTERPRETER
@@ -192,7 +191,7 @@ class QQmlNotifier;
namespace QQmlJS {
-union V4Instr {
+union Q_AUTOTEST_EXPORT V4Instr {
enum Type {
FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM)
};
@@ -241,6 +240,7 @@ union V4Instr {
qint8 output;
qint8 reg;
quint8 exceptionId;
+ quint8 valueType;
quint32 index;
};
@@ -283,10 +283,10 @@ union V4Instr {
qint8 reg;
};
- struct instr_real_value {
+ struct instr_number_value {
QML_V4_INSTR_HEADER
qint8 reg;
- qreal value; // XXX Makes the instruction 12 bytes
+ double value; // XXX Makes the instruction 12 bytes
};
struct instr_int_value {
@@ -358,6 +358,12 @@ union V4Instr {
quint32 block;
};
+ struct instr_throwop {
+ QML_V4_INSTR_HEADER
+ quint8 exceptionId;
+ quint32 message;
+ };
+
instr_common common;
instr_id id;
instr_init init;
@@ -371,7 +377,7 @@ union V4Instr {
instr_copy copy;
instr_construct construct;
instr_null_value null_value;
- instr_real_value real_value;
+ instr_number_value number_value;
instr_int_value int_value;
instr_bool_value bool_value;
instr_string_value string_value;
@@ -383,6 +389,7 @@ union V4Instr {
instr_initstring initstring;
instr_branchop branchop;
instr_blockop blockop;
+ instr_throwop throwop;
};
template<int N>
@@ -400,11 +407,11 @@ FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE);
#undef QML_V4_INSTR_META_TEMPLATE
template<int Instr>
-class V4InstrData : public V4InstrMeta<Instr>::DataType
+class Q_AUTOTEST_EXPORT V4InstrData : public V4InstrMeta<Instr>::DataType
{
};
-class Bytecode
+class Q_AUTOTEST_EXPORT Bytecode
{
Q_DISABLE_COPY(Bytecode)
diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp
index 34245f5bf4..ba0faec80e 100644
--- a/src/qml/qml/v4/qv4ir.cpp
+++ b/src/qml/qml/v4/qv4ir.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace IR {
-inline const char *typeName(Type t)
+const char *typeName(Type t)
{
switch (t) {
case InvalidType: return "invalid";
@@ -58,15 +58,15 @@ inline const char *typeName(Type t)
case NullType: return "null";
case VoidType: return "void";
case StringType: return "string";
- case UrlType: return "url";
- case ColorType: return "color";
+ case UrlType: return "QUrl";
+ case ColorType: return "QColor";
case SGAnchorLineType: return "SGAnchorLine";
case AttachType: return "AttachType";
case ObjectType: return "object";
case BoolType: return "bool";
case IntType: return "int";
- case RealType: return "qreal";
- case RealNaNType: return "NaN";
+ case FloatType: return "float";
+ case NumberType: return "number";
default: return "invalid";
}
}
@@ -91,15 +91,20 @@ IR::Type maxType(IR::Type left, IR::Type right)
return IR::StringType;
} else if (left == right)
return left;
- else if (isNumberType(left) && isNumberType(right))
- return qMax(left, right);
- else if ((isNumberType(left) && isStringType(right)) ||
+ else if (isNumberType(left) && isNumberType(right)) {
+ IR::Type ty = qMax(left, right);
+ return ty == FloatType ? NumberType : ty; // promote floats
+ } else if ((isNumberType(left) && isStringType(right)) ||
(isNumberType(right) && isStringType(left)))
return IR::StringType;
else
return IR::InvalidType;
}
+bool isRealType(IR::Type type)
+{
+ return type == IR::NumberType || type == IR::FloatType;
+}
const char *opname(AluOp op)
{
@@ -233,7 +238,7 @@ void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32
builtin = MathMinBuiltinFunction;
} else if (id->length() == 7 && *id == QLatin1String("Math.PI")) {
builtin = MathPIBuiltinConstant;
- this->type = RealType;
+ this->type = NumberType;
}
}
@@ -267,7 +272,7 @@ Type Unop::typeForOp(AluOp op, Expr *expr)
case OpUMinus:
case OpUPlus:
case OpCompl:
- return maxType(expr->type, RealType);
+ return maxType(expr->type, NumberType);
default:
break;
@@ -309,13 +314,13 @@ Type Binop::typeForOp(AluOp op, Expr *left, Expr *right)
case OpAdd:
if (left->type == StringType)
return StringType;
- return RealType;
+ return NumberType;
case OpSub:
case OpMul:
case OpDiv:
case OpMod:
- return RealType;
+ return NumberType;
case OpLShift:
case OpRShift:
@@ -364,7 +369,7 @@ Type Call::typeForFunction(Expr *base)
case MathAbsBuiltinFunction: //### type could also be Int if input was Int
case MathMaxBuiltinFunction:
case MathMinBuiltinFunction:
- return RealType;
+ return NumberType;
case MathRoundBultinFunction:
case MathFloorBultinFunction:
@@ -601,6 +606,12 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
break;
}
}
+ } else if (op == OpAdd) {
+ if (String *s1 = left->asString()) {
+ if (String *s2 = right->asString()) {
+ return STRING(function->newString(s1->value.toString() + s2->value));
+ }
+ }
}
}
diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h
index 4e9f9faacd..26bd43c406 100644
--- a/src/qml/qml/v4/qv4ir_p.h
+++ b/src/qml/qml/v4/qv4ir_p.h
@@ -150,10 +150,12 @@ enum Type {
FirstNumberType,
BoolType = FirstNumberType,
IntType,
- RealType,
- RealNaNType
+ FloatType,
+ NumberType
};
Type maxType(IR::Type left, IR::Type right);
+bool isRealType(IR::Type type);
+const char *typeName(IR::Type t);
struct ExprVisitor {
virtual ~ExprVisitor() {}
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 453120c6c7..31ed9a5a6a 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -61,8 +61,11 @@ static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QM
case QMetaType::Int:
return IR::IntType;
- case QMetaType::QReal:
- return IR::RealType;
+ case QMetaType::Float:
+ return IR::FloatType;
+
+ case QMetaType::Double:
+ return IR::NumberType;
case QMetaType::QString:
return IR::StringType;
@@ -542,7 +545,7 @@ bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
_expr.format = ExprResult::cx;
_block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
} else {
- _expr.code = _block->CONST(IR::RealType, ast->value);
+ _expr.code = _block->CONST(IR::NumberType, ast->value);
}
return false;
}
@@ -889,7 +892,14 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult
_expr.format = ExprResult::cx;
_block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
} else {
- _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
+ IR::Expr *e = _block->BINOP(IR::binaryOperator(ast->op), left, right);
+ if (e->asConst() != 0 || e->asString() != 0)
+ _expr.code = e;
+ else {
+ IR::Temp *t = _block->TEMP(e->type);
+ _block->MOVE(t, e);
+ _expr.code = t;
+ }
}
}
@@ -977,8 +987,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
if (left.type() == IR::StringType && right.type() == IR::StringType) {
binop(ast, left, right);
} else if (left.isValid() && right.isValid()) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
binop(ast, left, right);
}
} break;
@@ -998,8 +1008,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
}
} else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
(left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
binop(ast, left, right);
} else if (left.isValid() && right.isValid()) {
binop(ast, left, right);
@@ -1086,8 +1096,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
IR::Type t = maxType(left.type(), right.type());
if (t >= IR::FirstNumberType) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
_expr.code = _block->TEMP(code->type);
diff --git a/src/qml/qml/v4/qv4irbuilder_p.h b/src/qml/qml/v4/qv4irbuilder_p.h
index 2b338c0778..e73ec22750 100644
--- a/src/qml/qml/v4/qv4irbuilder_p.h
+++ b/src/qml/qml/v4/qv4irbuilder_p.h
@@ -95,8 +95,8 @@ protected:
case QQmlJS::IR::StringType:
case QQmlJS::IR::BoolType:
case QQmlJS::IR::IntType:
- case QQmlJS::IR::RealType:
- case QQmlJS::IR::RealNaNType:
+ case QQmlJS::IR::FloatType:
+ case QQmlJS::IR::NumberType:
return true;
default:
diff --git a/src/qml/qml/v4/qv4program_p.h b/src/qml/qml/v4/qv4program_p.h
index 60e7403786..c1dc39279d 100644
--- a/src/qml/qml/v4/qv4program_p.h
+++ b/src/qml/qml/v4/qv4program_p.h
@@ -65,7 +65,6 @@ struct QV4Program {
quint32 signalTableOffset;
quint32 exceptionDataOffset;
quint16 subscriptions;
- quint16 identifiers;
quint16 instructionCount;
struct BindingReference {
@@ -87,7 +86,8 @@ enum QQmlRegisterType {
UndefinedType,
NullType,
QObjectStarType,
- QRealType,
+ NumberType,
+ FloatType,
IntType,
BoolType,
diff --git a/src/qml/qml/v8/qjsvalue_p.h b/src/qml/qml/v8/qjsvalue_p.h
index acfe958cb6..099d53ee7a 100644
--- a/src/qml/qml/v8/qjsvalue_p.h
+++ b/src/qml/qml/v8/qjsvalue_p.h
@@ -177,7 +177,7 @@ private:
CBool,
CNull,
CUndefined,
- JSValue = 0x2000, // V8 values are equal or higher then this value.
+ JSValue = 0x2000 // V8 values are equal or higher then this value.
// JSPrimitive,
// JSObject
} m_state;
diff --git a/src/qml/qml/v8/qv8bindings.cpp b/src/qml/qml/v8/qv8bindings.cpp
index 4b96679cf3..025854f1ac 100644
--- a/src/qml/qml/v8/qv8bindings.cpp
+++ b/src/qml/qml/v8/qv8bindings.cpp
@@ -58,7 +58,7 @@ static QQmlJavaScriptExpression::VTable QV8Bindings_Binding_jsvtable = {
};
QV8Bindings::Binding::Binding()
-: QQmlJavaScriptExpression(&QV8Bindings_Binding_jsvtable), target(0), parent(0)
+: QQmlJavaScriptExpression(&QV8Bindings_Binding_jsvtable), parent(0)
{
}
@@ -85,12 +85,20 @@ void QV8Bindings::Binding::refresh()
int QV8Bindings::Binding::propertyIndex() const
{
- return instruction->property.encodedIndex();
+ if (target.hasValue()) return target.constValue()->targetProperty;
+ else return instruction->property.encodedIndex();
}
QObject *QV8Bindings::Binding::object() const
{
- return target;
+ if (target.hasValue()) return target.constValue()->target;
+ else return *target;
+}
+
+void QV8Bindings::Binding::retargetBinding(QObject *t, int i)
+{
+ target.value().target = t;
+ target.value().targetProperty = i;
}
void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
@@ -127,13 +135,13 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
trace.event("writing V8 result");
bool needsErrorData = false;
- if (!watcher.wasDeleted() && !hasError()) {
+ if (!watcher.wasDeleted() && !destroyedFlag() && !hasError()) {
typedef QQmlPropertyPrivate PP;
- needsErrorData = !PP::writeBinding(target, instruction->property, context, this, result,
+ needsErrorData = !PP::writeBinding(*target, instruction->property, context, this, result,
isUndefined, flags);
}
- if (!watcher.wasDeleted()) {
+ if (!watcher.wasDeleted() && !destroyedFlag()) {
if (needsErrorData) {
QUrl url = parent->url();
@@ -156,7 +164,7 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
ep->dereferenceScarceResources();
} else {
- QQmlProperty p = QQmlPropertyPrivate::restore(target, instruction->property, context);
+ QQmlProperty p = QQmlPropertyPrivate::restore(*target, instruction->property, context);
QQmlAbstractBinding::printBindingLoopError(p);
}
}
@@ -177,6 +185,7 @@ void QV8Bindings::Binding::expressionChanged(QQmlJavaScriptExpression *e)
void QV8Bindings::Binding::destroy()
{
setEnabledFlag(false);
+ setDestroyedFlag(true);
removeFromObject();
clear();
clearError();
diff --git a/src/qml/qml/v8/qv8bindings_p.h b/src/qml/qml/v8/qv8bindings_p.h
index ad5b2cb8b0..7cc1cc9c21 100644
--- a/src/qml/qml/v8/qv8bindings_p.h
+++ b/src/qml/qml/v8/qv8bindings_p.h
@@ -53,12 +53,13 @@
// We mean it.
//
+#include <private/qpointervaluepair_p.h>
#include <private/qqmlpropertycache_p.h>
#include <private/qqmlinstruction_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qqmlbinding_p.h>
#include <private/qflagpointer_p.h>
+#include <private/qqmlbinding_p.h>
QT_BEGIN_HEADER
@@ -96,17 +97,26 @@ public:
virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
virtual void update(QQmlPropertyPrivate::WriteFlags flags);
virtual void destroy();
- virtual int propertyIndex() const;
virtual QObject *object() const;
+ virtual int propertyIndex() const;
+ virtual void retargetBinding(QObject *, int);
- QObject *target;
QV8Bindings *parent;
+ struct Retarget {
+ QObject *target;
+ int targetProperty;
+ };
+
// To save memory, we store flags inside the instruction pointer.
- // flag1: enabled
- // flag2: updating
+ // target.flag1: destroyed
+ // instruction.flag1: enabled
+ // instruction.flag2: updating
+ QPointerValuePair<QObject, Retarget> target;
QFlagPointer<const QQmlInstruction::instr_assignBinding> instruction;
+ inline bool destroyedFlag() const { return target.flag(); }
+ inline void setDestroyedFlag(bool v) { return target.setFlagValue(v); }
inline bool enabledFlag() const { return instruction.flag(); }
inline void setEnabledFlag(bool v) { instruction.setFlagValue(v); }
inline bool updatingFlag() const { return instruction.flag2(); }
diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp
index 39392b8984..8a98727205 100644
--- a/src/qml/qml/v8/qv8contextwrapper.cpp
+++ b/src/qml/qml/v8/qv8contextwrapper.cpp
@@ -327,7 +327,7 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
const QVariant &value = cp->propertyValues.at(propertyIdx);
if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
- QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*)propertyIdx,
+ QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
0,
QQmlContextPrivate::context_count,
QQmlContextPrivate::context_at);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 678f9aa3ee..2302d0e369 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -46,7 +46,6 @@
#include "qv8sequencewrapper_p.h"
#include "qv8include_p.h"
#include "qjsengine_p.h"
-#include "../../../3rdparty/javascriptcore/DateMath.h"
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmllist_p.h>
@@ -765,23 +764,19 @@ void QV8Engine::setExtensionData(int index, Deletable *data)
double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt)
{
- // from QScriptEngine::DateTimeToMs()
if (!dt.isValid()) {
return qSNaN();
}
- QDateTime utc = dt.toUTC();
- QDate date = utc.date();
- QTime time = utc.time();
- QV8DateConverter::JSC::GregorianDateTime tm;
- tm.year = date.year() - 1900;
- tm.month = date.month() - 1;
- tm.monthDay = date.day();
- tm.weekDay = date.dayOfWeek();
- tm.yearDay = date.dayOfYear();
- tm.hour = time.hour();
- tm.minute = time.minute();
- tm.second = time.second();
- return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec());
+
+ return dt.toMSecsSinceEpoch();
+}
+
+QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
+{
+ if (qIsNaN(jsDate))
+ return QDateTime();
+
+ return QDateTime::fromMSecsSinceEpoch(jsDate);
}
v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong)
@@ -815,24 +810,6 @@ v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, boo
}
}
-QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
-{
- // from QScriptEngine::MsToDateTime()
- if (qIsNaN(jsDate))
- return QDateTime();
- QV8DateConverter::JSC::GregorianDateTime tm;
- QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm);
-
- // from QScriptEngine::MsFromTime()
- int ms = int(::fmod(jsDate, 1000.0));
- if (ms < 0)
- ms += int(1000.0);
-
- QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
- QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
- return convertedUTC.toLocalTime();
-}
-
void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle)
{
if (handle.IsEmpty())
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 2350b9dc2c..ce85725642 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -63,7 +63,7 @@ Q_DECLARE_METATYPE(QQmlV8Handle);
QT_BEGIN_NAMESPACE
-#if defined(__GNUC__)
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
// The code in this file does not violate strict aliasing, but GCC thinks it does
// so turn off the warnings for us to have a clean build
@@ -269,7 +269,7 @@ static v8::Handle<v8::Value> GenericValueGetter(v8::Local<v8::String>, const v8:
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This);
QObject *object = resource->object;
- if (!object) return v8::Undefined();
+ if (QQmlData::wasDeleted(object)) return v8::Undefined();
QQmlPropertyData *property =
(QQmlPropertyData *)v8::External::Unwrap(info.Data());
@@ -476,6 +476,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
objectHandle?*objectHandle:engine->newQObject(object),
v8::Integer::New(index)
};
+ Q_ASSERT(argv[0]->IsObject());
return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv);
}
static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object,
@@ -486,10 +487,14 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
v8::Integer::New(index),
v8::Context::GetCallingQmlGlobal()
};
+ Q_ASSERT(argv[0]->IsObject());
return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv);
}
};
+ if (QQmlData::wasDeleted(object))
+ return v8::Handle<v8::Value>();
+
{
// Comparing the hash first actually makes a measurable difference here, at least on x86
quint32 hash = property.hash();
@@ -705,6 +710,9 @@ bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QH
engine->qobjectWrapper()->m_destroyString == property)
return true;
+ if (QQmlData::wasDeleted(object))
+ return false;
+
QQmlPropertyData local;
QQmlPropertyData *result = 0;
result = QQmlPropertyCache::property(engine->engine(), object, property, local);
@@ -735,7 +743,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return v8::Handle<v8::Value>();
QObject *object = resource->object;
@@ -779,7 +787,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return value;
QObject *object = resource->object;
@@ -873,7 +881,7 @@ static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return;
QObject *object = resource->object;
@@ -900,7 +908,7 @@ static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return;
QV8Engine *v8engine = resource->engine;
@@ -1080,20 +1088,13 @@ released the handle.
*/
v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
{
- if (!object)
+ if (QQmlData::wasDeleted(object))
return v8::Null();
- if (QObjectPrivate::get(object)->wasDeleted)
- return v8::Null();
-
QQmlData *ddata = QQmlData::get(object, true);
-
if (!ddata)
return v8::Undefined();
- if (ddata->isQueuedForDeletion)
- return v8::Null();
-
if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) {
// We own the v8object
return v8::Local<v8::Object>::New(ddata->v8object);
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index de492a8ce5..7816c84b79 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,5 +1,3 @@
-INCLUDEPATH += $$PWD/../../../3rdparty/javascriptcore
-
include(script.pri)
HEADERS += \
@@ -20,7 +18,6 @@ HEADERS += \
$$PWD/qv8include_p.h \
$$PWD/qv8worker_p.h \
$$PWD/qv8bindings_p.h \
- $$PWD/../../../3rdparty/javascriptcore/DateMath.h \
$$PWD/qv8engine_impl_p.h \
$$PWD/qv8domerrors_p.h \
$$PWD/qv8sqlerrors_p.h \
@@ -39,7 +36,6 @@ SOURCES += \
$$PWD/qv8include.cpp \
$$PWD/qv8worker.cpp \
$$PWD/qv8bindings.cpp \
- $$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
$$PWD/qv8domerrors.cpp \
$$PWD/qv8sqlerrors.cpp \
- $$PWD/qqmlbuiltinfunctions.cpp \ No newline at end of file
+ $$PWD/qqmlbuiltinfunctions.cpp