aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-09-08 13:10:21 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2014-09-08 13:10:21 +0200
commit38fe461e2cc4bf3aebcb98d25c643bfe6653120a (patch)
treeb625415f33791ce0202538396509379fd04b111a
parentf9ee33f9683a4cd4d1a2e41efa6e8d124e9d731d (diff)
parentf7c3035fa1d965dceb36892122683a5ceb6cab89 (diff)
Merge remote-tracking branch 'origin/5.3' into 5.4
Conflicts: .qmake.conf src/qml/jsruntime/qv4arraydata.cpp src/quick/scenegraph/util/qsgatlastexture.cpp Change-Id: Ic4c96066d5c37dcf0d5446baed590ea005d445ce
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp56
-rw-r--r--src/qml/jsruntime/qv4script.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp11
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp1
-rw-r--r--src/quick/util/qquickanimatorjob.cpp14
-rw-r--r--src/quick/util/qquickanimatorjob_p.h4
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp19
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceSort.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp11
11 files changed, 128 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index f7940c9602..d58dbb91d4 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -678,6 +678,60 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
return p1s->toQString() < p2s->toQString();
}
+template <typename RandomAccessIterator, typename T, typename LessThan>
+void sortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
+{
+top:
+ int span = int(end - start);
+ if (span < 2)
+ return;
+
+ --end;
+ RandomAccessIterator low = start, high = end - 1;
+ RandomAccessIterator pivot = start + span / 2;
+
+ if (lessThan(*end, *start))
+ qSwap(*end, *start);
+ if (span == 2)
+ return;
+
+ if (lessThan(*pivot, *start))
+ qSwap(*pivot, *start);
+ if (lessThan(*end, *pivot))
+ qSwap(*end, *pivot);
+ if (span == 3)
+ return;
+
+ qSwap(*pivot, *end);
+
+ while (low < high) {
+ while (low < high && lessThan(*low, *end))
+ ++low;
+
+ while (high > low && lessThan(*end, *high))
+ --high;
+
+ if (low < high) {
+ qSwap(*low, *high);
+ ++low;
+ --high;
+ } else {
+ break;
+ }
+ }
+
+ if (lessThan(*low, *end))
+ ++low;
+
+ qSwap(*end, *low);
+ sortHelper(start, low, t, lessThan);
+
+ start = low + 1;
+ ++end;
+ goto top;
+}
+
+
void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint len)
{
if (!len)
@@ -769,7 +823,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Value *begin = thisObject->arrayData()->arrayData();
- std::sort(begin, begin + len, lessThan);
+ sortHelper(begin, begin + len, *begin, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
thisObject->initSparseArray();
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index a4378cf49a..8e91c0e6a5 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -320,7 +320,7 @@ QV4::CompiledData::CompilationUnit *Script::precompile(IR::Module *module, Compi
QQmlJS::Engine ee;
QQmlJS::Lexer lexer(&ee);
- lexer.setCode(source, /*line*/1, /*qml mode*/true);
+ lexer.setCode(source, /*line*/1, /*qml mode*/false);
QQmlJS::Parser parser(&ee);
parser.parseProgram();
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index c396507ab6..a9cbbe1dc3 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -307,7 +307,16 @@ void Atlas::uploadBgra(Texture *texture)
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// Inner part of the image....
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ if (bpl != iw) {
+ int sy = r.y() + 1;
+ int ey = sy + r.height() - 2;
+ for (int y = sy; y < ey; ++y) {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ src += bpl;
+ }
+ } else {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ }
}
void Atlas::bind(QSGTexture::Filtering filtering)
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index 01f182c35d..42b8840bf4 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -254,6 +254,7 @@ void QQuickAnimatorController::requestSync()
// These functions are called on the GUI thread.
void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job)
{
+ proxy->markJobManagedByController();
m_starting[job] = proxy;
requestSync();
}
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 741fa9bb7f..3725e22397 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -49,6 +49,7 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje
: m_controller(0)
, m_job(job)
, m_internalState(State_Stopped)
+ , m_jobManagedByController(false)
{
m_isRenderThreadProxy = true;
m_animation = qobject_cast<QQuickAbstractAnimation *>(item);
@@ -93,7 +94,10 @@ void QQuickAnimatorProxyJob::deleteJob()
// so delete it through the controller to clean up properly.
if (m_controller)
m_controller->deleteJob(m_job);
- else
+
+ // We explicitly delete the job if the animator controller has never touched
+ // it. If it has, it will have ownership as well.
+ else if (!m_jobManagedByController)
delete m_job;
m_job = 0;
}
@@ -141,11 +145,13 @@ void QQuickAnimatorProxyJob::controllerWasDeleted()
void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
{
if (!window) {
- // Stop will trigger syncBackCurrentValues so best to do it before
- // we delete m_job.
stop();
deleteJob();
- return;
+
+ // Upon leaving a window, we reset the controller. This means that
+ // animators will only enter the Starting phase and won't be making
+ // calls to QQuickAnimatorController::startjob().
+ m_controller = 0;
} else if (!m_controller && m_job) {
m_controller = QQuickWindowPrivate::get(window)->animationController;
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index 7c6ad823b3..f91410950c 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -69,6 +69,7 @@ public:
void startedByController();
void controllerWasDeleted();
+ void markJobManagedByController() { m_jobManagedByController = true; }
protected:
bool event(QEvent *);
@@ -87,7 +88,7 @@ private:
void setWindow(QQuickWindow *window);
static QObject *findAnimationContext(QQuickAbstractAnimation *);
- QQuickAnimatorController *m_controller;
+ QPointer<QQuickAnimatorController> m_controller;
QQuickAbstractAnimation *m_animation;
QAbstractAnimationJob *m_job;
int m_duration;
@@ -100,6 +101,7 @@ private:
};
InternalState m_internalState;
+ bool m_jobManagedByController;
};
class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorJob : public QAbstractAnimationJob
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 87549d2019..741fa9f04d 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -127,6 +127,7 @@ private slots:
void reentrancy_objectCreation();
void jsIncDecNonObjectProperty();
void JSONparse();
+ void arraySort();
void qRegExpInport_data();
void qRegExpInport();
@@ -2742,6 +2743,24 @@ void tst_QJSEngine::JSONparse()
QVERIFY(ret.isObject());
}
+void tst_QJSEngine::arraySort()
+{
+ // tests that calling Array.sort with a bad sort function doesn't cause issues
+ // Using std::sort is e.g. not safe when used with a bad sort function and causes
+ // crashes
+ QJSEngine eng;
+ eng.evaluate("function crashMe() {"
+ " var data = [];"
+ " for (var i = 0; i < 50; i++) {"
+ " data[i] = 'whatever';"
+ " }"
+ " data.sort(function(a, b) {"
+ " return -1;"
+ " });"
+ "}"
+ "crashMe();");
+}
+
static QRegExp minimal(QRegExp r) { r.setMinimal(true); return r; }
void tst_QJSEngine::qRegExpInport_data()
diff --git a/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js
new file mode 100644
index 0000000000..aabcc9f3b8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js
@@ -0,0 +1,7 @@
+.pragma library
+
+var as = undefined
+function isLegal() {
+ var as = true;
+ return as;
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml
new file mode 100644
index 0000000000..17d12199d7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+import "importScriptsWithoutQmlMode.js" as Export
+
+Rectangle {
+ id: root
+ property bool success: false
+
+ Component.onCompleted: success = Export.isLegal()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
index 5e2892a31d..b130408c18 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
@@ -23,7 +23,7 @@ Item {
}
function compareStrings(a, b) {
- return (a < b) ? 1 : -1;
+ return (a == b) ? 0 : ((a < b) ? 1 : -1);
}
function compareNumbers(a, b) {
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 7273cfbe5d..06d061a9fa 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -315,6 +315,7 @@ private slots:
void lazyBindingEvaluation();
void varPropertyAccessOnObjectWithInvalidContext();
void importedScriptsAccessOnObjectWithInvalidContext();
+ void importedScriptsWithoutQmlMode();
void contextObjectOnLazyBindings();
void garbageCollectionDuringCreation();
void qtbug_39520();
@@ -7636,6 +7637,16 @@ void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext()
QTRY_VERIFY(obj->property("success") == true);
}
+void tst_qqmlecmascript::importedScriptsWithoutQmlMode()
+{
+ QQmlComponent component(&engine, testFileUrl("importScriptsWithoutQmlMode.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
+ qDebug() << component.errors().first().toString();
+ QVERIFY(!obj.isNull());
+ QTRY_VERIFY(obj->property("success") == true);
+}
+
void tst_qqmlecmascript::contextObjectOnLazyBindings()
{
QQmlComponent component(&engine, testFileUrl("contextObjectOnLazyBindings.qml"));