diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-11-09 01:00:06 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-11-09 01:00:07 +0100 |
commit | b01a16ea74e92c78c009f132ef7bc70e91398a98 (patch) | |
tree | fca15f247fed71ebfd67e7fda7864612190c42d9 /src | |
parent | 6fecfdc769314162d6c909c9ae0a85631964883f (diff) | |
parent | 6c08137faf1a53db879701126608833474a2450b (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I2ed93c9d5fa8ec9b075112618a2535535591a0e8
Diffstat (limited to 'src')
22 files changed, 230 insertions, 76 deletions
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 535e29ee70..fd91add04e 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -1866,6 +1866,7 @@ Item { else qtest_runFunction(prop, row) qtest_results.dataTag = "" + qtest_results.skipped = false } if (!haveData) { if (datafunc === "init_data") diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp index 9cf96d27f3..af86b70014 100644 --- a/src/qml/compiler/qv4bytecodehandler.cpp +++ b/src/qml/compiler/qv4bytecodehandler.cpp @@ -537,6 +537,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint COLLECTOR_BEGIN_INSTR(ThrowOnNullOrUndefined) COLLECTOR_END_INSTR(ThrowOnNullOrUndefined) + COLLECTOR_BEGIN_INSTR(GetTemplateObject) + COLLECTOR_END_INSTR(GetTemplateObject) + COLLECTOR_BEGIN_INSTR(LoadQmlContext) COLLECTOR_END_INSTR(LoadQmlContext) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index ac596e2b5b..09c0e60f4d 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2243,85 +2243,35 @@ bool Codegen::visit(TaggedTemplate *ast) break; } - int arrayTemp = createTemplateArray(ast->templateLiteral); - Q_UNUSED(arrayTemp); + createTemplateObject(ast->templateLiteral); + int templateObjectTemp = Reference::fromAccumulator(this).storeOnStack().stackSlot(); + Q_UNUSED(templateObjectTemp); auto calldata = pushTemplateArgs(ast->templateLiteral); if (hasError) return false; ++calldata.argc; - Q_ASSERT(calldata.argv == arrayTemp + 1); + Q_ASSERT(calldata.argv == templateObjectTemp + 1); --calldata.argv; handleCall(base, calldata, functionObject, thisObject); return false; } -int Codegen::createTemplateArray(TemplateLiteral *t) +void Codegen::createTemplateObject(TemplateLiteral *t) { - int arrayTemp = bytecodeGenerator->newRegister(); + TemplateObject obj; - int argc = 0; - int args = -1; - auto push = [this, &argc, &args](const QStringRef &arg) { - int temp = bytecodeGenerator->newRegister(); - if (args == -1) - args = temp; - Instruction::LoadRuntimeString instr; - instr.stringId = registerString(arg.toString()); - bytecodeGenerator->addInstruction(instr); - Instruction::StoreReg store; - store.reg = temp; - bytecodeGenerator->addInstruction(store); - - ++argc; - }; - - { - RegisterScope scope(this); - - for (TemplateLiteral *it = t; it; it = it->next) - push(it->value); - - if (args == -1) { - Q_ASSERT(argc == 0); - args = 0; - } - - Instruction::DefineArray call; - call.argc = argc; - call.args = Moth::StackSlot::createRegister(args); - bytecodeGenerator->addInstruction(call); - - Instruction::StoreReg store; - store.reg = arrayTemp; - bytecodeGenerator->addInstruction(store); + for (TemplateLiteral *it = t; it; it = it->next) { + obj.strings.append(registerString(it->value.toString())); + obj.rawStrings.append(registerString(it->rawValue.toString())); } - { - RegisterScope scope(this); - - argc = 0; - args = -1; - - for (TemplateLiteral *it = t; it; it = it->next) - push(it->rawValue); - - if (args == -1) { - Q_ASSERT(argc == 0); - args = 0; - } - - Instruction::DefineArray call; - call.argc = argc; - call.args = Moth::StackSlot::createRegister(args); - bytecodeGenerator->addInstruction(call); - - Reference a = Reference::fromStackSlot(this, arrayTemp); - Reference m = Reference::fromMember(a, QStringLiteral("raw")); - m.storeConsumeAccumulator(); - } + int index = _module->templateObjects.size(); + _module->templateObjects.append(obj); - return arrayTemp; + Instruction::GetTemplateObject getTemplateObject; + getTemplateObject.index = index; + bytecodeGenerator->addInstruction(getTemplateObject); } bool Codegen::visit(FunctionExpression *ast) diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index e6e7d2e9fb..0bc04750f7 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -682,7 +682,7 @@ public: void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject); Arguments pushTemplateArgs(AST::TemplateLiteral *args); - int createTemplateArray(AST::TemplateLiteral *t); + void createTemplateObject(AST::TemplateLiteral *t); void setUseFastLookups(bool b) { useFastLookups = b; } diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 244e762faf..3b2d6e0a48 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -225,6 +225,36 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) return nullptr; } +Heap::Object *CompilationUnit::templateObjectAt(int index) const +{ + Q_ASSERT(index < int(data->templateObjectTableSize)); + if (!templateObjects.size()) + templateObjects.resize(data->templateObjectTableSize); + Heap::Object *o = templateObjects.at(index); + if (o) + return o; + + // create the template object + Scope scope(engine); + const CompiledData::TemplateObject *t = data->templateObjectAt(index); + Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size)); + Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size)); + ScopedValue s(scope); + for (uint i = 0; i < t->size; ++i) { + s = runtimeStrings[t->stringIndexAt(i)]; + a->arraySet(i, s); + s = runtimeStrings[t->rawStringIndexAt(i)]; + raw->arraySet(i, s); + } + + ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1); + a->defineReadonlyProperty(QStringLiteral("raw"), raw); + ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1); + + templateObjects[index] = a->objectValue()->d(); + return templateObjects.at(index); +} + void CompilationUnit::unlink() { if (engine) @@ -284,6 +314,10 @@ void CompilationUnit::markObjects(QV4::MarkStack *markStack) if (c) c->mark(markStack); + for (QV4::Heap::Object *o : qAsConst(templateObjects)) + if (o) + o->mark(markStack); + if (runtimeLookups) { for (uint i = 0; i < data->lookupTableSize; ++i) runtimeLookups[i].markObjects(markStack); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index b36b1a91ea..d0785c6883 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -373,6 +373,34 @@ struct Class }; static_assert(sizeof(Class) == 24, "Class structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +struct TemplateObject +{ + quint32_le size; + + static int calculateSize(int size) { + int trailingData = 2 * size * sizeof(quint32_le); + size_t s = align(sizeof(TemplateObject) + trailingData); + Q_ASSERT(s < INT_MAX); + return int(s); + } + + static size_t align(size_t a) { + return (a + 7) & ~size_t(7); + } + + const quint32_le *stringTable() const { + return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1)); + } + + uint stringIndexAt(uint i) const { + return stringTable()[i]; + } + uint rawStringIndexAt(uint i) const { + return stringTable()[size + i]; + } +}; +static_assert(sizeof(TemplateObject) == 4, "Template object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); + struct ExportEntry { quint32_le exportName; @@ -841,6 +869,8 @@ struct Unit quint32_le offsetToFunctionTable; quint32_le classTableSize; quint32_le offsetToClassTable; + quint32_le templateObjectTableSize; + quint32_le offsetToTemplateObjectTable; quint32_le blockTableSize; quint32_le offsetToBlockTable; quint32_le lookupTableSize; @@ -908,6 +938,7 @@ struct Unit const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); } const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); } + const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); } const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); } const Function *functionAt(int idx) const { @@ -922,6 +953,12 @@ struct Unit return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset); } + const TemplateObject *templateObjectAt(int idx) const { + const quint32_le *offsetTable = templateObjectOffsetTable(); + const quint32_le offset = offsetTable[idx]; + return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset); + } + const Block *blockAt(int idx) const { const quint32_le *offsetTable = blockOffsetTable(); const quint32_le offset = offsetTable[idx]; @@ -957,7 +994,7 @@ struct Unit const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); } }; -static_assert(sizeof(Unit) == 240, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Unit) == 248, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { @@ -1110,6 +1147,7 @@ public: QV4::Lookup *runtimeLookups = nullptr; QVector<QV4::Function *> runtimeFunctions; QVector<QV4::Heap::InternalClass *> runtimeBlocks; + mutable QVector<QV4::Heap::Object *> templateObjects; mutable QQmlNullableValue<QUrl> m_url; mutable QQmlNullableValue<QUrl> m_finalUrl; @@ -1160,6 +1198,8 @@ public: return data->stringAtInternal(index); } + Heap::Object *templateObjectAt(int index) const; + struct FunctionIterator { FunctionIterator(const Unit *unit, const Object *object, int index) : unit(unit), object(object), index(index) {} diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 7636baa1e6..3076c6b526 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -269,7 +269,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO registerString(request); } - Q_ALLOCA_VAR(quint32_le, blockClassAndFunctionOffsets, (module->functions.size() + module->classes.size() + module->blocks.size()) * sizeof(quint32_le)); + Q_ALLOCA_VAR(quint32_le, blockClassAndFunctionOffsets, (module->functions.size() + module->classes.size() + module->templateObjects.size() + module->blocks.size()) * sizeof(quint32_le)); uint jsClassDataOffset = 0; char *dataPtr; @@ -284,7 +284,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO memcpy(dataPtr + unit->offsetToFunctionTable, blockClassAndFunctionOffsets, unit->functionTableSize * sizeof(quint32_le)); memcpy(dataPtr + unit->offsetToClassTable, blockClassAndFunctionOffsets + unit->functionTableSize, unit->classTableSize * sizeof(quint32_le)); - memcpy(dataPtr + unit->offsetToBlockTable, blockClassAndFunctionOffsets + unit->functionTableSize + unit->classTableSize, unit->blockTableSize * sizeof(quint32_le)); + memcpy(dataPtr + unit->offsetToTemplateObjectTable, blockClassAndFunctionOffsets + unit->functionTableSize + unit->classTableSize, unit->templateObjectTableSize * sizeof(quint32_le)); + memcpy(dataPtr + unit->offsetToBlockTable, blockClassAndFunctionOffsets + unit->functionTableSize + unit->classTableSize + unit->templateObjectTableSize, unit->blockTableSize * sizeof(quint32_le)); for (int i = 0; i < module->functions.size(); ++i) { Context *function = module->functions.at(i); @@ -300,10 +301,16 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO writeClass(dataPtr + blockClassAndFunctionOffsets[i + module->functions.size()], c); } + for (int i = 0; i < module->templateObjects.size(); ++i) { + const TemplateObject &t = module->templateObjects.at(i); + + writeTemplateObject(dataPtr + blockClassAndFunctionOffsets[i + module->functions.size() + module->classes.size()], t); + } + for (int i = 0; i < module->blocks.size(); ++i) { Context *block = module->blocks.at(i); - writeBlock(dataPtr + blockClassAndFunctionOffsets[i + module->classes.size() + module->functions.size()], block); + writeBlock(dataPtr + blockClassAndFunctionOffsets[i + module->classes.size() + module->templateObjects.size() + module->functions.size()], block); } CompiledData::Lookup *lookupsToWrite = reinterpret_cast<CompiledData::Lookup*>(dataPtr + unit->offsetToLookupTable); @@ -532,6 +539,34 @@ void QV4::Compiler::JSUnitGenerator::writeClass(char *b, const QV4::Compiler::Cl } } +void QV4::Compiler::JSUnitGenerator::writeTemplateObject(char *b, const QV4::Compiler::TemplateObject &t) +{ + QV4::CompiledData::TemplateObject *tmpl = reinterpret_cast<QV4::CompiledData::TemplateObject *>(b); + tmpl->size = t.strings.size(); + + quint32 currentOffset = sizeof(QV4::CompiledData::TemplateObject); + + quint32_le *strings = reinterpret_cast<quint32_le *>(b + currentOffset); + + // write methods + for (int i = 0; i < t.strings.size(); ++i) + strings[i] = t.strings.at(i); + strings += t.strings.size(); + + for (int i = 0; i < t.rawStrings.size(); ++i) + strings[i] = t.rawStrings.at(i); + + static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); + if (showCode) { + qDebug() << "=== TemplateObject size" << tmpl->size; + for (uint i = 0; i < tmpl->size; ++i) { + qDebug() << " " << i << stringForIndex(tmpl->stringIndexAt(i)); + qDebug() << " raw: " << stringForIndex(tmpl->rawStringIndexAt(i)); + } + qDebug(); + } +} + void QV4::Compiler::JSUnitGenerator::writeBlock(char *b, QV4::Compiler::Context *irBlock) const { QV4::CompiledData::Block *block = reinterpret_cast<QV4::CompiledData::Block *>(b); @@ -580,6 +615,10 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp unit.offsetToClassTable = nextOffset; nextOffset += unit.classTableSize * sizeof(uint); + unit.templateObjectTableSize = module->templateObjects.size(); + unit.offsetToTemplateObjectTable = nextOffset; + nextOffset += unit.templateObjectTableSize * sizeof(uint); + unit.blockTableSize = module->blocks.size(); unit.offsetToBlockTable = nextOffset; nextOffset += unit.blockTableSize * sizeof(uint); @@ -658,6 +697,14 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp } blockAndFunctionOffsets += module->classes.size(); + for (int i = 0; i < module->templateObjects.size(); ++i) { + const TemplateObject &t = module->templateObjects.at(i); + blockAndFunctionOffsets[i] = nextOffset; + + nextOffset += QV4::CompiledData::TemplateObject::calculateSize(t.strings.size()); + } + blockAndFunctionOffsets += module->templateObjects.size(); + for (int i = 0; i < module->blocks.size(); ++i) { Context *c = module->blocks.at(i); blockAndFunctionOffsets[i] = nextOffset; diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index c4c886ffad..2f5889ab53 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -73,6 +73,7 @@ struct JSClassMember; namespace Compiler { struct Class; +struct TemplateObject; struct Q_QML_PRIVATE_EXPORT StringTableGenerator { StringTableGenerator(); @@ -137,6 +138,7 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator { QV4::CompiledData::Unit *generateUnit(GeneratorOption option = GenerateWithStringTable); void writeFunction(char *f, Context *irFunction) const; void writeClass(char *f, const Class &c); + void writeTemplateObject(char *f, const TemplateObject &o); void writeBlock(char *f, Context *irBlock) const; StringTableGenerator stringTable; diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index d36ef0f447..328715da07 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -99,6 +99,14 @@ struct Class { QVector<Method> methods; }; +struct TemplateObject { + QVector<uint> strings; + QVector<uint> rawStrings; + bool operator==(const TemplateObject &other) { + return strings == other.strings && rawStrings == other.rawStrings; + } +}; + struct ExportEntry { QString exportName; @@ -133,6 +141,7 @@ struct Module { QList<Context *> functions; QList<Context *> blocks; QVector<Class> classes; + QVector<TemplateObject> templateObjects; Context *rootContext; QString fileName; QString finalUrl; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index eed8ffe6b8..6edf5a4ae7 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -712,6 +712,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_BEGIN_INSTR(ThrowOnNullOrUndefined) MOTH_END_INSTR(ThrowOnNullOrUndefined) + MOTH_BEGIN_INSTR(GetTemplateObject) + d << index; + MOTH_END_INSTR(GetTemplateObject) + MOTH_BEGIN_INSTR(LoadQmlContext) d << dumpRegister(result, nFormals); MOTH_END_INSTR(LoadQmlContext) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 2b1660ee58..2ca8f692b8 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -198,6 +198,7 @@ QT_BEGIN_NAMESPACE #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) #define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count) #define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0) +#define INSTR_GetTemplateObject(op) INSTRUCTION(op, GetTemplateObject, 1, index) #define INSTR_TailCall(op) INSTRUCTION(op, TailCall, 4, func, thisObject, argc, argv) #define FOR_EACH_MOTH_INSTR_ALL(F) \ @@ -339,6 +340,7 @@ QT_BEGIN_NAMESPACE F(PopScriptContext) \ F(InitializeBlockDeadTemporalZone) \ F(ThrowOnNullOrUndefined) \ + F(GetTemplateObject) \ F(TailCall) \ F(Debug) \ diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 62c0f5d81b..969dd51433 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -356,13 +356,36 @@ */ /*! - \fn int qmlRegisterInterface(const char *typeName) - \relates QQmlEngine + \fn int qmlRegisterInterface(const char *typeName) + \relates QQmlEngine - This template function registers the C++ type in the QML system - under the name \a typeName. + This template function registers the C++ type in the QML system + under the name \a typeName. - Returns the QML type id. + Types registered as an interface with the engine should also + declare themselves as an interface with the + \l {The Meta-Object System}{meta object system}. For example: + + \code + struct FooInterface + { + public: + virtual ~FooInterface(); + virtual void doSomething() = 0; + }; + + Q_DECLARE_INTERFACE(FooInterface, "org.foo.FooInterface") + \endcode + + When registered with the QML engine in this way, they can be used as + property types: + + Q_PROPERTY(FooInterface *foo READ foo WRITE setFoo) + + When you assign a \l QObject sub-class to this property, the QML engine does + the interface cast to \c FooInterface* automatically. + + Returns the QML type id. */ /*! diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 6bc1ca6e45..098bbfc6c6 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -992,6 +992,15 @@ void BaselineJIT::generate_ThrowOnNullOrUndefined() as->checkException(); } +void BaselineJIT::generate_GetTemplateObject(int index) +{ + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passInt32AsArg(index, 1); + as->passFunctionAsArg(0); + BASELINEJIT_GENERATE_RUNTIME_CALL(RuntimeHelpers::getTemplateObject, CallResultDestination::InAccumulator); + as->checkException(); +} void BaselineJIT::startInstruction(Instr::Type /*instr*/) { diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h index 47ad274d23..98d23f4517 100644 --- a/src/qml/jit/qv4baselinejit_p.h +++ b/src/qml/jit/qv4baselinejit_p.h @@ -215,6 +215,7 @@ public: void generate_LoadQmlImportedScripts(int result) override; void generate_InitializeBlockDeadTemporalZone(int firstReg, int count) override; void generate_ThrowOnNullOrUndefined() override; + void generate_GetTemplateObject(int index) override; void startInstruction(Moth::Instr::Type instr) override; void endInstruction(Moth::Instr::Type instr) override; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b576bb4d87..13244fdd95 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -595,6 +595,12 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu return Encode(x + y); } +ReturnedValue RuntimeHelpers::getTemplateObject(Function *function, int index) +{ + return function->compilationUnit->templateObjectAt(index)->asReturnedValue(); +} + + void Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) { Scope scope(engine); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 72af90d1dc..2be3ebf012 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -114,6 +114,8 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { static Bool strictEqual(const Value &x, const Value &y); static ReturnedValue addHelper(ExecutionEngine *engine, const Value &left, const Value &right); + + static ReturnedValue getTemplateObject(Function *function, int index); }; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 1cca50f6c1..5208894934 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -1378,6 +1378,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, } MOTH_END_INSTR(ThrowOnNullOrUndefined) + MOTH_BEGIN_INSTR(GetTemplateObject) + acc = RuntimeHelpers::getTemplateObject(function, index); + MOTH_END_INSTR(GetTemplateObject) + MOTH_BEGIN_INSTR(Debug) #if QT_CONFIG(qml_debug) STORE_IP(); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index ba8d5831ad..11806a89a0 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -2244,6 +2244,9 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) return Unknown; } +/*! + See qmlRegisterInterface() for information about when this will return true. +*/ bool QQmlMetaType::isInterface(int userType) { QMutexLocker lock(metaTypeDataLock()); diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc index 0a89066d47..15ea33d06a 100644 --- a/src/qmltest/doc/src/qtquicktest-index.qdoc +++ b/src/qmltest/doc/src/qtquicktest-index.qdoc @@ -181,6 +181,8 @@ class Setup : public QObject { + Q_OBJECT + public: Setup() {} @@ -196,6 +198,15 @@ #include "tst_mytest.moc" \endcode + The \c .moc include is based on the file name of the \c .cpp file. + For example, in the example above, the \c .cpp file is named + \c tst_mytest.cpp. If the file was named \c MyTest.cpp, the include would + be: + + \code + #include "MyTest.moc" + \endcode + \section1 Licenses Qt Quick Tests is available under commercial licenses from \l{The Qt Company}. diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp index d51419a275..f32b32491b 100644 --- a/src/quick/items/qquickopenglshadereffectnode.cpp +++ b/src/quick/items/qquickopenglshadereffectnode.cpp @@ -366,6 +366,7 @@ class QQuickOpenGLShaderEffectMaterialCache : public QObject public: static QQuickOpenGLShaderEffectMaterialCache *get(bool create = true) { QOpenGLContext *ctx = QOpenGLContext::currentContext(); + Q_ASSERT(ctx); QQuickOpenGLShaderEffectMaterialCache *me = ctx->findChild<QQuickOpenGLShaderEffectMaterialCache *>(QStringLiteral("__qt_ShaderEffectCache"), Qt::FindDirectChildrenOnly); if (!me && create) { me = new QQuickOpenGLShaderEffectMaterialCache(); diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 025acefec2..f6d4e7ed49 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -192,7 +192,8 @@ void QQuickRenderControlPrivate::windowDestroyed() QQuickWindowPrivate::get(window)->animationController = nullptr; #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) - QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); + if (QOpenGLContext::currentContext()) + QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); #endif window = nullptr; diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 3d579fde46..2e91bafa7c 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -334,7 +334,8 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) qCDebug(QSG_LOG_RENDERLOOP, "cleanup without an OpenGL context"); #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) - QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); + if (current) + QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); #endif d->cleanupNodesOnShutdown(); |