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>
This commit is contained in:
Robin Burchell 2017-01-28 13:48:06 +01:00
parent 00b237a658
commit b63393c7aa
3 changed files with 62 additions and 1 deletions

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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"