Source

Target

Commits (6)
Showing with 166 additions and 27 deletions
...@@ -46,6 +46,13 @@ Third party components ...@@ -46,6 +46,13 @@ Third party components
- tryCompare now correctly fails when it only gets two parameters - tryCompare now correctly fails when it only gets two parameters
- If a QObject has a property and a slot (or invokable method) with the same
name, in QML the previous behavior was to let the property obscure the
method; from Qt 5.1 things work in the opposite way, that is a property can
never obscure a method having the same name. This is especially important
for objects having dynamic properties, such as QQmlPropertyMap. This change
was a consequence of the fix for QTBUG-29836.
**************************************************************************** ****************************************************************************
* Library * * Library *
**************************************************************************** ****************************************************************************
......
...@@ -166,6 +166,15 @@ Item { ...@@ -166,6 +166,15 @@ Item {
} }
\endqml \endqml
\li The \c with statement is deprecated. Using the \c with statement will issue a warning
at loading time and we plan on removing support for it in Qt 5.2. It is generally considered
a language feature that is not recommended for use due reducing the readability of code and disabling
many optimizations in the engine. It is also forbidden in ECMAScript 5 strict mode.
\li JavaScript binding expressions are executed in non-strict mode. However we
plan on changing the default for bindings in Qt 5.2 to execute always in
ECMAScript 5 strict mode.
\endlist \endlist
......
...@@ -2615,6 +2615,10 @@ case $rule_number: { ...@@ -2615,6 +2615,10 @@ case $rule_number: {
node->lparenToken = loc(2); node->lparenToken = loc(2);
node->rparenToken = loc(4); node->rparenToken = loc(4);
sym(1).Node = node; sym(1).Node = node;
if (lexer->qmlMode()) {
const QString msg = qApp->translate("QQmlParser", "Deprecated JavaScript `with' statement detected in QML expression. Support for this will be removed in Qt 5.2!");
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, node->withToken, msg));
}
} break; } break;
./ ./
......
...@@ -1515,6 +1515,10 @@ case 311: { ...@@ -1515,6 +1515,10 @@ case 311: {
node->lparenToken = loc(2); node->lparenToken = loc(2);
node->rparenToken = loc(4); node->rparenToken = loc(4);
sym(1).Node = node; sym(1).Node = node;
if (lexer->qmlMode()) {
const QString msg = qApp->translate("QQmlParser", "Deprecated JavaScript `with' statement detected in QML expression. Support for this will be removed in Qt 5.2!");
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, node->withToken, msg));
}
} break; } break;
case 312: { case 312: {
......
...@@ -1317,25 +1317,10 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS ...@@ -1317,25 +1317,10 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS
Q_ASSERT(metaObject); Q_ASSERT(metaObject);
QQmlPropertyData rv; QQmlPropertyData rv;
{
const QMetaObject *cmo = metaObject; /* It's important to check the method list before checking for properties;
const QByteArray propertyName = property.toUtf8(); * otherwise, if the meta object is dynamic, a property will be created even
while (cmo) { * if not found and it might obscure a method having the same name. */
int idx = cmo->indexOfProperty(propertyName);
if (idx != -1) {
QMetaProperty p = cmo->property(idx);
if (p.isScriptable()) {
rv.load(p);
return rv;
} else {
while (cmo && cmo->propertyOffset() >= idx)
cmo = cmo->superClass();
}
} else {
cmo = 0;
}
}
}
//Used to block access to QObject::destroyed() and QObject::deleteLater() from QML //Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
...@@ -1357,6 +1342,31 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS ...@@ -1357,6 +1342,31 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS
} }
} }
{
const QMetaObject *cmo = metaObject;
const QByteArray propertyName = property.toUtf8();
while (cmo) {
int idx = cmo->indexOfProperty(propertyName);
if (idx != -1) {
QMetaProperty p = cmo->property(idx);
if (p.isScriptable()) {
rv.load(p);
return rv;
} else {
bool changed = false;
while (cmo && cmo->propertyOffset() >= idx) {
cmo = cmo->superClass();
changed = true;
}
/* If the "cmo" variable didn't change, set it to 0 to
* avoid running into an infinite loop */
if (!changed) cmo = 0;
}
} else {
cmo = 0;
}
}
}
return rv; return rv;
} }
...@@ -1395,7 +1405,8 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, const T &name, ...@@ -1395,7 +1405,8 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, const T &name,
if (cache) { if (cache) {
rv = cache->property(name, obj, context); rv = cache->property(name, obj, context);
} else { }
if (!rv) {
local = qQmlPropertyCacheCreate(obj->metaObject(), qQmlPropertyCacheToString(name)); local = qQmlPropertyCacheCreate(obj->metaObject(), qQmlPropertyCacheToString(name));
if (local.isValid()) if (local.isValid())
rv = &local; rv = &local;
......
...@@ -1318,13 +1318,15 @@ bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* pre ...@@ -1318,13 +1318,15 @@ bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* pre
QQmlJS::Parser parser(&data->engine); QQmlJS::Parser parser(&data->engine);
if (! parser.parse() || !_errors.isEmpty()) { if (! parser.parse() || !parser.diagnosticMessages().isEmpty()) {
// Extract errors from the parser // Extract errors from the parser
foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) { foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
if (m.isWarning()) if (m.isWarning()) {
qWarning("%s:%d : %s", qPrintable(_scriptFile), m.loc.startLine, qPrintable(m.message));
continue; continue;
}
QQmlError error; QQmlError error;
error.setUrl(url); error.setUrl(url);
......
...@@ -524,7 +524,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject ...@@ -524,7 +524,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
QQmlData *ddata = QQmlData::get(object, false); QQmlData *ddata = QQmlData::get(object, false);
if (ddata && ddata->propertyCache) if (ddata && ddata->propertyCache)
result = ddata->propertyCache->property(property, object, context); result = ddata->propertyCache->property(property, object, context);
else if (!result)
result = QQmlPropertyCache::property(engine->engine(), object, property, context, local); result = QQmlPropertyCache::property(engine->engine(), object, property, context, local);
} }
......
...@@ -47,7 +47,9 @@ ...@@ -47,7 +47,9 @@
#include <QtQuick/private/qsgdefaultimagenode_p.h> #include <QtQuick/private/qsgdefaultimagenode_p.h>
#include <QtQuick/private/qsgdefaultglyphnode_p.h> #include <QtQuick/private/qsgdefaultglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h> #include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
#include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h> #include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
#include <QtQuick/QSGFlatColorMaterial>
#include <QtQuick/private/qsgtexture_p.h> #include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qquickpixmapcache_p.h> #include <QtQuick/private/qquickpixmapcache_p.h>
...@@ -263,9 +265,35 @@ void QSGContext::initialize(QOpenGLContext *context) ...@@ -263,9 +265,35 @@ void QSGContext::initialize(QOpenGLContext *context)
Q_ASSERT(!d->gl); Q_ASSERT(!d->gl);
d->gl = context; d->gl = context;
precompileMaterials();
emit initialized(); emit initialized();
} }
#define QSG_PRECOMPILE_MATERIAL(name) { name m; prepareMaterial(&m); }
/*
* Some glsl compilers take their time compiling materials, and
* the way the scene graph is being processed, these materials
* get compiled when they are first taken into use. This can
* easily lead to skipped frames. By precompiling the most
* common materials, we potentially add a few milliseconds to the
* start up, and reduce the chance of avoiding skipped frames
* later on.
*/
void QSGContext::precompileMaterials()
{
if (qEnvironmentVariableIsEmpty("QSG_NO_MATERIAL_PRELOADING")) {
QSG_PRECOMPILE_MATERIAL(QSGVertexColorMaterial);
QSG_PRECOMPILE_MATERIAL(QSGFlatColorMaterial);
QSG_PRECOMPILE_MATERIAL(QSGOpaqueTextureMaterial);
QSG_PRECOMPILE_MATERIAL(QSGTextureMaterial);
QSG_PRECOMPILE_MATERIAL(SmoothTextureMaterial);
QSG_PRECOMPILE_MATERIAL(SmoothColorMaterial);
QSG_PRECOMPILE_MATERIAL(QSGDistanceFieldTextMaterial);
}
}
/*! /*!
Returns if the scene graph context is ready or not, meaning that it has a valid Returns if the scene graph context is ready or not, meaning that it has a valid
......
...@@ -90,6 +90,7 @@ public: ...@@ -90,6 +90,7 @@ public:
bool isReady() const; bool isReady() const;
virtual void precompileMaterials();
QSGMaterialShader *prepareMaterial(QSGMaterial *material); QSGMaterialShader *prepareMaterial(QSGMaterial *material);
virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId); virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId);
......
...@@ -66,6 +66,8 @@ private slots: ...@@ -66,6 +66,8 @@ private slots:
void crashBug(); void crashBug();
void QTBUG_17868(); void QTBUG_17868();
void metaObjectAccessibility(); void metaObjectAccessibility();
void QTBUG_31226();
void QTBUG_29836();
}; };
void tst_QQmlPropertyMap::insert() void tst_QQmlPropertyMap::insert()
...@@ -286,13 +288,17 @@ class MyEnhancedPropertyMap : public QQmlPropertyMap ...@@ -286,13 +288,17 @@ class MyEnhancedPropertyMap : public QQmlPropertyMap
{ {
Q_OBJECT Q_OBJECT
public: public:
MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0) {} MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0), m_testSlotCalled(false) {}
bool testSlotCalled() const { return m_testSlotCalled; }
signals: signals:
void testSignal(); void testSignal();
public slots: public slots:
void testSlot() {} void testSlot() { m_testSlotCalled = true; }
private:
bool m_testSlotCalled;
}; };
void tst_QQmlPropertyMap::metaObjectAccessibility() void tst_QQmlPropertyMap::metaObjectAccessibility()
...@@ -312,6 +318,57 @@ void tst_QQmlPropertyMap::metaObjectAccessibility() ...@@ -312,6 +318,57 @@ void tst_QQmlPropertyMap::metaObjectAccessibility()
QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString())); QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
} }
void tst_QQmlPropertyMap::QTBUG_31226()
{
/* Instantiate a property map from QML, and verify that property changes
* made from C++ are visible from QML */
QQmlEngine engine;
QQmlContext context(&engine);
qmlRegisterType<QQmlPropertyMap>("QTBUG_31226", 1, 0, "PropertyMap");
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\nimport QTBUG_31226 1.0\n"
"Item {\n"
" property string myProp\n"
" PropertyMap { id: qmlPropertyMap; objectName: \"qmlPropertyMap\" }\n"
" Timer { interval: 5; running: true; onTriggered: { myProp = qmlPropertyMap.greeting; } }\n"
"}",
QUrl());
QObject *obj = c.create(&context);
QVERIFY(obj);
QQmlPropertyMap *qmlPropertyMap = obj->findChild<QQmlPropertyMap*>(QString("qmlPropertyMap"));
QVERIFY(qmlPropertyMap);
qmlPropertyMap->insert("greeting", QString("Hello world!"));
QTRY_COMPARE(obj->property("myProp").toString(), QString("Hello world!"));
delete obj;
}
void tst_QQmlPropertyMap::QTBUG_29836()
{
MyEnhancedPropertyMap map;
QCOMPARE(map.testSlotCalled(), false);
QQmlEngine engine;
QQmlContext context(&engine);
context.setContextProperty("enhancedMap", &map);
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\n"
"Item {\n"
" Timer { interval: 5; running: true; onTriggered: enhancedMap.testSlot() }\n"
"}",
QUrl());
QObject *obj = c.create(&context);
QVERIFY(obj);
QTRY_COMPARE(map.testSlotCalled(), true);
delete obj;
}
QTEST_MAIN(tst_QQmlPropertyMap) QTEST_MAIN(tst_QQmlPropertyMap)
#include "tst_qqmlpropertymap.moc" #include "tst_qqmlpropertymap.moc"
...@@ -195,8 +195,9 @@ void tst_TouchMouse::simpleTouchEvent() ...@@ -195,8 +195,9 @@ void tst_TouchMouse::simpleTouchEvent()
window->setSource(testFileUrl("singleitem.qml")); window->setSource(testFileUrl("singleitem.qml"));
window->show(); window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(window)); QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
...@@ -344,7 +345,9 @@ void tst_TouchMouse::mouse() ...@@ -344,7 +345,9 @@ void tst_TouchMouse::mouse()
window->setSource(testFileUrl("twoitems.qml")); window->setSource(testFileUrl("twoitems.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
...@@ -376,7 +379,9 @@ void tst_TouchMouse::touchOverMouse() ...@@ -376,7 +379,9 @@ void tst_TouchMouse::touchOverMouse()
window->setSource(testFileUrl("twoitems.qml")); window->setSource(testFileUrl("twoitems.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
...@@ -417,7 +422,9 @@ void tst_TouchMouse::mouseOverTouch() ...@@ -417,7 +422,9 @@ void tst_TouchMouse::mouseOverTouch()
window->setSource(testFileUrl("twoitems.qml")); window->setSource(testFileUrl("twoitems.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
...@@ -461,7 +468,9 @@ void tst_TouchMouse::buttonOnFlickable() ...@@ -461,7 +468,9 @@ void tst_TouchMouse::buttonOnFlickable()
window->setSource(testFileUrl("buttononflickable.qml")); window->setSource(testFileUrl("buttononflickable.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable"); QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
...@@ -569,7 +578,9 @@ void tst_TouchMouse::buttonOnTouch() ...@@ -569,7 +578,9 @@ void tst_TouchMouse::buttonOnTouch()
QQuickView *window = createView(); QQuickView *window = createView();
window->setSource(testFileUrl("buttonontouch.qml")); window->setSource(testFileUrl("buttonontouch.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
...@@ -691,7 +702,9 @@ void tst_TouchMouse::pinchOnFlickable() ...@@ -691,7 +702,9 @@ void tst_TouchMouse::pinchOnFlickable()
QQuickView *window = createView(); QQuickView *window = createView();
window->setSource(testFileUrl("pinchonflickable.qml")); window->setSource(testFileUrl("pinchonflickable.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
...@@ -758,7 +771,9 @@ void tst_TouchMouse::flickableOnPinch() ...@@ -758,7 +771,9 @@ void tst_TouchMouse::flickableOnPinch()
QQuickView *window = createView(); QQuickView *window = createView();
window->setSource(testFileUrl("flickableonpinch.qml")); window->setSource(testFileUrl("flickableonpinch.qml"));
window->show(); window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate(); window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
...@@ -935,8 +950,9 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() ...@@ -935,8 +950,9 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne()
window->setSource(testFileUrl("twoMouseAreas.qml")); window->setSource(testFileUrl("twoMouseAreas.qml"));
window->show(); window->show();
window->requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(window)); QVERIFY(QTest::qWaitForWindowExposed(window));
window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(window->rootObject() != 0); QVERIFY(window->rootObject() != 0);
QQuickMouseArea *bottomMouseArea = QQuickMouseArea *bottomMouseArea =
......