diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-08-11 15:47:13 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-08-17 16:14:53 +0200 |
commit | 8cd7aabfb24b391143b3c358f49fb6a28765d5f3 (patch) | |
tree | bb1252651849f8cff7b444ebf82ebfb81a86ae5d /src/qml/compiler/qv4compiler.cpp | |
parent | d0dc91158d0b44d9e1b73c3b0dacdd6699741ad7 (diff) |
When binding signals, run the outer function to get the nested one
The outer function may perform important tasks like setting up a call
context with a "this" member for the nested function. In particular,
arrow functions retain their original "this" member, no matter where
they are executed later. We can detect this condition while generating
the compilation unit. If the outer function is not a simple wrapper that
only returns the inner function, execute it when binding a signal.
Fixes: QTBUG-95659
Pick-to: 6.2
Change-Id: I7dfef2c78378588e6bfc4bedde7889c7f2ce03ef
Reviewed-by: Yuya Nishihara <yuya.nishihara@qt.io>
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compiler.cpp')
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 5511ed304a..02e2470850 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -432,9 +432,21 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->flags |= CompiledData::Function::IsArrowFunction; if (irFunction->isGenerator) function->flags |= CompiledData::Function::IsGenerator; - function->nestedFunctionIndex = - irFunction->returnsClosure ? quint32(module->functions.indexOf(irFunction->nestedContexts.first())) - : std::numeric_limits<uint32_t>::max(); + if (irFunction->returnsClosure) + function->flags |= CompiledData::Function::IsClosureWrapper; + + if (!irFunction->returnsClosure + || irFunction->innerFunctionAccessesThis + || irFunction->innerFunctionAccessesNewTarget) { + // If the inner function does things with this and new.target we need to do some work in + // the outer function. Then we shouldn't directly access the nested function. + function->nestedFunctionIndex = std::numeric_limits<uint32_t>::max(); + } else { + // Otherwise we can directly use the nested function. + function->nestedFunctionIndex + = quint32(module->functions.indexOf(irFunction->nestedContexts.first())); + } + function->length = irFunction->formals ? irFunction->formals->length() : 0; function->nFormals = irFunction->arguments.size(); function->formalsOffset = currentOffset; |