From 6aeff1b5429ca97af052a7a172369585382096e8 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Thu, 9 Aug 2012 13:26:32 +1000 Subject: Reduce memory consumption of source coordinates Reduce memory consumption by storing source location coordinates as 16-bit variables (in run-time structures). Also modify qmlmin to restrict line lengths so that the column bound is not normally exceeded. Change-Id: I08605626ffbdf081b6da2aea1116bdfe24998572 Reviewed-by: Yann Bodson --- src/qml/qml/qqmlbinding.cpp | 26 +++--- src/qml/qml/qqmlbinding_p.h | 10 +- src/qml/qml/qqmlboundsignal.cpp | 4 +- src/qml/qml/qqmlboundsignal_p.h | 13 +-- src/qml/qml/qqmlcompiler_p.h | 2 +- src/qml/qml/qqmldata_p.h | 4 +- src/qml/qml/qqmldirparser.cpp | 24 ++--- src/qml/qml/qqmldirparser_p.h | 2 +- src/qml/qml/qqmlerror.cpp | 33 ++++--- src/qml/qml/qqmlexpression.cpp | 21 +++-- src/qml/qml/qqmlexpression_p.h | 10 +- src/qml/qml/qqmlglobal_p.h | 10 ++ src/qml/qml/qqmljavascriptexpression.cpp | 6 +- src/qml/qml/qqmljavascriptexpression_p.h | 6 +- src/qml/qml/qqmlscript.cpp | 12 ++- src/qml/qml/qqmlscript_p.h | 6 +- src/qml/qml/qqmlscriptstring_p.h | 6 +- src/qml/qml/qqmlvme.cpp | 4 +- src/qml/qml/qqmlvmemetaobject.cpp | 4 +- src/qml/qml/qqmlvmemetaobject_p.h | 4 +- src/qml/qml/v4/qv4bindings.cpp | 10 +- src/qml/qml/v4/qv4bindings_p.h | 6 +- src/qml/qml/v4/qv4compiler.cpp | 10 +- src/qml/qml/v4/qv4compiler_p_p.h | 12 +-- src/qml/qml/v4/qv4instruction_p.h | 2 +- src/qml/qml/v4/qv4ir.cpp | 20 ++-- src/qml/qml/v4/qv4ir_p.h | 30 +++--- src/qml/qml/v4/qv4irbuilder.cpp | 4 +- src/qml/qml/v8/qjsengine.cpp | 3 +- src/qml/qml/v8/qv8bindings.cpp | 15 +-- src/qml/qml/v8/qv8bindings_p.h | 2 +- src/qml/qml/v8/qv8engine.cpp | 6 +- src/qml/qml/v8/qv8engine_impl_p.h | 2 +- src/qml/qml/v8/qv8engine_p.h | 8 +- src/qml/qml/v8/qv8qobjectwrapper.cpp | 3 +- src/qml/qml/v8/qv8valuetypewrapper.cpp | 2 +- tests/auto/qml/qmlmin/tst_qmlmin.cpp | 4 +- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 20 ++-- tools/qmlmin/main.cpp | 104 ++++++++++++++++----- 39 files changed, 279 insertions(+), 191 deletions(-) diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 5860cbe19d..f5f0f49ddd 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -72,7 +72,7 @@ QQmlBinding::Identifier QQmlBinding::Invalid = -1; QQmlBinding * QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt, - const QString &url, int lineNumber) + const QString &url, quint16 lineNumber) { if (id < 0) return 0; @@ -102,7 +102,7 @@ static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = { QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt) : QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding), - m_lineNumber(-1), m_columnNumber(-1) + m_lineNumber(0), m_columnNumber(0) { setNotifyOnValueChanged(true); QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt)); @@ -164,7 +164,7 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt) : QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding), - m_lineNumber(-1), m_columnNumber(-1) + m_lineNumber(0), m_columnNumber(0) { setNotifyOnValueChanged(true); QQmlAbstractExpression::setContext(ctxt); @@ -179,9 +179,9 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt QQmlBinding::QQmlBinding(const QString &str, bool isRewritten, QObject *obj, QQmlContextData *ctxt, - const QString &url, int lineNumber, int columnNumber) + const QString &url, quint16 lineNumber, quint16 columnNumber) : QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding), - m_lineNumber(-1), m_columnNumber(-1) + m_url(url), m_lineNumber(lineNumber), m_columnNumber(columnNumber) { setNotifyOnValueChanged(true); QQmlAbstractExpression::setContext(ctxt); @@ -195,12 +195,9 @@ QQmlBinding::QQmlBinding(const QString &str, bool isRewritten, QObject *obj, code = rewriteBinding(str); } - m_url = url; - m_lineNumber = lineNumber; - m_columnNumber = columnNumber; m_expression = str.toUtf8(); - v8function = evalFunction(ctxt, obj, code, url, lineNumber); + v8function = evalFunction(ctxt, obj, code, url, m_lineNumber); } /*! @@ -212,7 +209,7 @@ QQmlBinding::QQmlBinding(const QString &str, bool isRewritten, QObject *obj, new QQmlBinding(&function, scope, ctxt); */ QQmlBinding::QQmlBinding(void *functionPtr, QObject *obj, QQmlContextData *ctxt, - const QString &url, int lineNumber, int columnNumber) + const QString &url, quint16 lineNumber, quint16 columnNumber) : QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding), m_url(url), m_lineNumber(lineNumber), m_columnNumber(columnNumber) { @@ -252,13 +249,16 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) if (QQmlData::wasDeleted(object())) return; + int lineNo = qmlSourceCoordinate(m_lineNumber); + int columnNo = qmlSourceCoordinate(m_columnNumber); + QQmlTrace trace("General Binding Update"); trace.addDetail("URL", m_url); - trace.addDetail("Line", m_lineNumber); - trace.addDetail("Column", m_columnNumber); + trace.addDetail("Line", lineNo); + trace.addDetail("Column", columnNo); if (!updatingFlag()) { - QQmlBindingProfiler prof(m_url, m_lineNumber, m_columnNumber, QQmlProfilerService::QmlBinding); + QQmlBindingProfiler prof(m_url, lineNo, columnNo, QQmlProfilerService::QmlBinding); setUpdatingFlag(true); QQmlAbstractExpression::DeleteWatcher watcher(this); diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 888145126c..f8e4dcc039 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -83,9 +83,9 @@ public: QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *); QQmlBinding(const QString &, QObject *, QQmlContextData *); QQmlBinding(const QString &, bool isRewritten, QObject *, QQmlContextData *, - const QString &url, int lineNumber, int columnNumber); + const QString &url, quint16 lineNumber, quint16 columnNumber); QQmlBinding(void *, QObject *, QQmlContextData *, - const QString &url, int lineNumber, int columnNumber); + const QString &url, quint16 lineNumber, quint16 columnNumber); void setTarget(const QQmlProperty &); void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *); @@ -119,7 +119,7 @@ public: typedef int Identifier; static Identifier Invalid; - static QQmlBinding *createBinding(Identifier, QObject *, QQmlContext *, const QString &, int); + static QQmlBinding *createBinding(Identifier, QObject *, QQmlContext *, const QString &, quint16); QVariant evaluate(); @@ -152,8 +152,8 @@ private: // XXX It would be good if we could get rid of these in most circumstances QString m_url; - int m_lineNumber; - int m_columnNumber; + quint16 m_lineNumber; + quint16 m_columnNumber; QByteArray m_expression; }; diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 5f5e7b09af..071a9ed033 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -67,7 +67,7 @@ static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = { }; QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression, - bool isRewritten, const QString &fileName, int line, int column) + bool isRewritten, const QString &fileName, quint16 line, quint16 column) : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable) { setNotifyOnValueChanged(false); @@ -85,7 +85,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObj } QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression, - bool isRewritten, const QString &fileName, int line, int column) + bool isRewritten, const QString &fileName, quint16 line, quint16 column) : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable) { setNotifyOnValueChanged(false); diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 81bcb0bc06..879b84294c 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -61,6 +61,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -69,9 +70,9 @@ class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpres { public: QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression, - bool isRewritten, const QString &fileName, int line, int column); + bool isRewritten, const QString &fileName, quint16 line, quint16 column); QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression, - bool isRewritten, const QString &fileName, int line, int column); + bool isRewritten, const QString &fileName, quint16 line, quint16 column); // "inherited" from QQmlJavaScriptExpression. static QString expressionIdentifier(QQmlJavaScriptExpression *); @@ -81,8 +82,8 @@ public: void evaluate(QObject *secondaryScope = 0); QString sourceFile() const { return m_fileName; } - int lineNumber() const { return m_line; } - int columnNumber() const { return m_column; } + quint16 lineNumber() const { return m_line; } + quint16 columnNumber() const { return m_column; } QString expression() const; QQmlEngine *engine() const { return context() ? context()->engine : 0; } @@ -100,8 +101,8 @@ private: QString m_expression; //only used when expression needs to be rewritten QString m_fileName; - int m_line; - int m_column; + quint16 m_line; + quint16 m_column; bool m_expressionFunctionValid:1; bool m_expressionFunctionRewritten:1; diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index fc80ca9b6b..9d610c00c8 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -441,7 +441,7 @@ private: { ComponentStat() : lineNumber(0), ids(0), objects(0) {} - int lineNumber; + quint16 lineNumber; int ids; QList scriptBindings; diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 225d6d854d..92c1a0cc68 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -164,8 +164,8 @@ public: void clearBindingBit(int); void setBindingBit(QObject *obj, int); - ushort lineNumber; - ushort columnNumber; + quint16 lineNumber; + quint16 columnNumber; QQmlCompiledData *compiledData; unsigned int deferredIdx; diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp index 0bfc4eb4bd..ae328ca240 100644 --- a/src/qml/qml/qqmldirparser.cpp +++ b/src/qml/qml/qqmldirparser.cpp @@ -98,7 +98,7 @@ bool QQmlDirParser::parse(const QString &source) _components.clear(); _scripts.clear(); - int lineNumber = 0; + quint16 lineNumber = 0; bool firstLine = true; const QChar *ch = source.constData(); @@ -141,7 +141,7 @@ bool QQmlDirParser::parse(const QString &source) ++ch; if (invalidLine) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("invalid qmldir directive contains too many tokens")); continue; } else if (sectionCount == 0) { @@ -149,17 +149,17 @@ bool QQmlDirParser::parse(const QString &source) } else if (sections[0] == QLatin1String("module")) { if (sectionCount != 2) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1)); continue; } if (!_typeNamespace.isEmpty()) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("only one module identifier directive may be defined in a qmldir file")); continue; } if (!firstLine) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("module identifier directive must be the first command in a qmldir file")); continue; } @@ -168,7 +168,7 @@ bool QQmlDirParser::parse(const QString &source) } else if (sections[0] == QLatin1String("plugin")) { if (sectionCount < 2) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1)); continue; @@ -180,7 +180,7 @@ bool QQmlDirParser::parse(const QString &source) } else if (sections[0] == QLatin1String("internal")) { if (sectionCount != 3) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); continue; } @@ -189,7 +189,7 @@ bool QQmlDirParser::parse(const QString &source) _components.insertMulti(entry.typeName, entry); } else if (sections[0] == QLatin1String("typeinfo")) { if (sectionCount != 2) { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1)); continue; } @@ -207,9 +207,9 @@ bool QQmlDirParser::parse(const QString &source) const int dotIndex = version.indexOf(QLatin1Char('.')); if (dotIndex == -1) { - reportError(lineNumber, -1, QLatin1String("expected '.'")); + reportError(lineNumber, 0, QLatin1String("expected '.'")); } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) { - reportError(lineNumber, -1, QLatin1String("unexpected '.'")); + reportError(lineNumber, 0, QLatin1String("unexpected '.'")); } else { bool validVersionNumber = false; const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber); @@ -232,7 +232,7 @@ bool QQmlDirParser::parse(const QString &source) } } } else { - reportError(lineNumber, -1, + reportError(lineNumber, 0, QString::fromUtf8("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount)); } @@ -242,7 +242,7 @@ bool QQmlDirParser::parse(const QString &source) return hasError(); } -void QQmlDirParser::reportError(int line, int column, const QString &description) +void QQmlDirParser::reportError(quint16 line, quint16 column, const QString &description) { QQmlError error; error.setLine(line); diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h index 7a9078180e..c4358f133e 100644 --- a/src/qml/qml/qqmldirparser_p.h +++ b/src/qml/qml/qqmldirparser_p.h @@ -138,7 +138,7 @@ public: #endif private: - void reportError(int line, int column, const QString &message); + void reportError(quint16 line, quint16 column, const QString &message); private: QList _errors; diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index ce7fd01fdf..fc1c1b5998 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qqmlerror.h" +#include "qqmlglobal_p.h" #include #include @@ -81,12 +82,12 @@ public: QUrl url; QString description; - int line; - int column; + quint16 line; + quint16 column; }; QQmlErrorPrivate::QQmlErrorPrivate() -: line(-1), column(-1) +: line(0), column(0) { } @@ -182,7 +183,7 @@ void QQmlError::setDescription(const QString &description) */ int QQmlError::line() const { - if (d) return d->line; + if (d) return qmlSourceCoordinate(d->line); else return -1; } @@ -192,7 +193,7 @@ int QQmlError::line() const void QQmlError::setLine(int line) { if (!d) d = new QQmlErrorPrivate; - d->line = line; + d->line = qmlSourceCoordinate(line); } /*! @@ -200,7 +201,7 @@ void QQmlError::setLine(int line) */ int QQmlError::column() const { - if (d) return d->column; + if (d) return qmlSourceCoordinate(d->column); else return -1; } @@ -210,7 +211,7 @@ int QQmlError::column() const void QQmlError::setColumn(int column) { if (!d) d = new QQmlErrorPrivate; - d->column = column; + d->column = qmlSourceCoordinate(column); } /*! @@ -219,14 +220,20 @@ void QQmlError::setColumn(int column) QString QQmlError::toString() const { QString rv; - if (url().isEmpty()) { + + QUrl u(url()); + int l(line()); + + if (u.isEmpty()) { rv = QLatin1String(""); - } else if (line() != -1) { - rv = url().toString() + QLatin1Char(':') + QString::number(line()); - if(column() != -1) - rv += QLatin1Char(':') + QString::number(column()); + } else if (l != -1) { + rv = u.toString() + QLatin1Char(':') + QString::number(l); + + int c(column()); + if (c != -1) + rv += QLatin1Char(':') + QString::number(c); } else { - rv = url().toString(); + rv = u.toString(); } rv += QLatin1String(": ") + description(); diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 76d31448e5..d003b5af3f 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -42,6 +42,7 @@ #include "qqmlexpression.h" #include "qqmlexpression_p.h" +#include "qqmlglobal_p.h" #include "qqmlengine_p.h" #include "qqmlcontext_p.h" #include "qqmlrewrite_p.h" @@ -60,7 +61,7 @@ static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = { QQmlExpressionPrivate::QQmlExpressionPrivate() : QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable), expressionFunctionValid(true), expressionFunctionRewritten(false), - line(-1) + line(0), column(0) { } @@ -82,7 +83,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + quint16 lineNumber, quint16 columnNumber) { url = srcUrl; line = lineNumber; @@ -99,7 +100,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + quint16 lineNumber, quint16 columnNumber) { url = srcUrl; line = lineNumber; @@ -127,7 +128,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, QQmlExpression * QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, const QString &expr, bool isRewritten, - const QString &url, int lineNumber, int columnNumber) + const QString &url, quint16 lineNumber, quint16 columnNumber) { return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, *new QQmlExpressionPrivate); @@ -183,7 +184,7 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, : QObject(dd, 0) { Q_D(QQmlExpression); - d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber); + d->init(ctxt, expr, isRewritten, object, url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); } /*! \internal */ @@ -195,7 +196,7 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, : QObject(dd, 0) { Q_D(QQmlExpression); - d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber); + d->init(ctxt, expr, isRewritten, object, url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); } /*! @@ -450,7 +451,7 @@ QString QQmlExpression::sourceFile() const int QQmlExpression::lineNumber() const { Q_D(const QQmlExpression); - return d->line; + return qmlSourceCoordinate(d->line); } /*! @@ -460,7 +461,7 @@ int QQmlExpression::lineNumber() const int QQmlExpression::columnNumber() const { Q_D(const QQmlExpression); - return d->column; + return qmlSourceCoordinate(d->column); } /*! @@ -471,8 +472,8 @@ void QQmlExpression::setSourceLocation(const QString &url, int line, int column) { Q_D(QQmlExpression); d->url = url; - d->line = line; - d->column = column; + d->line = qmlSourceCoordinate(line); + d->column = qmlSourceCoordinate(column); } /*! diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h index 372d72c655..3108be26d8 100644 --- a/src/qml/qml/qqmlexpression_p.h +++ b/src/qml/qml/qqmlexpression_p.h @@ -79,8 +79,8 @@ public: ~QQmlExpressionPrivate(); void init(QQmlContextData *, const QString &, QObject *); - void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, int, int); - void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, int, int); + void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, quint16, quint16); + void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, quint16, quint16); QVariant value(bool *isUndefined = 0); @@ -92,7 +92,7 @@ public: void _q_notify(); static QQmlExpression *create(QQmlContextData *, QObject *, const QString &, bool, - const QString &, int, int); + const QString &, quint16, quint16); bool expressionFunctionValid:1; bool expressionFunctionRewritten:1; @@ -109,8 +109,8 @@ public: v8::Persistent v8function; QString url; // This is a QString for a reason. QUrls are slooooooow... - int line; - int column; + quint16 line; + quint16 column; QString name; //function name, hint for the debugger }; diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index ff337634ee..e79a91f035 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -165,6 +165,16 @@ T qmlobject_cast(QObject *object) return 0; } +inline quint16 qmlSourceCoordinate(int n) +{ + return (n > 0 && n <= USHRT_MAX) ? static_cast(n) : 0; +} + +inline int qmlSourceCoordinate(quint16 n) +{ + return (n == 0) ? -1 : static_cast(n); +} + #define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments) \ do { \ QObject *sender = (Sender); \ diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index a33db84a7f..650123bb8c 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -67,7 +67,7 @@ void QQmlDelayedError::setMessage(v8::Handle message) m_message = qPersistentNew(message); } -void QQmlDelayedError::setErrorLocation(const QUrl &url, int line, int column) +void QQmlDelayedError::setErrorLocation(const QUrl &url, quint16 line, quint16 column) { m_error.setUrl(url); m_error.setLine(line); @@ -322,7 +322,7 @@ void QQmlJavaScriptExpression::exceptionToError(v8::Handle message, v8::Persistent QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scope, const char *code, int codeLength, - const QString &filename, int line, + const QString &filename, quint16 line, v8::Persistent *qmlscope) { QQmlEngine *engine = ctxt->engine; @@ -364,7 +364,7 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scope, // Callee owns the persistent handle v8::Persistent QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scope, - const QString &code, const QString &filename, int line, + const QString &code, const QString &filename, quint16 line, v8::Persistent *qmlscope) { QQmlEngine *engine = ctxt->engine; diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 4c89a086a3..dc9b4b63c6 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -82,7 +82,7 @@ public: inline void clearError() { qPersistentDispose(m_message); m_error = QQmlError(); } void setMessage(v8::Handle message); - void setErrorLocation(const QUrl &url, int line, int column); + void setErrorLocation(const QUrl &url, quint16 line, quint16 column); void setErrorDescription(const QString &description); private: @@ -146,11 +146,11 @@ public: static void exceptionToError(v8::Handle, QQmlError &); static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, - int line, + quint16 line, v8::Persistent *qmlscope = 0); static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, const char *code, int codeLength, - const QString &filename, int line, + const QString &filename, quint16 line, v8::Persistent *qmlscope = 0); protected: ~QQmlJavaScriptExpression(); diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp index 985b6b6181..eb55f9fa71 100644 --- a/src/qml/qml/qqmlscript.cpp +++ b/src/qml/qml/qqmlscript.cpp @@ -760,7 +760,7 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, state.property->addValue(v); } else { Property *defaultProp = state.object->getDefaultProperty(); - if (defaultProp->location.start.line == -1) { + if (defaultProp->location.start.line == 0) { defaultProp->location = v->location; defaultProp->location.end = defaultProp->location.start; defaultProp->location.range.length = 0; @@ -1523,8 +1523,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri int startColumn = l.tokenStartColumn(); QQmlError importError; - importError.setLine(startLine); - importError.setColumn(startColumn); + importError.setLine(startLine + 1); // 0-based, adjust to be 1-based token = l.lex(); @@ -1545,6 +1544,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (!file.endsWith(js)) { importError.setDescription(QCoreApplication::translate("QQmlParser","Imported file must be a script")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1565,6 +1565,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (invalidImport) { importError.setDescription(QCoreApplication::translate("QQmlParser","File import requires a qualifier")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1580,6 +1581,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1600,6 +1602,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri while (true) { if (!isUriToken(token)) { importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid module URI")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1619,6 +1622,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) { importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a version")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1643,6 +1647,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (invalidImport) { importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a qualifier")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } @@ -1658,6 +1663,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) { importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier")); + importError.setColumn(l.tokenStartColumn()); *error = importError; return rv; } diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h index 60e667e4ea..f2e108e3d7 100644 --- a/src/qml/qml/qqmlscript_p.h +++ b/src/qml/qml/qqmlscript_p.h @@ -76,9 +76,9 @@ namespace QQmlScript { struct Location { - Location() : line(-1), column(-1) {} - int line; - int column; + Location() : line(0), column(0) {} + quint16 line; + quint16 column; inline bool operator<(const Location &other) { return line < other.line || diff --git a/src/qml/qml/qqmlscriptstring_p.h b/src/qml/qml/qqmlscriptstring_p.h index 97c02d21d7..362adb9157 100644 --- a/src/qml/qml/qqmlscriptstring_p.h +++ b/src/qml/qml/qqmlscriptstring_p.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class Q_AUTOTEST_EXPORT QQmlScriptStringPrivate : public QSharedData { public: - QQmlScriptStringPrivate() : context(0), scope(0), bindingId(-1), lineNumber(-1), columnNumber(-1), + QQmlScriptStringPrivate() : context(0), scope(0), bindingId(-1), lineNumber(0), columnNumber(0), numberValue(0), isStringLiteral(false), isNumberLiteral(false) {} //for testing @@ -60,8 +60,8 @@ public: QObject *scope; QString script; int bindingId; - int lineNumber; - int columnNumber; + quint16 lineNumber; + quint16 columnNumber; double numberValue; bool isStringLiteral; bool isNumberLiteral; diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 60e911d935..d6b60f724c 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -773,8 +773,8 @@ QObject *QQmlVME::run(QList *errors, QObject *scope = objects.at(objects.count() - 1 - instr.scope); QQmlScriptString ss(PRIMITIVES.at(instr.value), CTXT->asQQmlContext(), scope); ss.d.data()->bindingId = instr.bindingId; - ss.d.data()->lineNumber = instr.line; - ss.d.data()->columnNumber = instr.column; + ss.d.data()->lineNumber = qmlSourceCoordinate(instr.line); + ss.d.data()->columnNumber = qmlSourceCoordinate(instr.column); ss.d.data()->isStringLiteral = instr.isStringLiteral; ss.d.data()->isNumberLiteral = instr.isNumberLiteral; ss.d.data()->numberValue = instr.numberValue; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 902a6073b8..2ebb4526df 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -66,7 +66,7 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr() { } -void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *o) +void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) { if (m_target && m_index >= 0) { if (m_isVar && m_target->varPropertiesInitialized && !m_target->varProperties.IsEmpty()) { @@ -1151,7 +1151,7 @@ void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPrope interceptors = interceptor; } -int QQmlVMEMetaObject::vmeMethodLineNumber(int index) +quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index) { if (index < methodOffset()) { Q_ASSERT(parent.isT1()); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 4216e09733..3d70761563 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -122,7 +122,7 @@ struct QQmlVMEMetaData int parameterCount; int bodyOffset; int bodyLength; - int lineNumber; + quint16 lineNumber; }; PropertyData *propertyData() const { @@ -167,7 +167,7 @@ public: bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const; void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor); v8::Handle vmeMethod(int index); - int vmeMethodLineNumber(int index); + quint16 vmeMethodLineNumber(int index); void setVmeMethod(int index, v8::Persistent); v8::Handle vmeProperty(int index); void setVMEProperty(int index, v8::Handle v); diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 02f2bfc863..643a6197fb 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -299,7 +299,7 @@ QV4Bindings::~QV4Bindings() } QQmlAbstractBinding *QV4Bindings::configBinding(int index, int fallbackIndex, QObject *target, QObject *scope, - int property, int propType, int line, int column) + int property, int propType, quint16 line, quint16 column) { Q_ASSERT(propType <= std::numeric_limits::max()); @@ -556,7 +556,7 @@ QByteArray testResultToString(const QVariant &result, bool undefined) } } -static void testBindingResult(const QString &binding, int line, int column, +static void testBindingResult(const QString &binding, quint16 line, quint16 column, QQmlContextData *context, QObject *scope, const Register &result, int resultType) { @@ -658,7 +658,7 @@ static void testBindingResult(const QString &binding, int line, int column, } } -static void testBindingException(const QString &binding, int line, int column, +static void testBindingException(const QString &binding, quint16 line, quint16 column, QQmlContextData *context, QObject *scope) { QQmlExpression expression(context->asQQmlContext(), scope, binding); @@ -683,8 +683,8 @@ static void throwException(int id, QQmlDelayedError *error, else error->setErrorDescription(description); if (id != 0xFF) { - quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); - error->setErrorLocation(context->url, (e >> 32) & 0xFFFFFFFF, e & 0xFFFFFFFF); + quint32 e = *((quint32 *)(program->data() + program->exceptionDataOffset) + id); + error->setErrorLocation(context->url, (e >> 16), (e & 0xFFFF)); } else { error->setErrorLocation(context->url, -1, -1); } diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h index dd63f6d9f5..eae5703c50 100644 --- a/src/qml/qml/v4/qv4bindings_p.h +++ b/src/qml/qml/v4/qv4bindings_p.h @@ -73,7 +73,7 @@ public: QQmlAbstractBinding *configBinding(int index, int fallbackIndex, QObject *target, QObject *scope, int property, int propType, - int line, int column); + quint16 line, quint16 column); #ifdef QML_THREADED_INTERPRETER static void **getDecodeInstrTable(); @@ -107,8 +107,8 @@ public: quint16 propType; QObject *scope; - int line; - int column; + quint16 line; + quint16 column; QPointerValuePair target; quint32 executedBlocks; diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index b697204839..1506d09ce9 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -73,7 +73,7 @@ QV4CompilerPrivate::QV4CompilerPrivate() // // tracing // -void QV4CompilerPrivate::trace(int line, int column) +void QV4CompilerPrivate::trace(quint16 line, quint16 column) { bytecode.clear(); @@ -1401,13 +1401,13 @@ quint32 QV4CompilerPrivate::subscriptionBlockMask(const QStringList &sub) return *uiter; } -quint8 QV4CompilerPrivate::exceptionId(quint32 line, quint32 column) +quint8 QV4CompilerPrivate::exceptionId(quint16 line, quint16 column) { quint8 rv = 0xFF; if (exceptions.count() < 0xFF) { rv = (quint8)exceptions.count(); - quint64 e = line; - e <<= 32; + quint32 e = line; + e <<= 16; e |= column; exceptions.append(e); } @@ -1493,7 +1493,7 @@ QByteArray QV4CompilerPrivate::buildSignalTable() const QByteArray QV4CompilerPrivate::buildExceptionData() const { QByteArray rv; - rv.resize(committed.exceptions.count() * sizeof(quint64)); + rv.resize(committed.exceptions.count() * sizeof(quint32)); ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); return rv; } diff --git a/src/qml/qml/v4/qv4compiler_p_p.h b/src/qml/qml/v4/qv4compiler_p_p.h index 12beaa0fbb..989e428350 100644 --- a/src/qml/qml/v4/qv4compiler_p_p.h +++ b/src/qml/qml/v4/qv4compiler_p_p.h @@ -136,9 +136,9 @@ public: int subscriptionIndex(const QStringList &); quint32 subscriptionBlockMask(const QStringList &); - quint8 exceptionId(quint32 line, quint32 column); + quint8 exceptionId(quint16 line, quint16 column); quint8 exceptionId(QQmlJS::AST::ExpressionNode *); - QVector exceptions; + QVector exceptions; QQmlAssociationList usedSubscriptionIds; int subscriptionOffset; @@ -164,7 +164,7 @@ public: //QQmlJS::Bytecode bytecode; QByteArray bytecode; QByteArray data; - QVector exceptions; + QVector exceptions; int subscriptionCount; QList > subscriptions; @@ -191,7 +191,7 @@ protected: // // tracing // - void trace(int line, int column); + void trace(quint16 line, quint16 column); void trace(QVector *blocks); void traceExpression(QQmlJS::IR::Expr *e, quint8 r); @@ -235,8 +235,8 @@ private: bool usedSubscriptionIdsChanged; quint32 currentBlockMask; - int bindingLine; - int bindingColumn; + quint16 bindingLine; + quint16 bindingColumn; bool invalidatable; }; diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h index 2e06bd0850..763cd2d67b 100644 --- a/src/qml/qml/v4/qv4instruction_p.h +++ b/src/qml/qml/v4/qv4instruction_p.h @@ -231,7 +231,7 @@ union Q_AUTOTEST_EXPORT V4Instr { struct instr_id { QML_V4_INSTR_HEADER quint16 column; - quint32 line; + quint16 line; }; struct instr_init { diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp index ed25f28fa3..51f61716f0 100644 --- a/src/qml/qml/v4/qv4ir.cpp +++ b/src/qml/qml/v4/qv4ir.cpp @@ -210,7 +210,7 @@ QString String::escape(const QStringRef &s) return r; } -void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column) +void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint16 line, quint16 column) { this->type = type; this->base = base; @@ -482,12 +482,12 @@ Expr *BasicBlock::STRING(const QStringRef &value) return e; } -Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) +Name *BasicBlock::NAME(const QString &id, quint16 line, quint16 column) { return NAME(0, id, line, column); } -Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column) +Name *BasicBlock::NAME(Name *base, const QString &id, quint16 line, quint16 column) { Name *e = function->pool->New(); e->init(base, InvalidType, @@ -497,7 +497,7 @@ Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 colu } Name *BasicBlock::SYMBOL(Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, - quint32 line, quint32 column) + quint16 line, quint16 column) { Name *name = SYMBOL(/*base = */ 0, type, id, meta, property, line, column); name->storage = storage; @@ -505,7 +505,7 @@ Name *BasicBlock::SYMBOL(Type type, const QString &id, const QQmlMetaObject &met } Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, - quint32 line, quint32 column) + quint16 line, quint16 column) { Name *name = function->pool->New(); name->init(base, type, function->newString(id), @@ -517,7 +517,7 @@ Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMet } Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, - quint32 line, quint32 column) + quint16 line, quint16 column) { Name *name = function->pool->New(); name->init(base, type, function->newString(id), @@ -527,7 +527,7 @@ Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMet return name; } -Name *BasicBlock::ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column) +Name *BasicBlock::ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint16 line, quint16 column) { Name *name = function->pool->New(); name->init(/*base = */ 0, IR::ObjectType, @@ -540,7 +540,7 @@ Name *BasicBlock::ID_OBJECT(const QString &id, const QQmlScript::Object *object, } Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, - quint32 line, quint32 column) + quint16 line, quint16 column) { Name *name = function->pool->New(); name->init(/*base = */ 0, IR::AttachType, @@ -552,7 +552,7 @@ Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Nam } Name *BasicBlock::MODULE_OBJECT(const QString &id, const QQmlMetaObject &meta, Name::Storage storage, - quint32 line, quint32 column) + quint16 line, quint16 column) { Name *name = function->pool->New(); name->init(/*base = */ 0, IR::ObjectType, @@ -668,7 +668,7 @@ Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) return s; } -Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column) +Stmt *BasicBlock::RET(Expr *expr, Type type, quint16 line, quint16 column) { if (isTerminated()) return 0; diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h index 9b36762356..f6e20a7187 100644 --- a/src/qml/qml/v4/qv4ir_p.h +++ b/src/qml/qml/v4/qv4ir_p.h @@ -283,10 +283,10 @@ struct Name: Expr { QQmlPropertyData *property; Storage storage; BuiltinSymbol builtin; - quint32 line; - quint32 column; + quint16 line; + quint16 column; - void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column); + void init(Name *base, Type type, const QString *id, Symbol symbol, quint16 line, quint16 column); inline bool is(Symbol s) const { return s == symbol; } inline bool isNot(Symbol s) const { return s != symbol; } @@ -468,10 +468,10 @@ struct CJump: Stmt { struct Ret: Stmt { Expr *expr; Type type; - quint32 line; - quint32 column; + quint16 line; + quint16 column; - void init(Expr *expr, Type type, quint32 line, quint32 column) + void init(Expr *expr, Type type, quint16 line, quint16 column) { this->expr = expr; this->type = type; @@ -538,14 +538,14 @@ struct BasicBlock { Expr *CONST(Type type, double value); Expr *STRING(const QStringRef &value); - Name *NAME(const QString &id, quint32 line, quint32 column); - Name *NAME(Name *base, const QString &id, quint32 line, quint32 column); - Name *SYMBOL(Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column); - Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, quint32 line, quint32 column); - Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column); - Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column); - Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint32 line, quint32 column); - Name *MODULE_OBJECT(const QString &id, const QQmlMetaObject &meta, Name::Storage storage, quint32 line, quint32 column); + Name *NAME(const QString &id, quint16 line, quint16 column); + Name *NAME(Name *base, const QString &id, quint16 line, quint16 column); + Name *SYMBOL(Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint16 line, quint16 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, quint16 line, quint16 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint16 line, quint16 column); + Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint16 line, quint16 column); + Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint16 line, quint16 column); + Name *MODULE_OBJECT(const QString &id, const QQmlMetaObject &meta, Name::Storage storage, quint16 line, quint16 column); Expr *UNOP(AluOp op, Expr *expr); Expr *BINOP(AluOp op, Expr *left, Expr *right); @@ -556,7 +556,7 @@ struct BasicBlock { Stmt *JUMP(BasicBlock *target); Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse); - Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column); + Stmt *RET(Expr *expr, Type type, quint16 line, quint16 column); void dump(QTextStream &out); }; diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 93c552173f..37d71f1941 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -424,8 +424,8 @@ bool QV4IRBuilder::visit(AST::ThisExpression *) bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) { - const quint32 line = ast->identifierToken.startLine; - const quint32 column = ast->identifierToken.startColumn; + const quint16 line = ast->identifierToken.startLine; + const quint16 column = ast->identifierToken.startColumn; const QString name = ast->name.toString(); diff --git a/src/qml/qml/v8/qjsengine.cpp b/src/qml/qml/v8/qjsengine.cpp index 080540eeef..2bc4ffca7c 100644 --- a/src/qml/qml/v8/qjsengine.cpp +++ b/src/qml/qml/v8/qjsengine.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #undef Q_D #undef Q_Q @@ -249,7 +250,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in Q_D(QJSEngine); QScriptIsolate api(d, QScriptIsolate::NotNullEngine); v8::HandleScope handleScope; - return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber)); + return QJSValuePrivate::get(d->evaluate(program, fileName, qmlSourceCoordinate(lineNumber))); } /*! diff --git a/src/qml/qml/v8/qv8bindings.cpp b/src/qml/qml/v8/qv8bindings.cpp index 5a6abdbe22..9999ebc7fa 100644 --- a/src/qml/qml/v8/qv8bindings.cpp +++ b/src/qml/qml/v8/qv8bindings.cpp @@ -144,12 +144,15 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags) if (QQmlData::wasDeleted(object())) return; + int lineNo = qmlSourceCoordinate(instruction->line); + int columnNo = qmlSourceCoordinate(instruction->column); + QQmlTrace trace("V8 Binding Update"); trace.addDetail("URL", parent->url()); - trace.addDetail("Line", instruction->line); - trace.addDetail("Column", instruction->column); + trace.addDetail("Line", lineNo); + trace.addDetail("Column", columnNo); - QQmlBindingProfiler prof(parent->urlString(), instruction->line, instruction->column, QQmlProfilerService::V8Binding); + QQmlBindingProfiler prof(parent->urlString(), lineNo, columnNo, QQmlProfilerService::V8Binding); if (!updatingFlag()) { setUpdatingFlag(true); @@ -179,7 +182,7 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags) if (!watcher.wasDeleted() && !destroyedFlag()) { if (needsErrorLocationData) - delayedError()->setErrorLocation(parent->url(), instruction->line, -1); + delayedError()->setErrorLocation(parent->url(), instruction->line, 0); if (hasError()) { if (!delayedError()->addError(ep)) ep->warning(this->error(context->engine)); @@ -202,7 +205,7 @@ QString QV8Bindings::Binding::expressionIdentifier(QQmlJavaScriptExpression *e) { Binding *This = static_cast(e); return This->parent->urlString() + QLatin1Char(':') + - QString::number(This->instruction->line); + QString::number(qmlSourceCoordinate(This->instruction->line)); } void QV8Bindings::Binding::expressionChanged(QQmlJavaScriptExpression *e) @@ -224,7 +227,7 @@ void QV8Bindings::Binding::destroy(QQmlAbstractBinding *_This) } QV8Bindings::QV8Bindings(QQmlCompiledData::V8Program *program, - int line, + quint16 line, QQmlContextData *context) : program(program), bindings(0), refCount(1) { diff --git a/src/qml/qml/v8/qv8bindings_p.h b/src/qml/qml/v8/qv8bindings_p.h index c7c2a3c960..ca5c028824 100644 --- a/src/qml/qml/v8/qv8bindings_p.h +++ b/src/qml/qml/v8/qv8bindings_p.h @@ -72,7 +72,7 @@ class QV8Bindings : public QQmlAbstractExpression { public: QV8Bindings(QQmlCompiledData::V8Program *, - int line, + quint16 line, QQmlContextData *context); virtual ~QV8Bindings(); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index f98464868a..d86fc6b12f 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -446,7 +446,7 @@ v8::Handle QV8Engine::fromVariant(const QVariant &variant) // A handle scope and context must be entered v8::Local QV8Engine::qmlModeCompile(const QString &source, const QString &fileName, - int lineNumber) + quint16 lineNumber) { v8::Local v8source = m_stringWrapper.toString(source); v8::Local v8fileName = m_stringWrapper.toString(fileName); @@ -463,7 +463,7 @@ v8::Local QV8Engine::qmlModeCompile(const QString &source, // source can be either ascii or utf8. v8::Local QV8Engine::qmlModeCompile(const char *source, int sourceLength, const QString &fileName, - int lineNumber) + quint16 lineNumber) { if (sourceLength == -1) sourceLength = int(strlen(source)); @@ -1424,7 +1424,7 @@ qint64 QV8Engine::stopTimer(const QString &timerName, bool *wasRunning) return m_time.elapsed() - startedAt; } -int QV8Engine::consoleCountHelper(const QString &file, int line, int column) +int QV8Engine::consoleCountHelper(const QString &file, quint16 line, quint16 column) { const QString key = file + QString::number(line) + QString::number(column); int number = m_consoleCount.value(key, 0); diff --git a/src/qml/qml/v8/qv8engine_impl_p.h b/src/qml/qml/v8/qv8engine_impl_p.h index 41518bb352..9927d058b1 100644 --- a/src/qml/qml/v8/qv8engine_impl_p.h +++ b/src/qml/qml/v8/qv8engine_impl_p.h @@ -152,7 +152,7 @@ inline QJSValuePrivate::PropertyFlags QV8Engine::getPropertyFlags(v8::Handle QV8Engine::evaluate(const QString& program, const QString& fileName, int lineNumber) +QScriptPassPointer QV8Engine::evaluate(const QString& program, const QString& fileName, quint16 lineNumber) { v8::TryCatch tryCatch; v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1)); diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 1e91de91b6..7b0afafe7f 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -301,10 +301,10 @@ public: // Compile \a source (from \a fileName at \a lineNumber) in QML mode v8::Local qmlModeCompile(const QString &source, const QString &fileName = QString(), - int lineNumber = 1); + quint16 lineNumber = 1); v8::Local qmlModeCompile(const char *source, int sourceLength = -1, const QString &fileName = QString(), - int lineNumber = 1); + quint16 lineNumber = 1); // Return the QML global "scope" object for the \a ctxt context and \a scope object. inline v8::Local qmlScope(QQmlContextData *ctxt, QObject *scope); @@ -364,7 +364,7 @@ public: inline v8::Handle makeJSValue(QJSValue::SpecialValue value); inline v8::Local makeJSValue(const QString &value); - inline QScriptPassPointer evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); + inline QScriptPassPointer evaluate(const QString &program, const QString &fileName = QString(), quint16 lineNumber = 1); QScriptPassPointer evaluate(v8::Handle script, v8::TryCatch& tryCatch); QScriptPassPointer newArray(uint length); @@ -402,7 +402,7 @@ public: qint64 stopTimer(const QString &timerName, bool *wasRunning); // used for console.count() - int consoleCountHelper(const QString &file, int line, int column); + int consoleCountHelper(const QString &file, quint16 line, quint16 column); QObject *qtObjectFromJS(v8::Handle value); QSet visitedConversionObjects; diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index 14694a52fd..58a7520297 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -620,7 +621,7 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert int columnNumber = frame->GetColumn(); QString url = engine->toString(frame->GetScriptName()); - newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber); + newBinding = new QQmlBinding(&function, object, context, url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); newBinding->setTarget(object, *property, context); newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QQmlBinding::RequiresThisObject); diff --git a/src/qml/qml/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp index 91875150ec..6a0521b8be 100644 --- a/src/qml/qml/v8/qv8valuetypewrapper.cpp +++ b/src/qml/qml/v8/qv8valuetypewrapper.cpp @@ -395,7 +395,7 @@ v8::Handle QV8ValueTypeWrapper::Setter(v8::Local property QString url = r->engine->toString(frame->GetScriptName()); newBinding = new QQmlBinding(&function, reference->object, context, - url, lineNumber, columnNumber); + url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); newBinding->setTarget(reference->object, cacheData, context); newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QQmlBinding::RequiresThisObject); diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index dcdc8959d2..cafcf29a80 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -191,7 +191,9 @@ void tst_qmlmin::qmlMinify() QFETCH(QString, file); QProcess qmlminify; - qmlminify.start(qmlminPath, QStringList() << QLatin1String("--verify-only") << file); + + // Restrict line width to 100 characters + qmlminify.start(qmlminPath, QStringList() << QLatin1String("--verify-only") << QLatin1String("-w100") << file); qmlminify.waitForFinished(); QCOMPARE(qmlminify.error(), QProcess::UnknownError); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 963bec91bf..196587160b 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3918,70 +3918,70 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("malformed file name") << testFileUrl("jsimportfail/malformedFile.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedFile.js").toString() + QLatin1String(":0:1: Imported file must be a script")) + << (QStringList() << testFileUrl("jsimportfail/malformedFile.js").toString() + QLatin1String(":1:9: Imported file must be a script")) << QStringList() << QVariantList(); QTest::newRow("missing file qualifier") << testFileUrl("jsimportfail/missingFileQualifier.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/missingFileQualifier.js").toString() + QLatin1String(":0:1: File import requires a qualifier")) + << (QStringList() << testFileUrl("jsimportfail/missingFileQualifier.js").toString() + QLatin1String(":1:1: File import requires a qualifier")) << QStringList() << QVariantList(); QTest::newRow("malformed file qualifier") << testFileUrl("jsimportfail/malformedFileQualifier.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.js").toString() + QLatin1String(":0:1: File import requires a qualifier")) + << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.js").toString() + QLatin1String(":1:20: File import requires a qualifier")) << QStringList() << QVariantList(); QTest::newRow("malformed module qualifier 2") << testFileUrl("jsimportfail/malformedFileQualifier.2.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.2.js").toString() + QLatin1String(":0:1: Invalid import qualifier")) + << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier")) << QStringList() << QVariantList(); QTest::newRow("malformed module uri") << testFileUrl("jsimportfail/malformedModule.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedModule.js").toString() + QLatin1String(":0:1: Invalid module URI")) + << (QStringList() << testFileUrl("jsimportfail/malformedModule.js").toString() + QLatin1String(":1:17: Invalid module URI")) << QStringList() << QVariantList(); QTest::newRow("missing module version") << testFileUrl("jsimportfail/missingModuleVersion.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/missingModuleVersion.js").toString() + QLatin1String(":0:1: Module import requires a version")) + << (QStringList() << testFileUrl("jsimportfail/missingModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version")) << QStringList() << QVariantList(); QTest::newRow("malformed module version") << testFileUrl("jsimportfail/malformedModuleVersion.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedModuleVersion.js").toString() + QLatin1String(":0:1: Module import requires a version")) + << (QStringList() << testFileUrl("jsimportfail/malformedModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version")) << QStringList() << QVariantList(); QTest::newRow("missing module qualifier") << testFileUrl("jsimportfail/missingModuleQualifier.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/missingModuleQualifier.js").toString() + QLatin1String(":0:1: Module import requires a qualifier")) + << (QStringList() << testFileUrl("jsimportfail/missingModuleQualifier.js").toString() + QLatin1String(":1:1: Module import requires a qualifier")) << QStringList() << QVariantList(); QTest::newRow("malformed module qualifier") << testFileUrl("jsimportfail/malformedModuleQualifier.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.js").toString() + QLatin1String(":0:1: Module import requires a qualifier")) + << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.js").toString() + QLatin1String(":1:21: Module import requires a qualifier")) << QStringList() << QVariantList(); QTest::newRow("malformed module qualifier 2") << testFileUrl("jsimportfail/malformedModuleQualifier.2.qml") << QString() - << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.2.js").toString() + QLatin1String(":0:1: Invalid import qualifier")) + << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier")) << QStringList() << QVariantList(); } diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp index 8baa131b9a..66c08186bc 100644 --- a/tools/qmlmin/main.cpp +++ b/tools/qmlmin/main.cpp @@ -200,19 +200,22 @@ class Minify: public QmlminLexer QList _tokens; QList _tokenStrings; QString _minifiedCode; + int _maxWidth; + int _width; public: - Minify(); + Minify(int maxWidth); QString minifiedCode() const; protected: + void append(const QString &s); bool parse(int startToken); void escape(const QChar &ch, QString *out); }; -Minify::Minify() - : _stateStack(128) +Minify::Minify(int maxWidth) + : _stateStack(128), _maxWidth(maxWidth), _width(0) { } @@ -221,6 +224,24 @@ QString Minify::minifiedCode() const return _minifiedCode; } +void Minify::append(const QString &s) +{ + if (!s.isEmpty()) { + if (_maxWidth) { + // Prefer not to exceed the maximum chars per line (but don't break up segments) + int segmentLength = s.count(); + if (_width && ((_width + segmentLength) > _maxWidth)) { + _minifiedCode.append(QLatin1Char('\n')); + _width = 0; + } + + _width += segmentLength; + } + + _minifiedCode.append(s); + } +} + void Minify::escape(const QChar &ch, QString *out) { out->append(QLatin1String("\\u")); @@ -241,6 +262,7 @@ bool Minify::parse(int startToken) int yytoken = -1; int yytos = -1; QString yytokentext; + QString assembled; _minifiedCode.clear(); _tokens.append(startToken); @@ -250,7 +272,7 @@ bool Minify::parse(int startToken) // parse optional pragma directive if (scanDirectives(this)) { // append the scanned directives to the minifier code. - _minifiedCode += directives(); + append(directives()); _tokens.append(tokenKind()); _tokenStrings.append(tokenText()); @@ -281,33 +303,40 @@ bool Minify::parse(int startToken) if (yyaction > 0) { if (yyaction == ACCEPT_STATE) { --yytos; + if (!assembled.isEmpty()) + append(assembled); return true; } - const QChar lastChar = _minifiedCode.isEmpty() ? QChar() : _minifiedCode.at(_minifiedCode.length() - 1); + const QChar lastChar = assembled.isEmpty() ? (_minifiedCode.isEmpty() ? QChar() + : _minifiedCode.at(_minifiedCode.length() - 1)) + : assembled.at(assembled.length() - 1); if (yytoken == T_SEMICOLON) { - _minifiedCode += QLatin1Char(';'); + assembled += QLatin1Char(';'); + + append(assembled); + assembled.clear(); } else if (yytoken == T_PLUS || yytoken == T_MINUS || yytoken == T_PLUS_PLUS || yytoken == T_MINUS_MINUS) { if (lastChar == QLatin1Char(spell[yytoken][0])) { // don't merge unary signs, additive expressions and postfix/prefix increments. - _minifiedCode += QLatin1Char(' '); + assembled += QLatin1Char(' '); } - _minifiedCode += QLatin1String(spell[yytoken]); + assembled += QLatin1String(spell[yytoken]); } else if (yytoken == T_NUMERIC_LITERAL) { if (isIdentChar(lastChar)) - _minifiedCode += QLatin1Char(' '); + assembled += QLatin1Char(' '); if (yytokentext.startsWith('.')) - _minifiedCode += QLatin1Char('0'); + assembled += QLatin1Char('0'); - _minifiedCode += yytokentext; + assembled += yytokentext; - if (_minifiedCode.endsWith(QLatin1Char('.'))) - _minifiedCode += QLatin1Char('0'); + if (assembled.endsWith(QLatin1Char('.'))) + assembled += QLatin1Char('0'); } else if (yytoken == T_IDENTIFIER) { QString identifier = yytokentext; @@ -321,29 +350,29 @@ bool Minify::parse(int startToken) } if (isIdentChar(lastChar)) - _minifiedCode += QLatin1Char(' '); + assembled += QLatin1Char(' '); foreach (const QChar &ch, identifier) { if (isIdentChar(ch)) - _minifiedCode += ch; + assembled += ch; else { - escape(ch, &_minifiedCode); + escape(ch, &assembled); } } } else if (yytoken == T_STRING_LITERAL || yytoken == T_MULTILINE_STRING_LITERAL) { - _minifiedCode += QLatin1Char('"'); - _minifiedCode += quote(yytokentext); - _minifiedCode += QLatin1Char('"'); + assembled += QLatin1Char('"'); + assembled += quote(yytokentext); + assembled += QLatin1Char('"'); } else { if (isIdentChar(lastChar)) { if (! yytokentext.isEmpty()) { const QChar ch = yytokentext.at(0); if (isIdentChar(ch)) - _minifiedCode += QLatin1Char(' '); + assembled += QLatin1Char(' '); } } - _minifiedCode += yytokentext; + assembled += yytokentext; } yytoken = -1; } else if (yyaction < 0) { @@ -356,7 +385,7 @@ bool Minify::parse(int startToken) if (! scanRestOfRegExp(ruleno, &restOfRegExp)) break; // break the loop, it wil report a syntax error - _minifiedCode += restOfRegExp; + assembled += restOfRegExp; } yyaction = nt_action(_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT); } @@ -503,6 +532,7 @@ static void usage(bool showHelp = false) << " The options are:" << std::endl << " -o write output to file rather than stdout" << std::endl << " -v --verify-only just run the verifier, no output" << std::endl + << " -w restrict line characters to width" << std::endl << " -h display this output" << std::endl; } } @@ -517,6 +547,9 @@ int runQmlmin(int argc, char *argv[]) QString outputFile; bool verifyOnly = false; + // By default ensure the output character width is less than 16-bits (pass 0 to disable) + int width = USHRT_MAX; + int index = 1; while (index < args.size()) { const QString arg = args.at(index++); @@ -542,6 +575,29 @@ int runQmlmin(int argc, char *argv[]) std::cerr << "qmlmin: argument to '-o' is missing" << std::endl; return EXIT_FAILURE; } + } else if (arg == QLatin1String("-w")) { + if (next.isEmpty()) { + std::cerr << "qmlmin: argument to '-w' is missing" << std::endl; + return EXIT_FAILURE; + } else { + bool ok; + width = next.toInt(&ok); + + if (!ok) { + std::cerr << "qmlmin: argument to '-w' is invalid" << std::endl; + return EXIT_FAILURE; + } + + ++index; // consume the next argument + } + } else if (arg.startsWith(QLatin1String("-w"))) { + bool ok; + width = arg.mid(2).toInt(&ok); + + if (!ok) { + std::cerr << "qmlmin: argument to '-w' is invalid" << std::endl; + return EXIT_FAILURE; + } } else { const bool isInvalidOpt = arg.startsWith(QLatin1Char('-')); if (! isInvalidOpt && fileName.isEmpty()) @@ -571,7 +627,7 @@ int runQmlmin(int argc, char *argv[]) const QString code = QString::fromUtf8(file.readAll()); // QML files are UTF-8 encoded. file.close(); - QQmlJS::Minify minify; + QQmlJS::Minify minify(width); if (! minify(fileName, code)) { std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << "' (not a valid QML/JS file)" << std::endl; return EXIT_FAILURE; @@ -580,7 +636,7 @@ int runQmlmin(int argc, char *argv[]) // // verify the output // - QQmlJS::Minify secondMinify; + QQmlJS::Minify secondMinify(width); if (! secondMinify(fileName, minify.minifiedCode()) || secondMinify.minifiedCode() != minify.minifiedCode()) { std::cerr << "qmlmin: cannot minify '" << qPrintable(fileName) << "'" << std::endl; return EXIT_FAILURE; -- cgit v1.2.3