aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-30 01:00:08 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-30 01:00:08 +0100
commit2752a4632e94e2687655087d0d7f98b6b16e16a9 (patch)
tree3d9fe294e67cd5f5ae12a0004d467ec7b5b7bf51
parent070eb7bdde4f9e6e814c3afc593368918fd445af (diff)
parentd0a52c72b5756787ceb6094117cd71d935badc06 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
-rw-r--r--src/qml/compiler/qv4codegen.cpp8
-rw-r--r--src/qml/compiler/qv4codegen_p.h25
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp19
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h5
-rw-r--r--src/qml/jsruntime/qv4include.cpp2
-rw-r--r--src/qml/jsruntime/qv4script.cpp18
-rw-r--r--src/qml/jsruntime/qv4script_p.h6
-rw-r--r--src/qml/parser/qqmljs.g10
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h14
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp9
-rw-r--r--src/quick/items/qquickpathview.cpp6
-rw-r--r--src/quick/items/qquicktableview.cpp10
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp13
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp7
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/js/include2.js5
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp26
-rw-r--r--tools/qmlcachegen/qmlcachegen.pro1
19 files changed, 134 insertions, 59 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index bf05c5c538..8ec730a33d 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -315,6 +315,7 @@ void Codegen::accept(Node *node)
void Codegen::statement(Statement *ast)
{
+ RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
RegisterScope scope(this);
bytecodeGenerator->setLocation(ast->firstSourceLocation());
@@ -327,11 +328,12 @@ void Codegen::statement(Statement *ast)
void Codegen::statement(ExpressionNode *ast)
{
- RegisterScope scope(this);
-
if (! ast) {
return;
} else {
+ RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
+ RegisterScope scope(this);
+
Result r(nx);
qSwap(_expr, r);
VolatileMemoryLocations vLocs = scanVolatileMemoryLocations(ast);
@@ -358,6 +360,7 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift
if (!ast)
return;
+ RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
Result r(iftrue, iffalse, trueBlockFollowsCondition);
qSwap(_expr, r);
accept(ast);
@@ -381,6 +384,7 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift
Codegen::Reference Codegen::expression(ExpressionNode *ast)
{
+ RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
Result r;
if (ast) {
qSwap(_expr, r);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 0bc04750f7..289728f505 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -761,6 +761,31 @@ protected:
bool _onoff;
};
+ class RecursionDepthCheck {
+ public:
+ RecursionDepthCheck(Codegen *cg, const AST::SourceLocation &loc)
+ : _cg(cg)
+ {
+#ifdef QT_NO_DEBUG
+ const int depthLimit = 4000; // limit to ~1000 deep
+#else
+ const int depthLimit = 1000; // limit to ~250 deep
+#endif // QT_NO_DEBUG
+
+ ++_cg->_recursionDepth;
+ if (_cg->_recursionDepth > depthLimit)
+ _cg->throwSyntaxError(loc, QStringLiteral("Maximum statement or expression depth exceeded"));
+ }
+
+ ~RecursionDepthCheck()
+ { --_cg->_recursionDepth; }
+
+ private:
+ Codegen *_cg;
+ };
+ int _recursionDepth = 0;
+ friend class RecursionDepthCheck;
+
private:
VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const;
void handleConstruct(const Reference &base, AST::ArgumentList *args);
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 2026e64929..fc3ac769ae 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -96,6 +96,25 @@ void ScanFunctions::leaveEnvironment()
_context = _contextStack.isEmpty() ? nullptr : _contextStack.top();
}
+bool ScanFunctions::preVisit(Node *ast)
+{
+ if (_cg->hasError)
+ return false;
+ ++_recursionDepth;
+
+ if (_recursionDepth > 1000) {
+ _cg->throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded"));
+ return false;
+ }
+
+ return true;
+}
+
+void ScanFunctions::postVisit(Node *)
+{
+ --_recursionDepth;
+}
+
void ScanFunctions::checkDirectivePrologue(StatementList *ast)
{
for (StatementList *it = ast; it; it = it->next) {
diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h
index bb07540ec9..4463a4f4f3 100644
--- a/src/qml/compiler/qv4compilerscanfunctions_p.h
+++ b/src/qml/compiler/qv4compilerscanfunctions_p.h
@@ -96,6 +96,9 @@ protected:
using Visitor::visit;
using Visitor::endVisit;
+ bool preVisit(AST::Node *ast) override;
+ void postVisit(AST::Node *) override;
+
void checkDirectivePrologue(AST::StatementList *ast);
void checkName(const QStringRef &name, const AST::SourceLocation &loc);
@@ -169,6 +172,8 @@ protected:
bool _allowFuncDecls;
ContextType defaultProgramType;
+ unsigned _recursionDepth = 0;
+
private:
static constexpr AST::Node *astNodeForGlobalEnvironment = nullptr;
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index e456879d9c..36569b0a60 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -166,7 +166,7 @@ void QV4Include::finished()
QmlIR::Document::removeScriptPragmas(code);
QV4::Scoped<QV4::QmlContext> qml(scope, m_qmlContext.value());
- QV4::Script script(v4, qml, code, m_url.toString());
+ QV4::Script script(v4, qml, /*parse as QML binding*/false, code, m_url.toString());
script.parse();
if (!scope.engine->hasException)
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 951675b468..f80db86be5 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -240,23 +240,7 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo
QString sourceCode = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(sourceCode);
- auto result = new QV4::Script(engine, qmlContext, sourceCode, originalUrl.toString());
+ auto result = new QV4::Script(engine, qmlContext, /*parseAsBinding*/false, sourceCode, originalUrl.toString());
result->parse();
return result;
}
-
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext)
-{
- QV4::Scope scope(engine);
- QV4::Script qmlScript(engine, qmlContext, script, QString());
-
- qmlScript.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = qmlScript.run();
- if (scope.engine->hasException) {
- scope.engine->catchException();
- return Encode::undefined();
- }
- return result->asReturnedValue();
-}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index c138e4a538..a1e9b83a8b 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -73,10 +73,10 @@ struct Q_QML_EXPORT Script {
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, context(scope), strictMode(false), inheritContext(false), parsed(false), contextType(mode)
, vmFunction(nullptr), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, QmlContext *qml, bool parseAsBinding, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, context(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , vmFunction(nullptr), parseAsBinding(true) {
+ , vmFunction(nullptr), parseAsBinding(parseAsBinding) {
if (qml)
qmlContext.set(engine, *qml);
}
@@ -106,8 +106,6 @@ struct Q_QML_EXPORT Script {
QList<QQmlError> *reportedErrors = nullptr,
QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Global);
static Script *createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl, QString *error);
-
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
};
}
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 6549e5bfa3..860a4e999e 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -614,8 +614,16 @@ bool Parser::parse(int startToken)
program = 0;
do {
- if (++tos == stack_size)
+ if (++tos == stack_size) {
reallocateStack();
+ if (stack_size > 10000) {
+ // We're now in some serious right-recursive stuff, which will probably result in
+ // an AST that's so deep that recursively visiting it will run out of stack space.
+ const QString msg = QCoreApplication::translate("QQmlParser", "Maximum statement or expression depth exceeded");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ return false;
+ }
+ }
state_stack[tos] = action;
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 9a480f1224..afd0f809da 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -88,7 +88,7 @@ public:
inline void *allocate(size_t size)
{
- size = (size + 7) & ~7;
+ size = (size + 7) & ~size_t(7);
if (Q_LIKELY(_ptr && (_ptr + size < _end))) {
void *addr = _ptr;
_ptr += size;
@@ -113,7 +113,9 @@ public:
private:
Q_NEVER_INLINE void *allocate_helper(size_t size)
{
- Q_ASSERT(size < BLOCK_SIZE);
+ size_t currentBlockSize = DEFAULT_BLOCK_SIZE;
+ while (Q_UNLIKELY(size >= currentBlockSize))
+ currentBlockSize *= 2;
if (++_blockCount == _allocatedBlocks) {
if (! _allocatedBlocks)
@@ -121,7 +123,7 @@ private:
else
_allocatedBlocks *= 2;
- _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks);
+ _blocks = reinterpret_cast<char **>(realloc(_blocks, sizeof(char *) * size_t(_allocatedBlocks)));
Q_CHECK_PTR(_blocks);
for (int index = _blockCount; index < _allocatedBlocks; ++index)
@@ -131,12 +133,12 @@ private:
char *&block = _blocks[_blockCount];
if (! block) {
- block = (char *) malloc(BLOCK_SIZE);
+ block = reinterpret_cast<char *>(malloc(currentBlockSize));
Q_CHECK_PTR(block);
}
_ptr = block;
- _end = _ptr + BLOCK_SIZE;
+ _end = _ptr + currentBlockSize;
void *addr = _ptr;
_ptr += size;
@@ -153,7 +155,7 @@ private:
enum
{
- BLOCK_SIZE = 8 * 1024,
+ DEFAULT_BLOCK_SIZE = 8 * 1024,
DEFAULT_BLOCK_COUNT = 8
};
};
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 9f2a96d5d9..380163202a 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -408,7 +408,7 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
QV4::Scope scope(v4);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxt, scopeObject));
- QV4::Script script(v4, qmlContext, code, filename, line);
+ QV4::Script script(v4, qmlContext, /*parse as QML binding*/true, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
@@ -438,7 +438,7 @@ void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *
QV4::Scope scope(v4);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxt, qmlScope));
- QV4::Script script(v4, qmlContext, code, filename, line);
+ QV4::Script script(v4, qmlContext, /*parse as QML binding*/true, code, filename, line);
script.parse();
if (v4->hasException) {
QQmlDelayedError *error = delayedError();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index cb90af4cf0..9df502f778 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -3285,14 +3285,7 @@ QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
if (hasInlineSourceCode)
return QDateTime();
- QDateTime timeStamp = fileInfo.lastModified();
- if (timeStamp.isValid())
- return timeStamp;
-
- static QDateTime appTimeStamp;
- if (!appTimeStamp.isValid())
- appTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
- return appTimeStamp;
+ return fileInfo.lastModified();
}
bool QQmlDataBlob::SourceCodeData::exists() const
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index e7e19b041e..77ed8a659c 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -2403,7 +2403,11 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
const int duration = highlightMoveDuration;
- if (!duration) {
+ const qreal count = pathItems == -1 ? modelCount : qMin(pathItems, modelCount);
+ const qreal averageItemLength = path->path().length() / count;
+ const qreal threshold = 0.5 / averageItemLength; // if we are within .5 px, we want to immediately assign rather than animate
+
+ if (!duration || qAbs(offset - targetOffset) < threshold || (qFuzzyIsNull(targetOffset) && qAbs(modelCount - offset) < threshold)) {
tl.set(moveOffset, targetOffset);
} else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2.0)) {
qreal distance = modelCount - targetOffset + offset;
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index de1169c972..b1900c5b7a 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1647,8 +1647,9 @@ void QQuickTableViewPrivate::connectToModel()
QObjectPrivate::connect(model, &QQmlInstanceModel::initItem, this, &QQuickTableViewPrivate::initItemCallback);
if (tableModel) {
- QObjectPrivate::connect(tableModel, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback);
- QObjectPrivate::connect(tableModel, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback);
+ const auto tm = tableModel.data();
+ QObjectPrivate::connect(tm, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback);
+ QObjectPrivate::connect(tm, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback);
}
if (auto const aim = model->abstractItemModel()) {
@@ -1678,8 +1679,9 @@ void QQuickTableViewPrivate::disconnectFromModel()
QObjectPrivate::disconnect(model, &QQmlInstanceModel::initItem, this, &QQuickTableViewPrivate::initItemCallback);
if (tableModel) {
- QObjectPrivate::disconnect(tableModel, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback);
- QObjectPrivate::disconnect(tableModel, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback);
+ const auto tm = tableModel.data();
+ QObjectPrivate::disconnect(tm, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback);
+ QObjectPrivate::disconnect(tm, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback);
}
if (auto const aim = model->abstractItemModel()) {
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
index 74426c5c4d..405e2ab100 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
@@ -99,13 +99,6 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
xTarget.resize(columns + 1);
yTarget.resize(rows + 1);
- bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
- if (painter->paintEngine()->type() != QPaintEngine::OpenGL
- && painter->paintEngine()->type() != QPaintEngine::OpenGL2
- && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
- painter->setRenderHint(QPainter::Antialiasing, false);
- }
-
xTarget[0] = targetRect.left();
xTarget[1] = targetCenterLeft;
xTarget[columns - 1] = targetCenterRight;
@@ -311,9 +304,6 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
if (translucentData.size())
painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
-
- if (oldAA)
- painter->setRenderHint(QPainter::Antialiasing, true);
}
} // QSGSoftwareHelpers namespace
@@ -464,6 +454,8 @@ static Qt::TileRule getTileRule(qreal factor)
void QSGSoftwareInternalImageNode::paint(QPainter *painter)
{
painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth);
+ // Disable antialiased clipping. It causes transformed tiles to have gaps.
+ painter->setRenderHint(QPainter::Antialiasing, false);
const QPixmap &pm = m_mirror || m_textureIsLayer ? m_cachedMirroredPixmap : pixmap();
@@ -494,6 +486,7 @@ void QSGSoftwareInternalImageNode::paint(QPainter *painter)
}
}
+
QRectF QSGSoftwareInternalImageNode::rect() const
{
return m_targetRect;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
index 2c361e03e2..f50fa00b0b 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
@@ -121,7 +121,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
for (const QGradientStop &stop : qAsConst(stops)) {
if (stop.first < 0.0 || stop.first > 1.0) {
needsNormalization = true;
- continue;
+ break;
}
}
@@ -425,8 +425,11 @@ void QSGSoftwareInternalRectangleNode::generateCornerPixmap()
{
//Generate new corner Pixmap
int radius = qFloor(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius));
+ const auto width = qRound(radius * 2 * m_devicePixelRatio);
+
+ if (m_cornerPixmap.width() != width)
+ m_cornerPixmap = QPixmap(width, width);
- m_cornerPixmap = QPixmap(qRound(radius * 2 * m_devicePixelRatio), qRound(radius * 2 * m_devicePixelRatio));
m_cornerPixmap.setDevicePixelRatio(m_devicePixelRatio);
m_cornerPixmap.fill(Qt::transparent);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
index 471624d3f8..bd0698be6c 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp
@@ -99,6 +99,8 @@ void QSGSoftwareImageNode::paint(QPainter *painter)
updateCachedMirroredPixmap();
painter->setRenderHint(QPainter::SmoothPixmapTransform, (m_filtering == QSGTexture::Linear));
+ // Disable antialiased clipping. It causes transformed tiles to have gaps.
+ painter->setRenderHint(QPainter::Antialiasing, false);
if (!m_cachedPixmap.isNull()) {
painter->drawPixmap(m_rect, m_cachedPixmap, m_sourceRect);
@@ -194,6 +196,9 @@ void QSGSoftwareNinePatchNode::update()
void QSGSoftwareNinePatchNode::paint(QPainter *painter)
{
+ // Disable antialiased clipping. It causes transformed tiles to have gaps.
+ painter->setRenderHint(QPainter::Antialiasing, false);
+
if (m_margins.isNull())
painter->drawPixmap(m_bounds, m_pixmap, QRectF(0, 0, m_pixmap.width(), m_pixmap.height()));
else
diff --git a/tests/auto/qml/qqmlecmascript/data/js/include2.js b/tests/auto/qml/qqmlecmascript/data/js/include2.js
index 2a0c039dfa..7cfcdd95e2 100644
--- a/tests/auto/qml/qqmlecmascript/data/js/include2.js
+++ b/tests/auto/qml/qqmlecmascript/data/js/include2.js
@@ -2,3 +2,8 @@ test2 = true
var test2_1 = true
Qt.include("include3.js");
+
+function withTokensAllowedInJSButKeywordsInQML(char)
+{
+ var double;
+}
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index ecc3a4100c..2412ca7f92 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -43,6 +43,8 @@ private slots:
void subClassing_data();
void subClassing();
+
+ void nestingDepth();
};
void tst_v4misc::tdzOptimizations_data()
@@ -59,7 +61,7 @@ void tst_v4misc::tdzOptimizations()
QFETCH(QString, scriptToCompile);
QV4::ExecutionEngine v4;
- QV4::Script script(&v4, nullptr, scriptToCompile);
+ QV4::Script script(&v4, nullptr, /*parse as binding*/false, scriptToCompile);
script.parse();
QVERIFY(!v4.hasException);
@@ -173,6 +175,28 @@ void tst_v4misc::subClassing()
QVERIFY(!result.isError());
}
+void tst_v4misc::nestingDepth()
+{
+ { // left recursive
+ QString s(40000, '`');
+
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(s);
+ QVERIFY(result.isError());
+ QCOMPARE(result.toString(), "SyntaxError: Maximum statement or expression depth exceeded");
+ }
+
+ { // right recursive
+ QString s(200000, '-');
+ s += "\nd";
+
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(s);
+ QVERIFY(result.isError());
+ QCOMPARE(result.toString(), "SyntaxError: Maximum statement or expression depth exceeded");
+ }
+}
+
QTEST_MAIN(tst_v4misc);
#include "tst_v4misc.moc"
diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro
index 9662690395..bee0b9a37e 100644
--- a/tools/qmlcachegen/qmlcachegen.pro
+++ b/tools/qmlcachegen/qmlcachegen.pro
@@ -24,6 +24,7 @@ contains(CMAKE_BIN_DIR, "^\\.\\./.*") {
load(qt_build_paths)
+equals(QMAKE_HOST.os, Windows): CMAKE_BIN_SUFFIX = ".exe"
cmake_config_file.input = $$PWD/Qt5QuickCompilerConfig.cmake.in
cmake_config_file.output = $$MODULE_BASE_OUTDIR/lib/cmake/Qt5QuickCompiler/Qt5QuickCompilerConfig.cmake
QMAKE_SUBSTITUTES += cmake_config_file