aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen.cpp6
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp7
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp26
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations4
5 files changed, 33 insertions, 11 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 786753ab80..d61f79f0fc 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2717,6 +2717,12 @@ bool Codegen::visit(ThisExpression *)
if (hasError)
return false;
+ if (_context->isArrowFunction) {
+ Reference r = referenceForName(QStringLiteral("this"), false);
+ r.isReadonly = true;
+ _expr.setResult(r);
+ return false;
+ }
_expr.setResult(Reference::fromThis(this));
return false;
}
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 4ee6d2c179..1b4c084ab4 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -241,6 +241,13 @@ void Context::emitBlockHeader(Codegen *codegen)
Instruction::ConvertThisToObject convert;
bytecodeGenerator->addInstruction(convert);
}
+ if (innerFunctionAccessesThis) {
+ Instruction::LoadReg load;
+ load.reg = CallData::This;
+ bytecodeGenerator->addInstruction(load);
+ Codegen::Reference r = codegen->referenceForName(QStringLiteral("this"), true);
+ r.storeConsumeAccumulator();
+ }
if (contextType == ContextType::Global || (contextType == ContextType::Eval && !isStrict)) {
// variables in global code are properties of the global context object, not locals as with other functions.
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 3df0aa6b3a..8713b0a188 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -201,6 +201,7 @@ struct Context {
bool isArrowFunction = false;
bool isGenerator = false;
bool usesThis = false;
+ bool innerFunctionAccessesThis = false;
bool hasTry = false;
bool returnsClosure = false;
mutable bool argumentsCanEscape = false;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index e0a745ebb1..dafb1c360d 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -742,6 +742,8 @@ void ScanFunctions::calcEscapingVariables()
}
Q_ASSERT(c);
c->hasDirectEval = true;
+ if (!c->isStrict)
+ c->innerFunctionAccessesThis = true;
}
Context *c = inner;
while (c) {
@@ -751,17 +753,26 @@ void ScanFunctions::calcEscapingVariables()
}
if (inner->usesThis) {
inner->usesThis = false;
- if (!inner->isStrict) {
- Context *c = inner;
- while (c->contextType == ContextType::Block) {
- c = c->parent;
- }
- Q_ASSERT(c);
- c->usesThis = true;
+ bool innerFunctionAccessesThis = false;
+ Context *c = inner;
+ while (c->contextType == ContextType::Block || c->isArrowFunction) {
+ innerFunctionAccessesThis |= c->isArrowFunction;
+ c = c->parent;
}
+ Q_ASSERT(c);
+ if (!inner->isStrict)
+ c->usesThis = true;
+ c->innerFunctionAccessesThis |= innerFunctionAccessesThis;
}
}
for (Context *c : qAsConst(m->contextMap)) {
+ if (c->innerFunctionAccessesThis) {
+ // add an escaping 'this' variable
+ c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
+ c->requiresExecutionContext = true;
+ auto m = c->members.find(QStringLiteral("this"));
+ m->canEscape = true;
+ }
if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
c->allVarsEscape = false;
if (c->contextType == ContextType::Global || (!c->isStrict && c->contextType == ContextType::Eval) || m->debugMode)
@@ -801,6 +812,7 @@ void ScanFunctions::calcEscapingVariables()
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext << "isStrict" << c->isStrict;
+ qDebug() << " isArrowFunction" << c->isArrowFunction << "innerFunctionAccessesThis" << c->innerFunctionAccessesThis;
qDebug() << " parent:" << c->parent;
if (c->argumentsCanEscape)
qDebug() << " Arguments escape";
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 7b7ee40196..fe2e9835e1 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -445,7 +445,6 @@ built-ins/RegExp/unicode_restricted_quantifiable_assertion.js fails
built-ins/RegExp/u180e.js fails
built-ins/Set/proto-from-ctor-realm.js fails
built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js fails
-built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js fails
built-ins/SharedArrayBuffer/data-allocation-after-object-creation.js fails
built-ins/SharedArrayBuffer/proto-from-ctor-realm.js fails
built-ins/SharedArrayBuffer/prototype-from-newtarget.js fails
@@ -616,14 +615,12 @@ language/eval-code/indirect/var-env-global-lex-non-strict.js fails
language/eval-code/indirect/var-env-var-init-global-exstng.js strictFails
language/eval-code/indirect/var-env-var-init-global-new.js strictFails
language/eval-code/indirect/var-env-var-non-strict.js strictFails
-language/expressions/arrow-function/cannot-override-this-with-thisArg.js fails
language/expressions/arrow-function/dflt-params-ref-later.js fails
language/expressions/arrow-function/dflt-params-ref-self.js fails
language/expressions/arrow-function/lexical-new.target-closure-returned.js fails
language/expressions/arrow-function/lexical-new.target.js fails
language/expressions/arrow-function/lexical-super-call-from-within-constructor.js fails
language/expressions/arrow-function/lexical-supercall-from-immediately-invoked-arrow.js fails
-language/expressions/arrow-function/lexical-this.js fails
language/expressions/arrow-function/scope-body-lex-distinct.js sloppyFails
language/expressions/arrow-function/scope-param-elem-var-close.js sloppyFails
language/expressions/arrow-function/scope-param-elem-var-open.js sloppyFails
@@ -1002,7 +999,6 @@ language/statements/class/scope-static-setter-paramsbody-var-open.js fails
language/statements/class/subclass/bound-function.js fails
language/statements/class/subclass/builtin-objects/Promise/regular-subclassing.js fails
language/statements/class/subclass/builtin-objects/Promise/super-must-be-called.js fails
-language/statements/class/subclass/class-definition-null-proto-this.js fails
language/statements/class/subclass/default-constructor-spread-override.js fails
language/statements/do-while/tco-body.js strictFails
language/statements/for-in/head-lhs-let.js sloppyFails