diff options
-rw-r--r-- | src/declarative/qml/parser/qdeclarativejslexer.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/parser/qdeclarativejslexer_p.h | 7 | ||||
-rw-r--r-- | tests/auto/declarative/qmlmin/tst_qmlmin.cpp | 1 | ||||
-rw-r--r-- | tools/qmlmin/main.cpp | 47 |
4 files changed, 45 insertions, 15 deletions
diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 9b9af3868d..5e008d27f1 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -113,6 +113,11 @@ Lexer::Lexer(Engine *engine) engine->setLexer(this); } +bool Lexer::qmlMode() const +{ + return _qmlMode; +} + QString Lexer::code() const { return _code; diff --git a/src/declarative/qml/parser/qdeclarativejslexer_p.h b/src/declarative/qml/parser/qdeclarativejslexer_p.h index a0f02afa60..31eeff8181 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer_p.h +++ b/src/declarative/qml/parser/qdeclarativejslexer_p.h @@ -145,6 +145,8 @@ public: public: Lexer(Engine *engine); + bool qmlMode() const; + QString code() const; void setCode(const QString &code, int lineno, bool qmlMode = true); @@ -183,12 +185,13 @@ public: BalancedParentheses }; +protected: + int classify(const QChar *s, int n, bool qmlMode); + private: inline void scanChar(); int scanToken(); - int classify(const QChar *s, int n, bool qmlMode); - bool isLineTerminator() const; static bool isIdentLetter(QChar c); static bool isDecimalDigit(ushort c); diff --git a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp index d6146d121e..2726a637ec 100644 --- a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp @@ -107,6 +107,7 @@ void tst_qmlmin::initTestCase() invalidFiles << "tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js"; invalidFiles << "tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js"; invalidFiles << "tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js"; + invalidFiles << "tests/auto/declarative/parserstress/tests/ecma_3/Unicode/regress-352044-02-n.js"; } QStringList tst_qmlmin::findFiles(const QDir &d) diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp index ebfc5851dd..b1aeab6168 100644 --- a/tools/qmlmin/main.cpp +++ b/tools/qmlmin/main.cpp @@ -182,6 +182,13 @@ protected: *restOfRegExp += QLatin1Char('i'); if (flags & Multiline) *restOfRegExp += QLatin1Char('m'); + + if (regExpFlags() == 0) { + // Add an extra space after the regexp literal delimiter (aka '/'). + // This will avoid possible problems when pasting tokens like `instanceof' + // after the regexp literal. + *restOfRegExp += QLatin1Char(' '); + } return true; } }; @@ -201,6 +208,7 @@ public: protected: bool parse(int startToken); + void escape(const QChar &ch, QString *out); }; Minify::Minify() @@ -213,6 +221,20 @@ QString Minify::minifiedCode() const return _minifiedCode; } +void Minify::escape(const QChar &ch, QString *out) +{ + out->append(QLatin1String("\\u")); + const QString hx = QString::number(ch.unicode(), 16); + switch (hx.length()) { + case 1: out->append(QLatin1String("000")); break; + case 2: out->append(QLatin1String("00")); break; + case 3: out->append(QLatin1String("0")); break; + case 4: break; + default: Q_ASSERT(!"unreachable"); + } + out->append(hx); +} + bool Minify::parse(int startToken) { int yyaction = 0; @@ -288,25 +310,24 @@ bool Minify::parse(int startToken) _minifiedCode += QLatin1Char('0'); } else if (yytoken == T_IDENTIFIER) { + QString identifier = yytokentext; + + if (classify(identifier.constData(), identifier.size(), qmlMode()) != T_IDENTIFIER) { + // the unescaped identifier is a keyword. In this case just replace + // the last character of the identifier with it escape sequence. + const QChar ch = identifier.at(identifier.length() - 1); + identifier.chop(1); + escape(ch, &identifier); + } + if (isIdentChar(lastChar)) _minifiedCode += QLatin1Char(' '); - foreach (const QChar &ch, yytokentext) { + foreach (const QChar &ch, identifier) { if (isIdentChar(ch)) _minifiedCode += ch; else { - _minifiedCode += QLatin1String("\\u"); - const QString hx = QString::number(ch.unicode(), 16); - switch (hx.length()) { - case 1: _minifiedCode += QLatin1String("000"); break; - case 2: _minifiedCode += QLatin1String("00"); break; - case 3: _minifiedCode += QLatin1String("0"); break; - case 4: break; - default: - std::cerr << "qmlmin: invalid unicode sequence" << std::endl; - return false; - } - _minifiedCode += hx; + escape(ch, &_minifiedCode); } } |