Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I2ed93c9d5fa8ec9b075112618a2535535591a0e8
This commit is contained in:
commit
b01a16ea74
|
@ -1866,6 +1866,7 @@ Item {
|
|||
else
|
||||
qtest_runFunction(prop, row)
|
||||
qtest_results.dataTag = ""
|
||||
qtest_results.skipped = false
|
||||
}
|
||||
if (!haveData) {
|
||||
if (datafunc === "init_data")
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
int index = _module->templateObjects.size();
|
||||
_module->templateObjects.append(obj);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return arrayTemp;
|
||||
Instruction::GetTemplateObject getTemplateObject;
|
||||
getTemplateObject.index = index;
|
||||
bytecodeGenerator->addInstruction(getTemplateObject);
|
||||
}
|
||||
|
||||
bool Codegen::visit(FunctionExpression *ast)
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) \
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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*/)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -567,16 +567,9 @@ language/expressions/prefix-increment/S11.4.4_A5_T3.js sloppyFails
|
|||
language/expressions/prefix-increment/S11.4.4_A5_T4.js sloppyFails
|
||||
language/expressions/prefix-increment/S11.4.4_A5_T5.js fails
|
||||
language/expressions/prefix-increment/S11.4.4_A6_T3.js fails
|
||||
language/expressions/tagged-template/cache-different-functions-same-site.js fails
|
||||
language/expressions/tagged-template/cache-eval-inner-function.js fails
|
||||
language/expressions/tagged-template/cache-same-site-top-level.js fails
|
||||
language/expressions/tagged-template/cache-same-site.js fails
|
||||
language/expressions/tagged-template/cache-eval-inner-function.js strictFails
|
||||
language/expressions/tagged-template/invalid-escape-sequences.js fails
|
||||
language/expressions/tagged-template/tco-member.js strictFails
|
||||
language/expressions/tagged-template/template-object-frozen-non-strict.js sloppyFails
|
||||
language/expressions/tagged-template/template-object-frozen-strict.js strictFails
|
||||
language/expressions/tagged-template/template-object.js fails
|
||||
language/expressions/template-literal/tv-null-character-escape-sequence.js fails
|
||||
language/function-code/each-param-has-own-non-shared-eval-scope.js sloppyFails
|
||||
language/function-code/each-param-has-own-scope.js sloppyFails
|
||||
language/function-code/eval-param-env-with-computed-key.js sloppyFails
|
||||
|
|
|
@ -494,7 +494,7 @@ void Test262Runner::writeTestExpectations()
|
|||
|
||||
static bool executeTest(const QByteArray &data, bool runAsModule = false, const QString &testCasePath = QString(), const QByteArray &harnessForModules = QByteArray())
|
||||
{
|
||||
QString testData = QString::fromUtf8(data);
|
||||
QString testData = QString::fromUtf8(data.constData(), data.size());
|
||||
|
||||
QV4::ExecutionEngine vm;
|
||||
|
||||
|
@ -514,7 +514,7 @@ static bool executeTest(const QByteArray &data, bool runAsModule = false, const
|
|||
QFile f(url.toLocalFile());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
QByteArray content = harnessForModules + f.readAll();
|
||||
module = vm.compileModule(url.toString(), QString::fromUtf8(content), QFileInfo(f).lastModified());
|
||||
module = vm.compileModule(url.toString(), QString::fromUtf8(content.constData(), content.length()), QFileInfo(f).lastModified());
|
||||
if (vm.hasException)
|
||||
break;
|
||||
vm.injectModule(module);
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtTest 1.1
|
||||
|
||||
TestCase {
|
||||
name: "Third"
|
||||
|
||||
function init_data() {
|
||||
return [
|
||||
{ tag: "init_0" },
|
||||
{ tag: "skip_1" },
|
||||
{ tag: "init_2" },
|
||||
{ tag: "skip_3" },
|
||||
{ tag: "init_4" },
|
||||
]
|
||||
}
|
||||
|
||||
function test_default_tags(data) {
|
||||
if (data.tag.startsWith("skip_"))
|
||||
skip("skip '" + data.tag + "' tag")
|
||||
}
|
||||
|
||||
function test_tags_data() {
|
||||
return [
|
||||
{ tag: "foo" },
|
||||
{ tag: "bar" },
|
||||
{ tag: "baz" },
|
||||
]
|
||||
}
|
||||
|
||||
function test_tags(data) {
|
||||
if (data.tag === "bar")
|
||||
skip("skip '" + data.tag + "' tag")
|
||||
}
|
||||
}
|
|
@ -56,7 +56,8 @@ void tst_TestFiltering::noFilters()
|
|||
QVERIFY(process.waitForFinished());
|
||||
|
||||
const QString output = process.readAll();
|
||||
QVERIFY(output.contains(QLatin1String("Totals: 10 passed")));
|
||||
QVERIFY(output.contains(QLatin1String("Totals: 17 passed")));
|
||||
QVERIFY(output.contains(QLatin1String(", 3 skipped")));
|
||||
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
if (!script) {
|
||||
const QString code = QString::fromUtf8(file.readAll());
|
||||
QByteArray ba = file.readAll();
|
||||
const QString code = QString::fromUtf8(ba.constData(), ba.length());
|
||||
file.close();
|
||||
|
||||
script.reset(new QV4::Script(ctx, QV4::Compiler::ContextType::Global, code, fn));
|
||||
|
|
Loading…
Reference in New Issue