aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Burchell <robin.burchell@crimson.no>2017-01-28 13:48:06 +0100
committerRobin Burchell <robin.burchell@crimson.no>2017-02-02 15:49:13 +0000
commitb63393c7aac7c337672b87a914cb059f60091584 (patch)
tree4a76fa63adf744945f047f6394498a54c8186dc8
parent00b237a65825f26970eb8a14a5faa6af5a943e87 (diff)
Codegen: Disallow const declaration without an initializer expression
This seems to match up with the spec behavior. 13.3.1.1 (Static Semantics: Early Errors) says: It is a Syntax Error if Initializer is not present and IsConstantDeclaration of the LexicalDeclaration containing this production is true. In addition, we also allow "const" to be used in JS mode too. We don't yet fully support the semantics, but as it's there, why not let it work. [ChangeLog][QtQml] "const" variable declarations are now available in JS as well as QML mode. [ChangeLog][QtQml] "const" variable declarations now require an initializer, bringing them closer to the required spec behavior. Task-number: QTBUG-58493 Change-Id: Ife5d5979b3e7a5d7340bf04f43605f847ee25ee2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/parser/qqmljskeywords_p.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp57
3 files changed, 62 insertions, 1 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 7d3ad38f97..b5b70dbf45 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -216,6 +216,10 @@ bool Codegen::ScanFunctions::visit(VariableDeclaration *ast)
checkName(ast->name, ast->identifierToken);
if (ast->name == QLatin1String("arguments"))
_env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+ if (ast->readOnly && !ast->expression) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
+ return false;
+ }
_env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration);
return true;
}
diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h
index 84ebe5f210..a31c188efc 100644
--- a/src/qml/parser/qqmljskeywords_p.h
+++ b/src/qml/parser/qqmljskeywords_p.h
@@ -278,7 +278,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 's') {
if (s[4].unicode() == 't') {
- return qmlMode ? int(Lexer::T_CONST) : int(Lexer::T_RESERVED_WORD);
+ return int(Lexer::T_CONST);
}
}
}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 89dac33671..1f0248c258 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -333,6 +334,8 @@ private slots:
void stringify_qtbug_50592();
void instanceof_data();
void instanceof();
+ void constkw_data();
+ void constkw();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8183,6 +8186,60 @@ void tst_qqmlecmascript::instanceof()
}
}
+void tst_qqmlecmascript::constkw_data()
+{
+ QTest::addColumn<QString>("sourceCode");
+ QTest::addColumn<bool>("exceptionExpected");
+ QTest::addColumn<QVariant>("expectedValue");
+
+ QTest::newRow("simpleconst")
+ << "const v = 5\n"
+ "v\n"
+ << false
+ << QVariant(5);
+ QTest::newRow("twoconst")
+ << "const v = 5, i = 10\n"
+ "v + i\n"
+ << false
+ << QVariant(15);
+ QTest::newRow("constandvar")
+ << "const v = 5\n"
+ "var i = 20\n"
+ "v + i\n"
+ << false
+ << QVariant(25);
+
+ // error cases
+ QTest::newRow("const-no-initializer")
+ << "const v\n"
+ << true
+ << QVariant("SyntaxError: Missing initializer in const declaration");
+ QTest::newRow("const-no-initializer-comma")
+ << "const v = 1, i\n"
+ << true
+ << QVariant("SyntaxError: Missing initializer in const declaration");
+}
+
+void tst_qqmlecmascript::constkw()
+{
+ QFETCH(QString, sourceCode);
+ QFETCH(bool, exceptionExpected);
+ QFETCH(QVariant, expectedValue);
+
+ QJSEngine engine;
+ QJSValue ret = engine.evaluate(sourceCode);
+
+ if (!exceptionExpected) {
+ QVERIFY2(!ret.isError(), qPrintable(ret.toString()));
+ QCOMPARE(ret.toVariant(), expectedValue);
+ } else {
+ QVERIFY2(ret.isError(), qPrintable(ret.toString()));
+ QCOMPARE(ret.toString(), expectedValue.toString());
+ }
+}
+
+
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"