diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-05-21 15:10:45 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-05-21 18:03:47 +0200 |
commit | 3e716029ae61bf4c7bb33643ac331156e70e34f1 (patch) | |
tree | 2a2692dbaf49d87518c4b0da30078e177e8dd5c3 | |
parent | 9e919489c4e6b0c110281fda139fff84c1c71995 (diff) |
Don't add local for anonymous function's "name"
Instead, populate their "name" property directly from the surrounding
object pattern if applicable, without adding locals. This fixes some
ecmascript tests where functions were assigned to the key "eval" in an
object. The JS engine then rejected that because you shouldn't use eval
in strict mode. That should be close enough to test for regressions.
Fixes: QTBUG-75880
Change-Id: Iacc45a3f7b0eb90cddc6ecf6d2bada616d2cf355
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 19 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 4 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 2 |
4 files changed, 18 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 3fdba08f20..d2d913408a 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1061,6 +1061,7 @@ bool Codegen::visit(Expression *ast) TailCallBlocker blockTailCalls(this); statement(ast->left); blockTailCalls.unblock(); + clearExprResultName(); // The name only holds for the left part accept(ast->right); return false; } @@ -2523,7 +2524,7 @@ bool Codegen::visit(ObjectPattern *ast) { RegisterScope innerScope(this); - Reference value = expression(p->initializer); + Reference value = expression(p->initializer, name); if (hasError) return false; value.loadInAccumulator(); @@ -2965,7 +2966,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, // already defined return leaveContext(); - _context->name = name; + _context->name = name.isEmpty() ? currentExpr().result().name : name; _module->functions.append(_context); _context->functionIndex = _module->functions.count() - 1; diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index ad86483132..958dd16816 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -196,8 +196,9 @@ public: codegen = cg; } - Reference() : + Reference(const QString &name = QString()) : constant(0), + name(name), isArgOrEval(false), isReadonly(false), isReferenceToConst(false), @@ -414,6 +415,11 @@ protected: bool _trueBlockFollowsCondition = false; public: + explicit Result(const QString &name) + : _result(name) + , _requested(ex) + {} + explicit Result(const Reference &lrvalue) : _result(lrvalue) , _requested(ex) @@ -472,6 +478,10 @@ protected: void setResult(Reference &&result) { _result = std::move(result); } + + void clearResultName() { + _result.name.clear(); + } }; void enterContext(AST::Node *node); @@ -519,12 +529,12 @@ protected: const BytecodeGenerator::Label *iffalse, bool trueBlockFollowsCondition); - inline Reference expression(AST::ExpressionNode *ast) + inline Reference expression(AST::ExpressionNode *ast, const QString &name = QString()) { if (!ast || hasError) return Reference(); - pushExpr(); + pushExpr(name); ast->accept(this); return popResult(); } @@ -712,6 +722,7 @@ protected: inline void setExprResult(const Reference &result) { m_expressions.back().setResult(result); } inline void setExprResult(Reference &&result) { m_expressions.back().setResult(std::move(result)); } inline Reference exprResult() const { return m_expressions.back().result(); } + inline void clearExprResultName() { m_expressions.back().clearResultName(); } inline bool exprAccept(Format f) { return m_expressions.back().accept(f); } @@ -719,7 +730,7 @@ protected: inline void pushExpr(Result &&expr) { m_expressions.push_back(std::move(expr)); } inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); } - inline void pushExpr() { m_expressions.emplace_back(); } + inline void pushExpr(const QString &name = QString()) { m_expressions.emplace_back(name); } inline Result popExpr() { diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 8ae51a795f..27f23a6fa7 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -1773,10 +1773,6 @@ PropertyDefinition: PropertyName T_COLON AssignmentExpression_In; /. case $rule_number: { AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Expression); - if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) { - if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName)) - f->name = driver->newStringRef(sym(1).PropertyName->asString()); - } if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) { if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName)) c->name = driver->newStringRef(sym(1).PropertyName->asString()); diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index cf7bf3d8ba..a5246c8792 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -714,8 +714,6 @@ language/statements/generators/yield-identifier-non-strict.js sloppyFails language/statements/let/block-local-closure-set-before-initialization.js fails language/statements/let/function-local-closure-set-before-initialization.js fails language/statements/let/global-closure-set-before-initialization.js fails -language/statements/throw/S12.13_A2_T6.js strictFails -language/statements/try/S12.14_A18_T6.js strictFails language/statements/try/scope-catch-block-lex-open.js fails language/statements/variable/binding-resolution.js sloppyFails language/statements/with/unscopables-inc-dec.js sloppyFails |