aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/testlib/TestCase.qml1
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp3
-rw-r--r--src/qml/compiler/qv4codegen.cpp78
-rw-r--r--src/qml/compiler/qv4codegen_p.h2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp34
-rw-r--r--src/qml/compiler/qv4compileddata_p.h42
-rw-r--r--src/qml/compiler/qv4compiler.cpp53
-rw-r--r--src/qml/compiler/qv4compiler_p.h2
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h9
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc33
-rw-r--r--src/qml/jit/qv4baselinejit.cpp9
-rw-r--r--src/qml/jit/qv4baselinejit_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp6
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp3
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc11
-rw-r--r--src/quick/items/qquickopenglshadereffectnode.cpp1
-rw-r--r--src/quick/items/qquickrendercontrol.cpp3
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp3
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations9
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp4
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml62
-rw-r--r--tests/auto/quicktest/testfiltering/tst_testfiltering.cpp3
-rw-r--r--tools/qmljs/qmljs.cpp3
27 files changed, 299 insertions, 88 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();
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index d51b45b75c..81f9318cdc 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -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
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
index a16f2414b0..cbe3be2e70 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
+++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
@@ -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);
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml
new file mode 100644
index 0000000000..6e26d8171b
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_third.qml
@@ -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")
+ }
+}
diff --git a/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
index 72bb8f02b7..8817adb3bc 100644
--- a/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
+++ b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
@@ -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);
}
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index 56d4a7d383..4b581fff05 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -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));