aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-08-03 14:25:26 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-09-01 09:45:56 +0200
commit6fa4d45b0d321d5d2c935ed000467b167d0c1b27 (patch)
treefef43524cf06c307cb0d5d5b9cba1254081f5a89
parentff8893d28d5d2e8470d04bf49af895f27bdc0343 (diff)
Parser: Preserve keywordiness of "static" across nested classes
"static" is a keyword in the context of JS classes, no matter how deeply nested. Therefore, keep track of the nesting level. Switching the keywordiness of "static" off during method definition parsing makes no sense as the standard doesn't mention such a thing. Method bodies are strict code where you cannot use "static" as identifier. Methods and properties can be called "static" no matter if static is a keyword or not. Fixes: QTBUG-96631 Change-Id: Ia09e52fe2ae72721fe1c8a9b95899a31095db988 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit b50d01891b1adba15c4cfc47ad078d227aa1f491)
-rw-r--r--src/qml/parser/qqmljs.g12
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp17
2 files changed, 23 insertions, 6 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 93d110c19f..8c694af082 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -368,6 +368,7 @@ protected:
SavedToken *last_token = nullptr;
int functionNestingLevel = 0;
+ int classNestingLevel = 0;
enum CoverExpressionType {
CE_Invalid,
@@ -4278,16 +4279,16 @@ ClassDeclaration_Default: ClassDeclaration;
ClassLBrace: T_LBRACE;
/.
case $rule_number: {
- lexer->setStaticIsKeyword(true);
+ if (++classNestingLevel == 1)
+ lexer->setStaticIsKeyword(true);
} break;
./
ClassRBrace: T_RBRACE;
-/. case $rule_number: ./
-ClassStaticQualifier: T_STATIC;
/.
case $rule_number: {
- lexer->setStaticIsKeyword(false);
+ if (--classNestingLevel == 0)
+ lexer->setStaticIsKeyword(false);
} break;
./
@@ -4342,10 +4343,9 @@ ClassElement: MethodDefinition;
} break;
./
-ClassElement: ClassStaticQualifier MethodDefinition;
+ClassElement: T_STATIC MethodDefinition;
/.
case $rule_number: {
- lexer->setStaticIsKeyword(true);
AST::ClassElementList *node = new (pool) AST::ClassElementList(sym(2).PatternProperty, true);
sym(1).Node = node;
} break;
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 0c3a8d1703..71e3830fd2 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -260,6 +260,7 @@ private slots:
void urlObject();
void thisInConstructor();
void forOfAndGc();
+ void staticInNestedClasses();
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
@@ -5571,6 +5572,22 @@ void tst_QJSEngine::forOfAndGc()
QTRY_VERIFY(o->property("count").toInt() > 32768);
}
+void tst_QJSEngine::staticInNestedClasses()
+{
+ QJSEngine engine;
+ const QString program = uR"(
+ class Tester {
+ constructor() {
+ new (class {})();
+ }
+ static get test() { return "a" }
+ }
+ Tester.test
+ )"_s;
+
+ QCOMPARE(engine.evaluate(program).toString(), u"a"_s);
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"