diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 26 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 4 |
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 |