Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I0376b25557ba633e5b148c6e9c467d88fae1778f
This commit is contained in:
commit
a298b4dc5f
|
@ -39,13 +39,13 @@
|
|||
|
||||
\include examples-run.qdocinc
|
||||
|
||||
\section1 GridView and PathView
|
||||
\section1 Using GridView and PathView
|
||||
|
||||
\e GridView and \e PathView demonstrate usage of these types to display
|
||||
views.
|
||||
\snippet views/gridview/gridview-example.qml 0
|
||||
|
||||
\section1 Dynamic List
|
||||
\section1 Using Dynamic List
|
||||
|
||||
\e{Dynamic List} demonstrates animation of runtime additions and removals to
|
||||
a \l ListView.
|
||||
|
@ -66,12 +66,12 @@
|
|||
\snippet views/listview/expandingdelegates.qml 2
|
||||
\snippet views/listview/expandingdelegates.qml 3
|
||||
|
||||
\section1 Highlight
|
||||
\section1 Using Highlight
|
||||
|
||||
\e Highlight demonstrates adding a custom highlight to a ListView.
|
||||
\snippet views/listview/highlight.qml 0
|
||||
|
||||
\section1 Highlight Ranges
|
||||
\section1 Using Highlight Ranges
|
||||
|
||||
\e{Highlight Ranges} shows the three different highlight range modes of
|
||||
ListView.
|
||||
|
@ -79,13 +79,13 @@
|
|||
\snippet views/listview/highlightranges.qml 1
|
||||
\snippet views/listview/highlightranges.qml 2
|
||||
|
||||
\section1 Sections
|
||||
\section1 Using Sections
|
||||
|
||||
\e Sections demonstrates the various section headers and footers available
|
||||
to \l ListView.
|
||||
\snippet views/listview/sections.qml 0
|
||||
|
||||
\section1 Packages
|
||||
\section1 Using Packages
|
||||
|
||||
\e Packages use the \l [QML]{Package} type to transition delegates between
|
||||
two views.
|
||||
|
@ -100,13 +100,13 @@
|
|||
|
||||
\snippet views/package/view.qml 0
|
||||
|
||||
\section1 ObjectModel
|
||||
\section1 Using ObjectModel
|
||||
|
||||
\e ObjectModel uses an ObjectModel for the model instead of a \l ListModel.
|
||||
|
||||
\snippet views/objectmodel/objectmodel.qml 0
|
||||
|
||||
\section1 Display Margins
|
||||
\section1 Using Display Margins
|
||||
|
||||
\e{Display Margins} uses delegates to display items and implements a simple
|
||||
header and footer components.
|
||||
|
|
|
@ -1631,7 +1631,7 @@ Item {
|
|||
|
||||
TestCase {
|
||||
name: "ItemTests"
|
||||
when: area.pressed
|
||||
when: windowShown
|
||||
id: test1
|
||||
|
||||
function test_touch() {
|
||||
|
|
|
@ -1104,6 +1104,7 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size)
|
|||
QQuickImageParticle::QQuickImageParticle(QQuickItem* parent)
|
||||
: QQuickParticlePainter(parent)
|
||||
, m_color_variation(0.0)
|
||||
, m_outgoingNode(nullptr)
|
||||
, m_material(nullptr)
|
||||
, m_alphaVariation(0.0)
|
||||
, m_alpha(1.0)
|
||||
|
@ -1149,6 +1150,8 @@ void QQuickImageParticle::sceneGraphInvalidated()
|
|||
{
|
||||
m_nodes.clear();
|
||||
m_material = nullptr;
|
||||
delete m_outgoingNode;
|
||||
m_outgoingNode = nullptr;
|
||||
}
|
||||
|
||||
void QQuickImageParticle::setImage(const QUrl &image)
|
||||
|
@ -1931,8 +1934,11 @@ QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *node, UpdatePaintNodeData
|
|||
}
|
||||
|
||||
if (m_pleaseReset){
|
||||
if (node)
|
||||
delete node;
|
||||
// Cannot just destroy the node and then return null (in case image
|
||||
// loading is still in progress). Rather, keep track of the old node
|
||||
// until we have a new one.
|
||||
delete m_outgoingNode;
|
||||
m_outgoingNode = node;
|
||||
node = nullptr;
|
||||
|
||||
m_lastLevel = perfLevel;
|
||||
|
@ -1946,6 +1952,9 @@ QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *node, UpdatePaintNodeData
|
|||
|
||||
m_pleaseReset = false;
|
||||
m_startedImageLoading = 0;//Cancel a part-way build (may still have a pending load)
|
||||
} else if (!m_material) {
|
||||
delete node;
|
||||
node = nullptr;
|
||||
}
|
||||
|
||||
if (m_system && m_system->isRunning() && !m_system->isPaused()){
|
||||
|
@ -1959,6 +1968,11 @@ QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *node, UpdatePaintNodeData
|
|||
}
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
node = m_outgoingNode;
|
||||
m_outgoingNode = nullptr;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -390,6 +390,7 @@ private:
|
|||
QColor m_color;
|
||||
qreal m_color_variation;
|
||||
|
||||
QSGNode *m_outgoingNode;
|
||||
QHash<int, QSGGeometryNode *> m_nodes;
|
||||
QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
|
||||
QList<QPair<int, int> > m_startsIdx;//Same data, optimized for alternate retrieval
|
||||
|
|
|
@ -96,8 +96,9 @@ private:
|
|||
static void printDisassembledOutputWithCalls(QByteArray processedOutput,
|
||||
const QHash<const void*, const char*>& functions)
|
||||
{
|
||||
for (QHash<const void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
|
||||
it != end; ++it) {
|
||||
const auto symbols = Runtime::symbolTable();
|
||||
const QByteArray padding(" ; ");
|
||||
for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
|
||||
const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16);
|
||||
int idx = 0;
|
||||
while (idx >= 0) {
|
||||
|
@ -107,7 +108,9 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput,
|
|||
idx = processedOutput.indexOf('\n', idx);
|
||||
if (idx < 0)
|
||||
break;
|
||||
processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; ") + it.value());
|
||||
const char *functionName = it.value();
|
||||
processedOutput = processedOutput.insert(
|
||||
idx, padding + QByteArray(functionName ? functionName : symbols[it.key()]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,27 +305,29 @@ void JIT::PlatformAssemblerCommon::passPointerAsArg(void *ptr, int arg)
|
|||
storePtr(TrustedImmPtr(ptr), argStackAddress(arg));
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::callRuntime(const char *functionName, const void *funcPtr)
|
||||
void PlatformAssemblerCommon::callRuntime(const void *funcPtr, const char *functionName)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(remainingArgcForCall == 0);
|
||||
remainingArgcForCall = NoCall;
|
||||
#endif
|
||||
callRuntimeUnchecked(functionName, funcPtr);
|
||||
callRuntimeUnchecked(funcPtr, functionName);
|
||||
if (argcOnStackForCall > 0) {
|
||||
addPtr(TrustedImm32(argcOnStackForCall), StackPointerRegister);
|
||||
argcOnStackForCall = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::callRuntimeUnchecked(const char *functionName, const void *funcPtr)
|
||||
void PlatformAssemblerCommon::callRuntimeUnchecked(const void *funcPtr, const char *functionName)
|
||||
{
|
||||
Q_ASSERT(functionName || Runtime::symbolTable().contains(funcPtr));
|
||||
functions.insert(funcPtr, functionName);
|
||||
callAbsolute(funcPtr);
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::tailCallRuntime(const char *functionName, const void *funcPtr)
|
||||
void PlatformAssemblerCommon::tailCallRuntime(const void *funcPtr, const char *functionName)
|
||||
{
|
||||
Q_ASSERT(functionName || Runtime::symbolTable().contains(funcPtr));
|
||||
functions.insert(funcPtr, functionName);
|
||||
setTailCallArg(EngineRegister, 1);
|
||||
setTailCallArg(CppStackFrameRegister, 0);
|
||||
|
|
|
@ -706,9 +706,9 @@ public:
|
|||
void passCppFrameAsArg(int arg);
|
||||
void passInt32AsArg(int value, int arg);
|
||||
void passPointerAsArg(void *ptr, int arg);
|
||||
void callRuntime(const char *functionName, const void *funcPtr);
|
||||
void callRuntimeUnchecked(const char *functionName, const void *funcPtr);
|
||||
void tailCallRuntime(const char *functionName, const void *funcPtr);
|
||||
void callRuntime(const void *funcPtr, const char *functionName = nullptr);
|
||||
void callRuntimeUnchecked(const void *funcPtr, const char *functionName = nullptr);
|
||||
void tailCallRuntime(const void *funcPtr, const char *functionName = nullptr);
|
||||
void setTailCallArg(RegisterID src, int arg);
|
||||
Address jsAlloca(int slotCount);
|
||||
void storeInt32AsValue(int srcInt, Address destAddr);
|
||||
|
|
|
@ -61,7 +61,8 @@ namespace JIT {
|
|||
|
||||
#define ASM_GENERATE_RUNTIME_CALL(function, destination) \
|
||||
pasm()->GENERATE_RUNTIME_CALL(function, destination)
|
||||
#define callHelper(x) PlatformAssemblerCommon::callRuntimeUnchecked(#x, reinterpret_cast<void *>(&x))
|
||||
#define callHelper(x) \
|
||||
PlatformAssemblerCommon::callRuntimeUnchecked(reinterpret_cast<void *>(&x), #x)
|
||||
|
||||
const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer;
|
||||
|
||||
|
@ -83,10 +84,9 @@ public:
|
|||
: PlatformAssemblerCommon(constantTable)
|
||||
{}
|
||||
|
||||
void callRuntime(const char *functionName, const void *funcPtr,
|
||||
CallResultDestination dest)
|
||||
void callRuntime(const void *funcPtr, CallResultDestination dest)
|
||||
{
|
||||
PlatformAssemblerCommon::callRuntime(functionName, funcPtr);
|
||||
PlatformAssemblerCommon::callRuntime(funcPtr);
|
||||
if (dest == CallResultDestination::InAccumulator)
|
||||
saveReturnValueInAccumulator();
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ public:
|
|||
auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
|
||||
|
||||
move(AccumulatorRegister, registerForArg(0));
|
||||
callRuntimeUnchecked("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper));
|
||||
callHelper(toInt32Helper);
|
||||
saveReturnValueInAccumulator();
|
||||
|
||||
isInt.link(this);
|
||||
|
@ -383,10 +383,9 @@ public:
|
|||
: PlatformAssemblerCommon(constantTable)
|
||||
{}
|
||||
|
||||
void callRuntime(const char *functionName, const void *funcPtr,
|
||||
CallResultDestination dest)
|
||||
void callRuntime(const void *funcPtr, CallResultDestination dest)
|
||||
{
|
||||
PlatformAssemblerCommon::callRuntime(functionName, funcPtr);
|
||||
PlatformAssemblerCommon::callRuntime(funcPtr);
|
||||
if (dest == CallResultDestination::InAccumulator)
|
||||
saveReturnValueInAccumulator();
|
||||
}
|
||||
|
@ -491,7 +490,7 @@ public:
|
|||
move(AccumulatorRegisterValue, registerForArg(0));
|
||||
move(AccumulatorRegisterTag, registerForArg(1));
|
||||
}
|
||||
callRuntimeUnchecked("toNumberHelper", reinterpret_cast<void *>(&toNumberHelper));
|
||||
callHelper(toNumberHelper);
|
||||
saveReturnValueInAccumulator();
|
||||
if (ArgInRegCount < 2)
|
||||
addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
|
||||
|
@ -548,7 +547,7 @@ public:
|
|||
move(AccumulatorRegisterValue, registerForArg(0));
|
||||
move(AccumulatorRegisterTag, registerForArg(1));
|
||||
}
|
||||
callRuntimeUnchecked("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper));
|
||||
callHelper(toInt32Helper);
|
||||
saveReturnValueInAccumulator();
|
||||
if (ArgInRegCount < 2)
|
||||
addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
|
||||
|
@ -570,7 +569,7 @@ public:
|
|||
move(AccumulatorRegisterValue, registerForArg(0));
|
||||
move(AccumulatorRegisterTag, registerForArg(1));
|
||||
}
|
||||
callRuntimeUnchecked("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper));
|
||||
callHelper(toInt32Helper);
|
||||
saveReturnValueInAccumulator();
|
||||
if (ArgInRegCount < 2)
|
||||
addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
|
||||
|
@ -1267,7 +1266,7 @@ void BaselineAssembler::cmpeqInt(int lhs)
|
|||
else
|
||||
pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
|
||||
pasm()->pushAccumulatorAsArg(0);
|
||||
pasm()->callRuntimeUnchecked("Equal", (void*)Runtime::Equal::call);
|
||||
pasm()->callRuntimeUnchecked((void*)Runtime::Equal::call);
|
||||
pasm()->saveReturnValueInAccumulator();
|
||||
if (PlatformAssembler::ArgInRegCount < 2)
|
||||
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
|
||||
|
@ -1291,7 +1290,7 @@ void BaselineAssembler::cmpneInt(int lhs)
|
|||
else
|
||||
pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
|
||||
pasm()->pushAccumulatorAsArg(0);
|
||||
pasm()->callRuntimeUnchecked("NotEqual", (void*)Runtime::NotEqual::call);
|
||||
pasm()->callRuntimeUnchecked((void*)Runtime::NotEqual::call);
|
||||
pasm()->saveReturnValueInAccumulator();
|
||||
if (PlatformAssembler::ArgInRegCount < 2)
|
||||
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
|
||||
|
@ -1305,7 +1304,7 @@ void BaselineAssembler::cmpneInt(int lhs)
|
|||
done.link(pasm());
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmp(int cond, CmpFunc function, const char *functionName, int lhs)
|
||||
void BaselineAssembler::cmp(int cond, CmpFunc function, int lhs)
|
||||
{
|
||||
auto c = static_cast<PlatformAssembler::RelationalCondition>(cond);
|
||||
auto done = pasm()->binopBothIntPath(regAddr(lhs), [this, c](){
|
||||
|
@ -1321,7 +1320,7 @@ void BaselineAssembler::cmp(int cond, CmpFunc function, const char *functionName
|
|||
pasm()->passAccumulatorAsArg(1);
|
||||
pasm()->passJSSlotAsArg(lhs, 0);
|
||||
|
||||
callRuntime(functionName, reinterpret_cast<void*>(function), CallResultDestination::InAccumulator);
|
||||
callRuntime(reinterpret_cast<void*>(function), CallResultDestination::InAccumulator);
|
||||
checkException();
|
||||
|
||||
// done.
|
||||
|
@ -1331,50 +1330,42 @@ void BaselineAssembler::cmp(int cond, CmpFunc function, const char *functionName
|
|||
|
||||
void BaselineAssembler::cmpeq(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::Equal, &Runtime::CompareEqual::call,
|
||||
"CompareEqual", lhs);
|
||||
cmp(PlatformAssembler::Equal, &Runtime::CompareEqual::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmpne(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::NotEqual, &Runtime::CompareNotEqual::call,
|
||||
"CompareNotEqual", lhs);
|
||||
cmp(PlatformAssembler::NotEqual, &Runtime::CompareNotEqual::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmpgt(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::GreaterThan, &Runtime::CompareGreaterThan::call,
|
||||
"CompareGreaterThan", lhs);
|
||||
cmp(PlatformAssembler::GreaterThan, &Runtime::CompareGreaterThan::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmpge(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::CompareGreaterEqual::call,
|
||||
"CompareGreaterEqual", lhs);
|
||||
cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::CompareGreaterEqual::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmplt(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::LessThan, &Runtime::CompareLessThan::call,
|
||||
"CompareLessThan", lhs);
|
||||
cmp(PlatformAssembler::LessThan, &Runtime::CompareLessThan::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmple(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::LessThanOrEqual, &Runtime::CompareLessEqual::call,
|
||||
"CompareLessEqual", lhs);
|
||||
cmp(PlatformAssembler::LessThanOrEqual, &Runtime::CompareLessEqual::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmpStrictEqual(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::Equal, &Runtime::CompareStrictEqual::call,
|
||||
"RuntimeHelpers::strictEqual", lhs);
|
||||
cmp(PlatformAssembler::Equal, &Runtime::CompareStrictEqual::call, lhs);
|
||||
}
|
||||
|
||||
void BaselineAssembler::cmpStrictNotEqual(int lhs)
|
||||
{
|
||||
cmp(PlatformAssembler::NotEqual, &Runtime::CompareStrictNotEqual::call,
|
||||
"RuntimeHelpers::strictNotEqual", lhs);
|
||||
cmp(PlatformAssembler::NotEqual, &Runtime::CompareStrictNotEqual::call, lhs);
|
||||
}
|
||||
|
||||
int BaselineAssembler::jump(int offset)
|
||||
|
@ -1463,9 +1454,9 @@ void BaselineAssembler::passPointerAsArg(void *ptr, int arg)
|
|||
pasm()->passPointerAsArg(ptr, arg);
|
||||
}
|
||||
|
||||
void BaselineAssembler::callRuntime(const char *functionName, const void *funcPtr, CallResultDestination dest)
|
||||
void BaselineAssembler::callRuntime(const void *funcPtr, CallResultDestination dest)
|
||||
{
|
||||
pasm()->callRuntime(functionName, funcPtr, dest);
|
||||
pasm()->callRuntime(funcPtr, dest);
|
||||
}
|
||||
|
||||
void BaselineAssembler::saveAccumulatorInFrame()
|
||||
|
@ -1498,8 +1489,9 @@ void BaselineAssembler::jsTailCall(int func, int thisObject, int argc, int argv)
|
|||
pasm()->storeInt32AsValue(argv, Address(tos.base, argvOffset));
|
||||
pasm()->moveReg(regAddr(thisObject), Address(tos.base, thisOffset));
|
||||
pasm()->moveReg(regAddr(func), Address(tos.base, funcOffset));
|
||||
pasm()->tailCallRuntime("TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing",
|
||||
reinterpret_cast<void *>(TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing));
|
||||
pasm()->tailCallRuntime(
|
||||
reinterpret_cast<void *>(TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing),
|
||||
"TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing");
|
||||
}
|
||||
|
||||
void BaselineAssembler::checkException()
|
||||
|
|
|
@ -62,16 +62,11 @@ QT_BEGIN_NAMESPACE
|
|||
namespace QV4 {
|
||||
namespace JIT {
|
||||
|
||||
#define JIT_STRINGIFYx(s) #s
|
||||
#define JIT_STRINGIFY(s) JIT_STRINGIFYx(s)
|
||||
|
||||
#define GENERATE_RUNTIME_CALL(function, destination) \
|
||||
callRuntime(JIT_STRINGIFY(function), \
|
||||
reinterpret_cast<void *>(&Runtime::function::call), \
|
||||
callRuntime(reinterpret_cast<void *>(&Runtime::function::call), \
|
||||
destination)
|
||||
#define GENERATE_TAIL_CALL(function) \
|
||||
tailCallRuntime(JIT_STRINGIFY(function), \
|
||||
reinterpret_cast<void *>(&function))
|
||||
tailCallRuntime(reinterpret_cast<void *>(&function))
|
||||
|
||||
class BaselineAssembler {
|
||||
public:
|
||||
|
@ -153,7 +148,7 @@ public:
|
|||
void passCppFrameAsArg(int arg);
|
||||
void passInt32AsArg(int value, int arg);
|
||||
void passPointerAsArg(void *ptr, int arg);
|
||||
void callRuntime(const char *functionName, const void *funcPtr, CallResultDestination dest);
|
||||
void callRuntime(const void *funcPtr, CallResultDestination dest);
|
||||
void saveAccumulatorInFrame();
|
||||
void loadAccumulatorFromFrame();
|
||||
void jsTailCall(int func, int thisObject, int argc, int argv);
|
||||
|
@ -179,7 +174,7 @@ protected:
|
|||
|
||||
private:
|
||||
typedef unsigned(*CmpFunc)(const Value&,const Value&);
|
||||
void cmp(int cond, CmpFunc function, const char *functionName, int lhs);
|
||||
void cmp(int cond, CmpFunc function, int lhs);
|
||||
};
|
||||
|
||||
} // namespace JIT
|
||||
|
|
|
@ -2316,6 +2316,133 @@ Bool Runtime::CompareStrictNotEqual::call(const Value &left, const Value &right)
|
|||
return ! RuntimeHelpers::strictEqual(left, right);
|
||||
}
|
||||
|
||||
template<typename Operation>
|
||||
static inline const void *symbol()
|
||||
{
|
||||
return reinterpret_cast<void *>(&Operation::call);
|
||||
}
|
||||
|
||||
QHash<const void *, const char *> Runtime::symbolTable()
|
||||
{
|
||||
static const QHash<const void *, const char *> symbols({
|
||||
#ifndef V4_BOOTSTRAP
|
||||
{symbol<CallGlobalLookup>(), "CallGlobalLookup" },
|
||||
{symbol<CallQmlContextPropertyLookup>(), "CallQmlContextPropertyLookup" },
|
||||
{symbol<CallName>(), "CallName" },
|
||||
{symbol<CallProperty>(), "CallProperty" },
|
||||
{symbol<CallPropertyLookup>(), "CallPropertyLookup" },
|
||||
{symbol<CallElement>(), "CallElement" },
|
||||
{symbol<CallValue>(), "CallValue" },
|
||||
{symbol<CallWithReceiver>(), "CallWithReceiver" },
|
||||
{symbol<CallPossiblyDirectEval>(), "CallPossiblyDirectEval" },
|
||||
{symbol<CallWithSpread>(), "CallWithSpread" },
|
||||
{symbol<TailCall>(), "TailCall" },
|
||||
|
||||
{symbol<Construct>(), "Construct" },
|
||||
{symbol<ConstructWithSpread>(), "ConstructWithSpread" },
|
||||
|
||||
{symbol<StoreNameStrict>(), "StoreNameStrict" },
|
||||
{symbol<StoreNameSloppy>(), "StoreNameSloppy" },
|
||||
{symbol<StoreProperty>(), "StoreProperty" },
|
||||
{symbol<StoreElement>(), "StoreElement" },
|
||||
{symbol<LoadProperty>(), "LoadProperty" },
|
||||
{symbol<LoadName>(), "LoadName" },
|
||||
{symbol<LoadElement>(), "LoadElement" },
|
||||
{symbol<LoadSuperProperty>(), "LoadSuperProperty" },
|
||||
{symbol<StoreSuperProperty>(), "StoreSuperProperty" },
|
||||
{symbol<LoadSuperConstructor>(), "LoadSuperConstructor" },
|
||||
{symbol<LoadGlobalLookup>(), "LoadGlobalLookup" },
|
||||
{symbol<LoadQmlContextPropertyLookup>(), "LoadQmlContextPropertyLookup" },
|
||||
{symbol<GetLookup>(), "GetLookup" },
|
||||
{symbol<SetLookupStrict>(), "SetLookupStrict" },
|
||||
{symbol<SetLookupSloppy>(), "SetLookupSloppy" },
|
||||
|
||||
{symbol<TypeofValue>(), "TypeofValue" },
|
||||
{symbol<TypeofName>(), "TypeofName" },
|
||||
|
||||
{symbol<DeleteProperty_NoThrow>(), "DeleteProperty_NoThrow" },
|
||||
{symbol<DeleteProperty>(), "DeleteProperty" },
|
||||
{symbol<DeleteName_NoThrow>(), "DeleteName_NoThrow" },
|
||||
{symbol<DeleteName>(), "DeleteName" },
|
||||
|
||||
{symbol<ThrowException>(), "ThrowException" },
|
||||
{symbol<PushCallContext>(), "PushCallContext" },
|
||||
{symbol<PushWithContext>(), "PushWithContext" },
|
||||
{symbol<PushCatchContext>(), "PushCatchContext" },
|
||||
{symbol<PushBlockContext>(), "PushBlockContext" },
|
||||
{symbol<CloneBlockContext>(), "CloneBlockContext" },
|
||||
{symbol<PushScriptContext>(), "PushScriptContext" },
|
||||
{symbol<PopScriptContext>(), "PopScriptContext" },
|
||||
{symbol<ThrowReferenceError>(), "ThrowReferenceError" },
|
||||
{symbol<ThrowOnNullOrUndefined>(), "ThrowOnNullOrUndefined" },
|
||||
|
||||
{symbol<Closure>(), "Closure" },
|
||||
|
||||
{symbol<ConvertThisToObject>(), "ConvertThisToObject" },
|
||||
{symbol<DeclareVar>(), "DeclareVar" },
|
||||
{symbol<CreateMappedArgumentsObject>(), "CreateMappedArgumentsObject" },
|
||||
{symbol<CreateUnmappedArgumentsObject>(), "CreateUnmappedArgumentsObject" },
|
||||
{symbol<CreateRestParameter>(), "CreateRestParameter" },
|
||||
|
||||
{symbol<ArrayLiteral>(), "ArrayLiteral" },
|
||||
{symbol<ObjectLiteral>(), "ObjectLiteral" },
|
||||
{symbol<CreateClass>(), "CreateClass" },
|
||||
|
||||
{symbol<GetIterator>(), "GetIterator" },
|
||||
{symbol<IteratorNext>(), "IteratorNext" },
|
||||
{symbol<IteratorNextForYieldStar>(), "IteratorNextForYieldStar" },
|
||||
{symbol<IteratorClose>(), "IteratorClose" },
|
||||
{symbol<DestructureRestElement>(), "DestructureRestElement" },
|
||||
|
||||
{symbol<ToObject>(), "ToObject" },
|
||||
{symbol<ToBoolean>(), "ToBoolean" },
|
||||
{symbol<ToNumber>(), "ToNumber" },
|
||||
|
||||
{symbol<UMinus>(), "UMinus" },
|
||||
|
||||
{symbol<Instanceof>(), "Instanceof" },
|
||||
{symbol<In>(), "In" },
|
||||
{symbol<Add>(), "Add" },
|
||||
{symbol<Sub>(), "Sub" },
|
||||
{symbol<Mul>(), "Mul" },
|
||||
{symbol<Div>(), "Div" },
|
||||
{symbol<Mod>(), "Mod" },
|
||||
{symbol<Exp>(), "Exp" },
|
||||
{symbol<BitAnd>(), "BitAnd" },
|
||||
{symbol<BitOr>(), "BitOr" },
|
||||
{symbol<BitXor>(), "BitXor" },
|
||||
{symbol<Shl>(), "Shl" },
|
||||
{symbol<Shr>(), "Shr" },
|
||||
{symbol<UShr>(), "UShr" },
|
||||
{symbol<GreaterThan>(), "GreaterThan" },
|
||||
{symbol<LessThan>(), "LessThan" },
|
||||
{symbol<GreaterEqual>(), "GreaterEqual" },
|
||||
{symbol<LessEqual>(), "LessEqual" },
|
||||
{symbol<Equal>(), "Equal" },
|
||||
{symbol<NotEqual>(), "NotEqual" },
|
||||
{symbol<StrictEqual>(), "StrictEqual" },
|
||||
{symbol<StrictNotEqual>(), "StrictNotEqual" },
|
||||
|
||||
{symbol<CompareGreaterThan>(), "CompareGreaterThan" },
|
||||
{symbol<CompareLessThan>(), "CompareLessThan" },
|
||||
{symbol<CompareGreaterEqual>(), "CompareGreaterEqual" },
|
||||
{symbol<CompareLessEqual>(), "CompareLessEqual" },
|
||||
{symbol<CompareEqual>(), "CompareEqual" },
|
||||
{symbol<CompareNotEqual>(), "CompareNotEqual" },
|
||||
{symbol<CompareStrictEqual>(), "CompareStrictEqual" },
|
||||
{symbol<CompareStrictNotEqual>(), "CompareStrictNotEqual" },
|
||||
|
||||
{symbol<CompareInstanceof>(), "CompareInstanceOf" },
|
||||
{symbol<CompareIn>(), "CompareIn" },
|
||||
|
||||
{symbol<RegexpLiteral>(), "RegexpLiteral" },
|
||||
{symbol<GetTemplateObject>(), "GetTemplateObject" }
|
||||
#endif
|
||||
});
|
||||
|
||||
return symbols;
|
||||
}
|
||||
|
||||
} // namespace QV4
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -501,6 +501,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
|
|||
static const int tailCall_argv = -3;
|
||||
static const int tailCall_argc = -4;
|
||||
};
|
||||
|
||||
static QHash<const void *, const char *> symbolTable();
|
||||
};
|
||||
|
||||
static_assert(std::is_standard_layout<Runtime>::value, "Runtime needs to be standard layout in order for us to be able to use offsetof");
|
||||
|
|
|
@ -298,8 +298,9 @@ protected:
|
|||
case QMetaType::Int:
|
||||
if (result.isInteger())
|
||||
return doStore<int>(result.integerValue(), pd, flags);
|
||||
else if (result.isNumber())
|
||||
return doStore<int>(result.doubleValue(), pd, flags);
|
||||
else if (result.isNumber()) {
|
||||
return doStore<int>(QV4::StaticValue::toInteger(result.doubleValue()), pd, flags);
|
||||
}
|
||||
break;
|
||||
case QMetaType::Double:
|
||||
if (result.isNumber())
|
||||
|
|
|
@ -969,6 +969,7 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
|
|||
|
||||
if (!state->creator->populateDeferredProperties(object, deferredData))
|
||||
state->errors << state->creator->errors;
|
||||
deferredData->bindings.clear();
|
||||
|
||||
deferredState->constructionStates += state;
|
||||
}
|
||||
|
|
|
@ -2141,6 +2141,40 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
|
|||
return true;
|
||||
}
|
||||
|
||||
bool QQmlImportDatabase::removeDynamicPlugin(const QString &filePath)
|
||||
{
|
||||
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
|
||||
QMutexLocker lock(&plugins->mutex);
|
||||
|
||||
auto it = plugins->find(QFileInfo(filePath).absoluteFilePath());
|
||||
if (it == plugins->end())
|
||||
return false;
|
||||
|
||||
QPluginLoader *loader = it->loader;
|
||||
if (!loader)
|
||||
return false;
|
||||
|
||||
if (!loader->unload()) {
|
||||
qWarning("Unloading %s failed: %s", qPrintable(it->uri),
|
||||
qPrintable(loader->errorString()));
|
||||
}
|
||||
|
||||
delete loader;
|
||||
plugins->erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList QQmlImportDatabase::dynamicPlugins() const
|
||||
{
|
||||
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
|
||||
QMutexLocker lock(&plugins->mutex);
|
||||
QStringList results;
|
||||
for (auto it = plugins->constBegin(), end = plugins->constEnd(); it != end; ++it) {
|
||||
if (it->loader != nullptr)
|
||||
results.append(it.key());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
#endif // QT_CONFIG(library)
|
||||
|
||||
void QQmlImportDatabase::clearDirCache()
|
||||
|
|
|
@ -203,7 +203,7 @@ private:
|
|||
QQmlImportsPrivate *d;
|
||||
};
|
||||
|
||||
class QQmlImportDatabase
|
||||
class Q_QML_PRIVATE_EXPORT QQmlImportDatabase
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(QQmlImportDatabase)
|
||||
public:
|
||||
|
@ -214,6 +214,8 @@ public:
|
|||
|
||||
#if QT_CONFIG(library)
|
||||
bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, int vmaj, QList<QQmlError> *errors);
|
||||
bool removeDynamicPlugin(const QString &filePath);
|
||||
QStringList dynamicPlugins() const;
|
||||
#endif
|
||||
|
||||
QStringList importPathList(PathType type = LocalOrRemote) const;
|
||||
|
|
|
@ -234,73 +234,23 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
|
|||
return instance;
|
||||
}
|
||||
|
||||
// ### unify or keep in sync with populateDeferredBinding()
|
||||
bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData)
|
||||
void QQmlObjectCreator::beginPopulateDeferred(QQmlContextData *newContext)
|
||||
{
|
||||
QQmlData *declarativeData = QQmlData::get(instance);
|
||||
context = deferredData->context;
|
||||
sharedState->rootContext = context;
|
||||
|
||||
QObject *bindingTarget = instance;
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
|
||||
QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
|
||||
|
||||
QObject *scopeObject = instance;
|
||||
qSwap(_scopeObject, scopeObject);
|
||||
|
||||
QV4::Scope valueScope(v4);
|
||||
context = newContext;
|
||||
sharedState->rootContext = newContext;
|
||||
|
||||
Q_ASSERT(topLevelCreator);
|
||||
Q_ASSERT(!sharedState->allJavaScriptObjects);
|
||||
|
||||
QV4::Scope valueScope(v4);
|
||||
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
|
||||
|
||||
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
|
||||
|
||||
qSwap(_qmlContext, qmlContext);
|
||||
|
||||
qSwap(_propertyCache, cache);
|
||||
qSwap(_qobject, instance);
|
||||
|
||||
int objectIndex = deferredData->deferredIdx;
|
||||
qSwap(_compiledObjectIndex, objectIndex);
|
||||
|
||||
const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
|
||||
qSwap(_compiledObject, obj);
|
||||
|
||||
qSwap(_ddata, declarativeData);
|
||||
qSwap(_bindingTarget, bindingTarget);
|
||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||
|
||||
setupBindings(/*applyDeferredBindings=*/true);
|
||||
|
||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||
qSwap(_bindingTarget, bindingTarget);
|
||||
qSwap(_ddata, declarativeData);
|
||||
qSwap(_compiledObject, obj);
|
||||
qSwap(_compiledObjectIndex, objectIndex);
|
||||
qSwap(_qobject, instance);
|
||||
qSwap(_propertyCache, cache);
|
||||
|
||||
qSwap(_qmlContext, qmlContext);
|
||||
qSwap(_scopeObject, scopeObject);
|
||||
|
||||
deferredData->bindings.clear();
|
||||
phase = ObjectsCreated;
|
||||
|
||||
return errors.isEmpty();
|
||||
}
|
||||
|
||||
// ### unify or keep in sync with populateDeferredProperties()
|
||||
bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding)
|
||||
void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex,
|
||||
const QQmlPropertyPrivate *qmlProperty,
|
||||
const QV4::CompiledData::Binding *binding)
|
||||
{
|
||||
Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding);
|
||||
|
||||
QObject *instance = qmlProperty.object();
|
||||
QQmlData *declarativeData = QQmlData::get(instance);
|
||||
context = deferredData->context;
|
||||
sharedState->rootContext = context;
|
||||
|
||||
QObject *bindingTarget = instance;
|
||||
|
||||
QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
|
||||
|
@ -312,9 +262,6 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
|
|||
QV4::Scope valueScope(v4);
|
||||
|
||||
Q_ASSERT(topLevelCreator);
|
||||
if (!sharedState->allJavaScriptObjects)
|
||||
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
|
||||
|
||||
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
|
||||
|
||||
qSwap(_qmlContext, qmlContext);
|
||||
|
@ -322,7 +269,7 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
|
|||
qSwap(_propertyCache, cache);
|
||||
qSwap(_qobject, instance);
|
||||
|
||||
int objectIndex = deferredData->deferredIdx;
|
||||
int objectIndex = deferredIndex;
|
||||
qSwap(_compiledObjectIndex, objectIndex);
|
||||
|
||||
const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
|
||||
|
@ -332,22 +279,29 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
|
|||
qSwap(_bindingTarget, bindingTarget);
|
||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||
|
||||
QQmlListProperty<void> savedList;
|
||||
qSwap(_currentList, savedList);
|
||||
if (binding) {
|
||||
Q_ASSERT(qmlProperty);
|
||||
Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding);
|
||||
|
||||
const QQmlPropertyData &property = QQmlPropertyPrivate::get(qmlProperty)->core;
|
||||
QQmlListProperty<void> savedList;
|
||||
qSwap(_currentList, savedList);
|
||||
|
||||
if (property.isQList()) {
|
||||
void *argv[1] = { (void*)&_currentList };
|
||||
QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
|
||||
} else if (_currentList.object) {
|
||||
_currentList = QQmlListProperty<void>();
|
||||
const QQmlPropertyData &property = qmlProperty->core;
|
||||
|
||||
if (property.isQList()) {
|
||||
void *argv[1] = { (void*)&_currentList };
|
||||
QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
|
||||
} else if (_currentList.object) {
|
||||
_currentList = QQmlListProperty<void>();
|
||||
}
|
||||
|
||||
setPropertyBinding(&property, binding);
|
||||
|
||||
qSwap(_currentList, savedList);
|
||||
} else {
|
||||
setupBindings(/*applyDeferredBindings=*/true);
|
||||
}
|
||||
|
||||
setPropertyBinding(&property, binding);
|
||||
|
||||
qSwap(_currentList, savedList);
|
||||
|
||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||
qSwap(_bindingTarget, bindingTarget);
|
||||
qSwap(_ddata, declarativeData);
|
||||
|
@ -358,12 +312,29 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
|
|||
|
||||
qSwap(_qmlContext, qmlContext);
|
||||
qSwap(_scopeObject, scopeObject);
|
||||
}
|
||||
|
||||
phase = ObjectsCreated;
|
||||
|
||||
bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
|
||||
const QQmlData::DeferredData *deferredData)
|
||||
{
|
||||
beginPopulateDeferred(deferredData->context);
|
||||
populateDeferred(instance, deferredData->deferredIdx);
|
||||
finalizePopulateDeferred();
|
||||
return errors.isEmpty();
|
||||
}
|
||||
|
||||
void QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
|
||||
const QV4::CompiledData::Binding *binding)
|
||||
{
|
||||
populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
|
||||
binding);
|
||||
}
|
||||
|
||||
void QQmlObjectCreator::finalizePopulateDeferred()
|
||||
{
|
||||
phase = ObjectsCreated;
|
||||
}
|
||||
|
||||
void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
|
||||
{
|
||||
QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
|
||||
|
|
|
@ -112,8 +112,14 @@ public:
|
|||
~QQmlObjectCreator();
|
||||
|
||||
QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr);
|
||||
bool populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData);
|
||||
bool populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding);
|
||||
|
||||
bool populateDeferredProperties(QObject *instance, const QQmlData::DeferredData *deferredData);
|
||||
|
||||
void beginPopulateDeferred(QQmlContextData *context);
|
||||
void populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
|
||||
const QV4::CompiledData::Binding *binding);
|
||||
void finalizePopulateDeferred();
|
||||
|
||||
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
|
||||
void clear();
|
||||
|
||||
|
@ -139,6 +145,11 @@ private:
|
|||
bool populateInstance(int index, QObject *instance,
|
||||
QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty);
|
||||
|
||||
// If qmlProperty and binding are null, populate all properties, otherwise only the given one.
|
||||
void populateDeferred(QObject *instance, int deferredIndex,
|
||||
const QQmlPropertyPrivate *qmlProperty = nullptr,
|
||||
const QV4::CompiledData::Binding *binding = nullptr);
|
||||
|
||||
void setupBindings(bool applyDeferredBindings = false);
|
||||
bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
||||
void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qurl.h>
|
||||
#include <QPointer>
|
||||
#include <QtCore/qpointer.h>
|
||||
|
||||
#include <QtCore/qmetaobject.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
|
|
@ -2060,20 +2060,19 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
|
|||
firstDirtyPos = nodeIterator->startPos();
|
||||
// ### this could be optimized if the first and last dirty nodes are not connected
|
||||
// as the intermediate text nodes would usually only need to be transformed differently.
|
||||
int lastDirtyPos = firstDirtyPos;
|
||||
QQuickTextNode *firstCleanNode = nullptr;
|
||||
auto it = d->textNodeMap.constEnd();
|
||||
while (it != nodeIterator) {
|
||||
--it;
|
||||
if (it->dirty()) {
|
||||
lastDirtyPos = it->startPos();
|
||||
if (it->dirty())
|
||||
break;
|
||||
}
|
||||
firstCleanNode = it->textNode();
|
||||
}
|
||||
do {
|
||||
rootNode->removeChildNode(nodeIterator->textNode());
|
||||
delete nodeIterator->textNode();
|
||||
nodeIterator = d->textNodeMap.erase(nodeIterator);
|
||||
} while (nodeIterator != d->textNodeMap.constEnd() && nodeIterator->startPos() <= lastDirtyPos);
|
||||
} while (nodeIterator != d->textNodeMap.constEnd() && nodeIterator->textNode() != firstCleanNode);
|
||||
}
|
||||
|
||||
// FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
|
||||
|
|
|
@ -2259,8 +2259,8 @@ void QQuickTextInput::remove(int start, int end)
|
|||
d->m_cursor -= qMin(d->m_cursor, end) - start;
|
||||
if (d->m_selstart > start)
|
||||
d->m_selstart -= qMin(d->m_selstart, end) - start;
|
||||
if (d->m_selend > end)
|
||||
d->m_selend -= qMin(d->m_selend, end) - start;
|
||||
if (d->m_selend >= end)
|
||||
d->m_selend -= end - start;
|
||||
}
|
||||
d->addCommand(QQuickTextInputPrivate::Command(
|
||||
QQuickTextInputPrivate::SetSelection, d->m_cursor, 0, d->m_selstart, d->m_selend));
|
||||
|
|
|
@ -4220,16 +4220,18 @@ QQmlIncubationController *QQuickWindow::incubationController() const
|
|||
The OpenGL context used for rendering the scene graph will be bound
|
||||
at this point.
|
||||
|
||||
When using the RHI and a graphics API other than OpenGL, the signal is
|
||||
emitted after the preparations for the frame have been done, meaning there
|
||||
is a command buffer in recording mode, where applicable. If desired, the
|
||||
slot function connected to this signal can query native resources like the
|
||||
command before via QSGRendererInterface. Note however that the recording of
|
||||
the main render pass is not yet started at this point and it is not
|
||||
possible to add commands within that pass. Instead, use
|
||||
beforeRenderPassRecording() for that. However, connecting to this signal is
|
||||
still important if the recording of copy type of commands is desired since
|
||||
those cannot be enqueued within a render pass.
|
||||
When using the RHI, the signal is emitted after the preparations for the
|
||||
frame have been done, meaning there is a command buffer in recording mode,
|
||||
where applicable. If desired, the slot function connected to this signal
|
||||
can query native resources like the command before via
|
||||
QSGRendererInterface. Note however that the recording of the main render
|
||||
pass is not yet started at this point and it is not possible to add
|
||||
commands within that pass. Starting a pass means clearing the color, depth,
|
||||
and stencil buffers so it is not possible to achieve an underlay type of
|
||||
rendering by just connecting to this signal. Rather, connect to
|
||||
beforeRenderPassRecording(). However, connecting to this signal is still
|
||||
important if the recording of copy type of commands is desired since those
|
||||
cannot be enqueued within a render pass.
|
||||
|
||||
\warning This signal is emitted from the scene graph rendering thread. If your
|
||||
slot function needs to finish before execution continues, you must make sure that
|
||||
|
@ -4252,18 +4254,17 @@ QQmlIncubationController *QQuickWindow::incubationController() const
|
|||
|
||||
The OpenGL context used for rendering the scene graph will be bound at this point.
|
||||
|
||||
When using the RHI and a graphics API other than OpenGL, the signal is
|
||||
emitted after scene graph has added its commands to the command buffer,
|
||||
which is not yet submitted to the graphics queue. If desired, the slot
|
||||
function connected to this signal can query native resources, like the
|
||||
command buffer, before via QSGRendererInterface. Note however that the
|
||||
render pass (or passes) are already recorded at this point and it is not
|
||||
possible to add more commands within the scenegraph's pass. Instead, use
|
||||
afterRenderPassRecording() for that. This signal has therefore limited use
|
||||
and is rarely needed in an RHI-based setup. Rather, it is the combination
|
||||
of beforeRendering() + beforeRenderPassRecording() or beforeRendering() +
|
||||
afterRenderPassRecording() that is typically used to achieve under- or
|
||||
overlaying of the custom rendering.
|
||||
When using the RHI, the signal is emitted after scene graph has added its
|
||||
commands to the command buffer, which is not yet submitted to the graphics
|
||||
queue. If desired, the slot function connected to this signal can query
|
||||
native resources, like the command buffer, before via QSGRendererInterface.
|
||||
Note however that the render pass (or passes) are already recorded at this
|
||||
point and it is not possible to add more commands within the scenegraph's
|
||||
pass. Instead, use afterRenderPassRecording() for that. This signal has
|
||||
therefore limited use and is rarely needed in an RHI-based setup. Rather,
|
||||
it is the combination of beforeRendering() + beforeRenderPassRecording() or
|
||||
beforeRendering() + afterRenderPassRecording() that is typically used to
|
||||
achieve under- or overlaying of the custom rendering.
|
||||
|
||||
\warning This signal is emitted from the scene graph rendering thread. If your
|
||||
slot function needs to finish before execution continues, you must make sure that
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
pragma Singleton
|
||||
import dumper.Imports 1.0
|
||||
|
||||
Imports {
|
||||
property int something: 2
|
||||
}
|
|
@ -17,7 +17,7 @@ HEADERS += \
|
|||
imports.h
|
||||
|
||||
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
|
||||
cp.files = qmldir plugins.qmltypes CompositeImports.qml
|
||||
cp.files = qmldir plugins.qmltypes CompositeImports.qml Derived.qml
|
||||
cp.path = $$OUT_PWD
|
||||
COPIES += cp
|
||||
}
|
||||
|
|
|
@ -14,4 +14,14 @@ Module {
|
|||
exports: ["dumper.Imports/Imports 1.0"]
|
||||
exportMetaObjectRevisions: [0]
|
||||
}
|
||||
Component {
|
||||
prototype: "Imports"
|
||||
name: "dumper.Imports/Derived 1.0"
|
||||
exports: ["dumper.Imports/Derived 1.0"]
|
||||
exportMetaObjectRevisions: [0]
|
||||
isComposite: true
|
||||
isCreatable: false
|
||||
isSingleton: true
|
||||
Property { name: "something"; type: "int" }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module dumper.Imports
|
||||
plugin Imports
|
||||
CompositeImports 1.0 CompositeImports.qml
|
||||
singleton Derived 1.0 Derived.qml
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import QtQuick 2.11
|
||||
|
||||
Item {
|
||||
visible: true
|
||||
width: 320
|
||||
height: 200
|
||||
property int val: other.val
|
||||
|
||||
Rectangle {
|
||||
id: other
|
||||
anchors.fill: parent;
|
||||
property int val: undefined / 2
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ private slots:
|
|||
void bindingOverwriting();
|
||||
void bindToQmlComponent();
|
||||
void bindingDoesNoWeirdConversion();
|
||||
void bindNaNToInt();
|
||||
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
|
@ -398,6 +399,16 @@ void tst_qqmlbinding::bindingDoesNoWeirdConversion()
|
|||
QVERIFY(colorLabel);
|
||||
}
|
||||
|
||||
//QTBUG-72442
|
||||
void tst_qqmlbinding::bindNaNToInt()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
QQmlComponent c(&engine, testFileUrl("nanPropertyToInt.qml"));
|
||||
QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
|
||||
|
||||
QVERIFY(item != nullptr);
|
||||
QCOMPARE(item->property("val").toInt(), 0);
|
||||
}
|
||||
QTEST_MAIN(tst_qqmlbinding)
|
||||
|
||||
#include "tst_qqmlbinding.moc"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <QtQuick/qquickview.h>
|
||||
#include <QtQuick/qquickitem.h>
|
||||
#include <private/qqmlimport_p.h>
|
||||
#include <private/qqmlengine_p.h>
|
||||
#include "../../shared/util.h"
|
||||
|
||||
class tst_QQmlImport : public QQmlDataTest
|
||||
|
@ -46,6 +47,7 @@ private slots:
|
|||
void completeQmldirPaths();
|
||||
void interceptQmldir();
|
||||
void singletonVersionResolution();
|
||||
void removeDynamicPlugin();
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
|
@ -260,6 +262,25 @@ void tst_QQmlImport::singletonVersionResolution()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_QQmlImport::removeDynamicPlugin()
|
||||
{
|
||||
qmlClearTypeRegistrations();
|
||||
QQmlEngine engine;
|
||||
{
|
||||
// Load something that adds a dynamic plugin
|
||||
QQmlComponent component(&engine);
|
||||
component.setData(QByteArray("import QtTest 1.0; TestResult{}"), QUrl());
|
||||
QVERIFY(component.isReady());
|
||||
}
|
||||
QQmlImportDatabase *imports = &QQmlEnginePrivate::get(&engine)->importDatabase;
|
||||
const QStringList &plugins = imports->dynamicPlugins();
|
||||
QVERIFY(!plugins.isEmpty());
|
||||
for (const QString &plugin : plugins)
|
||||
QVERIFY(imports->removeDynamicPlugin(plugin));
|
||||
QVERIFY(imports->dynamicPlugins().isEmpty());
|
||||
qmlClearTypeRegistrations();
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QQmlImport)
|
||||
|
||||
|
|
|
@ -4728,11 +4728,13 @@ static void beginDeferredOnce(QQmlEnginePrivate *enginePriv,
|
|||
typedef QMultiHash<int, const QV4::CompiledData::Binding *> QV4PropertyBindingHash;
|
||||
auto it = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.second);
|
||||
auto last = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.first);
|
||||
state->creator->beginPopulateDeferred(deferData->context);
|
||||
while (it != last) {
|
||||
if (!state->creator->populateDeferredBinding(property, deferData, *it))
|
||||
state->errors << state->creator->errors;
|
||||
state->creator->populateDeferredBinding(property, deferData->deferredIdx, *it);
|
||||
++it;
|
||||
}
|
||||
state->creator->finalizePopulateDeferred();
|
||||
state->errors << state->creator->errors;
|
||||
|
||||
deferredState->constructionStates += state;
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick 2.12
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 600
|
||||
height: 300
|
||||
|
||||
TextInput {
|
||||
id: qwe
|
||||
objectName: "qwe"
|
||||
width: 500
|
||||
height: 100
|
||||
font.pixelSize: 50
|
||||
text: "123456"
|
||||
focus: true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
qwe.insert(0, "***")
|
||||
qwe.remove(0, 3)
|
||||
}
|
||||
}
|
|
@ -230,6 +230,7 @@ private slots:
|
|||
void padding();
|
||||
|
||||
void QTBUG_51115_readOnlyResetsSelection();
|
||||
void QTBUG_77814_InsertRemoveNoSelection();
|
||||
|
||||
private:
|
||||
void simulateKey(QWindow *, int key);
|
||||
|
@ -7003,6 +7004,18 @@ void tst_qquicktextinput::QTBUG_51115_readOnlyResetsSelection()
|
|||
QCOMPARE(obj->selectedText(), QString());
|
||||
}
|
||||
|
||||
void tst_qquicktextinput::QTBUG_77814_InsertRemoveNoSelection()
|
||||
{
|
||||
QQuickView view;
|
||||
view.setSource(testFileUrl("qtbug77841.qml"));
|
||||
view.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
||||
QQuickTextInput *textInput = view.rootObject()->findChild<QQuickTextInput*>("qwe");
|
||||
QVERIFY(textInput);
|
||||
|
||||
QCOMPARE(textInput->selectedText(), QString());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qquicktextinput)
|
||||
|
||||
#include "tst_qquicktextinput.moc"
|
||||
|
|
|
@ -380,23 +380,21 @@ public:
|
|||
relocatableModuleUri = uri;
|
||||
}
|
||||
|
||||
const QString getExportString(QString qmlTyName, int majorVersion, int minorVersion)
|
||||
QString getExportString(const QQmlType &type, const QmlVersionInfo &versionInfo)
|
||||
{
|
||||
if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) {
|
||||
qmlTyName.remove(0, relocatableModuleUri.size() + 1);
|
||||
}
|
||||
if (qmlTyName.startsWith("./")) {
|
||||
qmlTyName.remove(0, 2);
|
||||
}
|
||||
if (qmlTyName.startsWith(QLatin1Char('/'))) {
|
||||
qmlTyName.remove(0, 1);
|
||||
}
|
||||
const QString exportString = enquote(
|
||||
QString("%1 %2.%3").arg(
|
||||
qmlTyName,
|
||||
QString::number(majorVersion),
|
||||
QString::number(minorVersion)));
|
||||
return exportString;
|
||||
const QString module = type.module().isEmpty() ? versionInfo.pluginImportUri
|
||||
: type.module();
|
||||
const int majorVersion = type.majorVersion() >= 0 ? type.majorVersion()
|
||||
: versionInfo.majorVersion;
|
||||
const int minorVersion = type.minorVersion() >= 0 ? type.minorVersion()
|
||||
: versionInfo.minorVersion;
|
||||
|
||||
const QString versionedElement = type.elementName()
|
||||
+ QString::fromLatin1(" %1.%2").arg(majorVersion).arg(minorVersion);
|
||||
|
||||
return enquote((module == relocatableModuleUri)
|
||||
? versionedElement
|
||||
: module + QLatin1Char('/') + versionedElement);
|
||||
}
|
||||
|
||||
void writeMetaContent(const QMetaObject *meta, KnownAttributes *knownAttributes = nullptr)
|
||||
|
@ -441,8 +439,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
QString getPrototypeNameForCompositeType(const QMetaObject *metaObject, QSet<QByteArray> &defaultReachableNames,
|
||||
QList<const QMetaObject *> *objectsToMerge, const QmlVersionInfo &versionInfo)
|
||||
QString getPrototypeNameForCompositeType(
|
||||
const QMetaObject *metaObject, QList<const QMetaObject *> *objectsToMerge,
|
||||
const QmlVersionInfo &versionInfo)
|
||||
{
|
||||
auto ty = QQmlMetaType::qmlType(metaObject);
|
||||
QString prototypeName;
|
||||
|
@ -454,24 +453,28 @@ public:
|
|||
&& !objectsToMerge->contains(metaObject))
|
||||
objectsToMerge->append(metaObject);
|
||||
const QMetaObject *superMetaObject = metaObject->superClass();
|
||||
if (!superMetaObject)
|
||||
if (!superMetaObject) {
|
||||
prototypeName = "QObject";
|
||||
else
|
||||
} else {
|
||||
QQmlType superType = QQmlMetaType::qmlType(superMetaObject);
|
||||
if (superType.isValid() && !superType.isComposite())
|
||||
return convertToId(superMetaObject->className());
|
||||
prototypeName = getPrototypeNameForCompositeType(
|
||||
superMetaObject, defaultReachableNames, objectsToMerge, versionInfo);
|
||||
superMetaObject, objectsToMerge, versionInfo);
|
||||
}
|
||||
} else {
|
||||
prototypeName = convertToId(metaObject->className());
|
||||
}
|
||||
return prototypeName;
|
||||
}
|
||||
|
||||
void dumpComposite(QQmlEngine *engine, const QList<QQmlType> &compositeType, QSet<QByteArray> &defaultReachableNames, const QmlVersionInfo &versionInfo)
|
||||
void dumpComposite(QQmlEngine *engine, const QList<QQmlType> &compositeType, const QmlVersionInfo &versionInfo)
|
||||
{
|
||||
for (const QQmlType &type : compositeType)
|
||||
dumpCompositeItem(engine, type, defaultReachableNames, versionInfo);
|
||||
dumpCompositeItem(engine, type, versionInfo);
|
||||
}
|
||||
|
||||
void dumpCompositeItem(QQmlEngine *engine, const QQmlType &compositeType, QSet<QByteArray> &defaultReachableNames, const QmlVersionInfo &versionInfo)
|
||||
void dumpCompositeItem(QQmlEngine *engine, const QQmlType &compositeType, const QmlVersionInfo &versionInfo)
|
||||
{
|
||||
QQmlComponent e(engine, compositeType.sourceUrl());
|
||||
if (!e.isReady()) {
|
||||
|
@ -492,13 +495,17 @@ public:
|
|||
QList<const QMetaObject *> objectsToMerge;
|
||||
KnownAttributes knownAttributes;
|
||||
// Get C++ base class name for the composite type
|
||||
QString prototypeName = getPrototypeNameForCompositeType(mainMeta, defaultReachableNames,
|
||||
&objectsToMerge, versionInfo);
|
||||
QString prototypeName = getPrototypeNameForCompositeType(mainMeta, &objectsToMerge,
|
||||
versionInfo);
|
||||
qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
|
||||
|
||||
QString qmlTyName = compositeType.qmlTypeName();
|
||||
const QString exportString = getExportString(qmlTyName, compositeType.majorVersion(), compositeType.minorVersion());
|
||||
const QString exportString = getExportString(compositeType, versionInfo);
|
||||
|
||||
// TODO: why don't we simply output the compositeType.elementName() here?
|
||||
// That would make more sense, but it would change the format quite a bit.
|
||||
qml->writeScriptBinding(QLatin1String("name"), exportString);
|
||||
|
||||
qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
|
||||
qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType.minorVersion()));
|
||||
qml->writeBooleanBinding(QLatin1String("isComposite"), true);
|
||||
|
@ -565,7 +572,7 @@ public:
|
|||
if (attachedType != meta)
|
||||
attachedTypeId = convertToId(attachedType);
|
||||
}
|
||||
const QString exportString = getExportString(type.qmlTypeName(), type.majorVersion(), type.minorVersion());
|
||||
const QString exportString = getExportString(type, { QString(), -1, -1, false });
|
||||
int metaObjectRevision = type.metaObjectRevision();
|
||||
if (extendedObject) {
|
||||
// emulate custom metaobjectrevision out of import
|
||||
|
@ -1239,9 +1246,6 @@ int main(int argc, char *argv[])
|
|||
QSet<const QMetaObject *> uncreatableMetas;
|
||||
QSet<const QMetaObject *> singletonMetas;
|
||||
|
||||
// QQuickKeyEvent, QQuickPinchEvent, QQuickDropEvent are not exported
|
||||
QSet<QByteArray> defaultReachableNames;
|
||||
|
||||
// this will hold the meta objects we want to dump information of
|
||||
QSet<const QMetaObject *> metas;
|
||||
|
||||
|
@ -1370,7 +1374,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
QMap<QString, QList<QQmlType>>::const_iterator iter = compositeTypes.constBegin();
|
||||
for (; iter != compositeTypes.constEnd(); ++iter)
|
||||
dumper.dumpComposite(&engine, iter.value(), defaultReachableNames, info);
|
||||
dumper.dumpComposite(&engine, iter.value(), info);
|
||||
|
||||
// define QEasingCurve as an extension of QQmlEasingValueType, this way
|
||||
// properties using the QEasingCurve type get useful type information.
|
||||
|
|
Loading…
Reference in New Issue