diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-06-04 10:45:14 +0200 |
---|---|---|
committer | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-06-04 10:45:14 +0200 |
commit | 3ca5f33c8b9c273f0169ec4c11417328f8071e97 (patch) | |
tree | 155da80482fb4593ca074f7a1bf9b22d031dba4a /src/qml | |
parent | 5f4698c4e7952d64e78e3a06de5ac28d68415b19 (diff) | |
parent | b7a1bcd83a8f68185b617b860cef6f2d2d7c8d9b (diff) |
Merge remote-tracking branch 'gerrit/5.11' into wip/webassembly
Change-Id: I7556ac62fd8e1aeb99186c929f1225f02f9d2430
Diffstat (limited to 'src/qml')
26 files changed, 162 insertions, 148 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 4a1b27d7aa..8a1b3744ee 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -322,16 +322,16 @@ Document::Document(bool debugMode) { } -ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator) - : engine(engine) - , jsGenerator(unitGenerator) - , hasPragmaLibrary(false) +ScriptDirectivesCollector::ScriptDirectivesCollector(Document *doc) + : document(doc) + , engine(&doc->jsParserEngine) + , jsGenerator(&doc->jsGenerator) { } void ScriptDirectivesCollector::pragmaLibrary() { - hasPragmaLibrary = true; + document->jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; } void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column) @@ -342,7 +342,7 @@ void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; - imports << import; + document->imports << import; } void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) @@ -358,7 +358,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString & import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; - imports << import; + document->imports << import; } IRBuilder::IRBuilder(const QSet<QString> &illegalNames) @@ -2414,6 +2414,22 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO object->qmlSignals->append(s); } + for (uint i = 0; i < serializedObject->nEnums; ++i) { + const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i); + QmlIR::Enum *e = pool->New<QmlIR::Enum>(); + e->nameIndex = serializedEnum->nameIndex; + e->location = serializedEnum->location; + e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >(); + + for (uint i = 0; i < serializedEnum->nEnumValues; ++i) { + QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>(); + *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i); + e->enumValues->append(v); + } + + object->qmlEnums->append(e); + } + const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable(); for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) { QmlIR::Property *p = pool->New<QmlIR::Property>(); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index c2cf18e3c4..689b232b1c 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -462,14 +462,14 @@ struct Q_QML_PRIVATE_EXPORT Document static void removeScriptPragmas(QString &script); }; -struct Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives +class Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives { - ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator); - + QmlIR::Document *document; QQmlJS::Engine *engine; QV4::Compiler::JSUnitGenerator *jsGenerator; - QList<const QV4::CompiledData::Import *> imports; - bool hasPragmaLibrary; + +public: + ScriptDirectivesCollector(QmlIR::Document *doc); void pragmaLibrary() override; void importFile(const QString &jsfile, const QString &module, int lineNumber, int column) override; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index c281275da1..e831fd48f5 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2075,6 +2075,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, _context->functionIndex = _module->functions.count() - 1; _context->hasDirectEval |= (_context->compilationMode == EvalCode || _context->compilationMode == GlobalCode || _module->debugMode); // Conditional breakpoints are like eval in the function + if (_module->debugMode) // allow the debugger to see overwritten arguments + _context->argumentsCanEscape = true; // When a user writes the following QML signal binding: // onSignal: function() { doSomethingUsefull } diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h index f84a2c44e2..7b972c5d0d 100644 --- a/src/qml/debugger/qqmlprofilerdefinitions_p.h +++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h @@ -96,11 +96,6 @@ struct QQmlProfilerDefinitions { MaximumRangeType }; - enum BindingType { - QmlBinding, - MaximumBindingType - }; - enum PixmapEventType { PixmapSizeKnown, PixmapReferenceCountChanged, @@ -129,8 +124,6 @@ struct QQmlProfilerDefinitions { NumGUIThreadFrameTypes = MaximumSceneGraphFrameType - NumRenderThreadFrameTypes }; - typedef QV4::Profiling::MemoryType MemoryType; - enum ProfileFeature { ProfileJavaScript, ProfileMemory, @@ -162,26 +155,6 @@ struct QQmlProfilerDefinitions { MaximumInputEventType }; - - static ProfileFeature featureFromRangeType(RangeType range) - { - switch (range) { - case Painting: - return ProfilePainting; - case Compiling: - return ProfileCompiling; - case Creating: - return ProfileCreating; - case Binding: - return ProfileBinding; - case HandlingSignal: - return ProfileHandlingSignal; - case Javascript: - return ProfileJavaScript; - default: - return MaximumProfileFeature; - } - } }; QT_END_NAMESPACE diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index c3e16c4093..9786293e4c 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -62,7 +62,6 @@ namespace JIT { #define callHelper(x) PlatformAssemblerCommon::callRuntime(#x, reinterpret_cast<void *>(&x)) const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer; -const int IsIntegerConvertible_Shift = QV4::Value::IsIntegerConvertible_Shift; static ReturnedValue toNumberHelper(ReturnedValue v) { @@ -873,7 +872,7 @@ struct PlatformAssembler64 : PlatformAssemblerCommon Jump unopIntPath(std::function<Jump(void)> fastPath) { - urshift64(AccumulatorRegister, TrustedImm32(IsIntegerConvertible_Shift), ScratchRegister); + urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister); Jump accNotIntConvertible = branch32(NotEqual, TrustedImm32(1), ScratchRegister); // both integer diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index b97468ab7b..348ddb25d9 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -409,7 +409,7 @@ bool QJSValue::isObject() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - return val->as<Object>(); + return val->as<QV4::Object>(); } /*! @@ -649,7 +649,7 @@ QVariant QJSValue::toVariant() const QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch); Q_ASSERT(val); - if (Object *o = val->as<Object>()) + if (QV4::Object *o = val->as<QV4::Object>()) return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false); if (String *s = val->stringValue()) @@ -849,7 +849,7 @@ QJSValue QJSValue::prototype() const if (!engine) return QJSValue(); QV4::Scope scope(engine); - ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>()); + ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<QV4::Object>()); if (!o) return QJSValue(); ScopedObject p(scope, o->prototype()); @@ -931,7 +931,7 @@ static bool js_equal(const QString &string, const QV4::Value &value) return RuntimeHelpers::stringToNumber(string) == value.asDouble(); if (value.isBoolean()) return RuntimeHelpers::stringToNumber(string) == double(value.booleanValue()); - if (Object *o = value.objectValue()) { + if (QV4::Object *o = value.objectValue()) { Scope scope(o->engine()); ScopedValue p(scope, RuntimeHelpers::toPrimitive(value, PREFERREDTYPE_HINT)); return js_equal(string, p); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index bc9b3013d1..5bbe312146 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -55,7 +55,7 @@ #include <wtf/MathExtras.h> -#ifdef Q_OS_LINUX +#if defined(Q_OS_LINUX) && QT_CONFIG(timezone) /* See QTBUG-56899. Although we don't (yet) have a proper way to reset the system zone, the code below, that uses QTimeZone::systemTimeZone(), works diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 5521633db7..835933c043 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -769,16 +769,19 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const QString CppStackFrame::source() const { - return v4Function->sourceFile(); + return v4Function ? v4Function->sourceFile() : QString(); } QString CppStackFrame::function() const { - return v4Function->name()->toQString(); + return v4Function ? v4Function->name()->toQString() : QString(); } int CppStackFrame::lineNumber() const { + if (!v4Function) + return -1; + auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) { return entry.codeOffset < offset; }; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 83e861138b..6fca9ecd45 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -112,6 +112,11 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr internalClass = engine->internalClasses[EngineBase::Class_CallContext]; + // first locals + const quint32_le *localsIndices = compiledFunction->localsTable(); + for (quint32 i = 0; i < compiledFunction->nLocals; ++i) + internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); + Scope scope(engine); ScopedString arg(scope); for (const QString ¶meterName : parameterNames) { @@ -119,10 +124,6 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr internalClass = internalClass->addMember(arg, Attr_NotConfigurable); } nFormals = parameters.size(); - - const quint32_le *localsIndices = compiledFunction->localsTable(); - for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 9b13d4e341..1fa4bae049 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -101,7 +101,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } # define V4_ENABLE_JIT # endif #elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8) -# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) +# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY) # define V4_ENABLE_JIT # endif //#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX) diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 9da854e7d7..3bfcf358bf 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -533,6 +533,8 @@ void InternalClass::updateInternalClassIdRecursive() id = engine->newInternalClassId(); for (auto &t : transitions) { Q_ASSERT(t.lookup); + if (t.flags == InternalClassTransition::VTableChange || t.flags == InternalClassTransition::PrototypeChange) + continue; t.lookup->updateInternalClassIdRecursive(); } } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 816c259b9b..d63d42478a 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -102,10 +102,10 @@ QPair<QObject *, int> QObjectMethod::extractQtMethod(const QV4::FunctionObject * return qMakePair((QObject *)nullptr, -1); } -static QPair<QObject *, int> extractQtSignal(const Value &value) +static QPair<QObject *, int> extractQtSignal(const QV4::Value &value) { if (value.isObject()) { - QV4::ExecutionEngine *v4 = value.as<Object>()->engine(); + QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine(); QV4::Scope scope(v4); QV4::ScopedFunctionObject function(scope, value); if (function) @@ -1106,7 +1106,7 @@ struct CallArgument { inline void *dataPtr(); inline void initAsType(int type); - inline void fromValue(int type, ExecutionEngine *, const Value &); + inline void fromValue(int type, ExecutionEngine *, const QV4::Value &); inline ReturnedValue toValue(ExecutionEngine *); private: @@ -1304,7 +1304,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType) return 10; } } - } else if (const Object *obj = actual.as<Object>()) { + } else if (const QV4::Object *obj = actual.as<QV4::Object>()) { if (obj->as<QV4::VariantObject>()) { if (conversionType == qMetaTypeId<QVariant>()) return 0; @@ -1720,7 +1720,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q || callType == qMetaTypeId<std::vector<QUrl>>() || callType == qMetaTypeId<std::vector<QModelIndex>>()) { queryEngine = true; - const QV4::Object* object = value.as<Object>(); + const QV4::Object* object = value.as<QV4::Object>(); if (callType == qMetaTypeId<std::vector<int>>()) { stdVectorIntPtr = nullptr; fromContainerValue<std::vector<int>>(object, callType, &CallArgument::stdVectorIntPtr, queryEngine); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 0211ad1011..9729228511 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1408,7 +1408,7 @@ ReturnedValue Runtime::method_mod(const Value &left, const Value &right) { TRACE2(left, right); - if (Value::integerCompatible(left, right) && right.integerValue() != 0) { + if (Value::integerCompatible(left, right) && left.integerValue() > 0 && right.integerValue() > 0) { int intRes = left.integerValue() % right.integerValue(); if (intRes != 0 || left.integerValue() >= 0) return Encode(intRes); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index e5a02fdc22..61176b3706 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -200,7 +200,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("trim"), method_trim); } -static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject) +static Heap::String *thisAsString(ExecutionEngine *v4, const QV4::Value *thisObject) { if (String *s = thisObject->stringValue()) return s->d(); @@ -209,7 +209,7 @@ static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject) return thisObject->toString(v4); } -static QString getThisString(ExecutionEngine *v4, const Value *thisObject) +static QString getThisString(ExecutionEngine *v4, const QV4::Value *thisObject) { if (String *s = thisObject->stringValue()) return s->toQString(); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 6adb25f964..fe7c2bd654 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -345,7 +345,7 @@ static struct InstrCount { if (engine->hasException) \ goto catchException -static inline Heap::CallContext *getScope(Value *stack, int level) +static inline Heap::CallContext *getScope(QV4::Value *stack, int level) { Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d(); while (level > 0) { @@ -362,7 +362,7 @@ static inline const QV4::Value &constant(Function *function, int index) } -static bool compareEqual(Value lhs, Value rhs) +static bool compareEqual(QV4::Value lhs, QV4::Value rhs) { redo: if (lhs.asReturnedValue() == rhs.asReturnedValue()) @@ -376,22 +376,22 @@ static bool compareEqual(Value lhs, Value rhs) } switch (lt) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (lhs.isUndefined()) return rhs.isNullOrUndefined(); Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: // LHS: Managed switch (rt) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (rhs.isUndefined()) return false; Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: { + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: { // RHS: Managed Heap::Base *l = lhs.m(); Heap::Base *r = rhs.m(); @@ -409,12 +409,12 @@ static bool compareEqual(Value lhs, Value rhs) } return false; } - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return false; - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: rhs = Primitive::fromDouble(rhs.int_32()); // fall through default: // double @@ -424,22 +424,22 @@ static bool compareEqual(Value lhs, Value rhs) lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); } goto redo; - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return rhs.isNull(); - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: switch (rt) { - case Value::QT_ManagedOrUndefined: - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: - case Value::QT_Empty: - case Value::QT_Null: + case QV4::Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_Empty: + case QV4::Value::QT_Null: Q_UNREACHABLE(); - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: return lhs.int_32() == rhs.int_32(); default: // double return lhs.int_32() == rhs.doubleValue(); @@ -450,29 +450,29 @@ static bool compareEqual(Value lhs, Value rhs) } } -static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) +static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs) { redo: switch (lhs.quickType()) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (lhs.isUndefined()) return false; Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: // LHS: Managed if (lhs.m()->vtable()->isString) return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs; accumulator = lhs; lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT)); goto redo; - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return false; - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: return lhs.int_32() == rhs; default: // double return lhs.doubleValue() == rhs; @@ -500,11 +500,11 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) } \ } while (false) -QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) +QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObject, const QV4::Value *argv, int argc) { qt_v4ResolvePendingBreakpointsHook(); ExecutionEngine *engine; - Value *stack; + QV4::Value *stack; CppStackFrame frame; frame.originalArguments = argv; frame.originalArgumentsCount = argc; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 5dd3278b4c..3dcfa92416 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -536,7 +536,7 @@ QQmlContextData::QQmlContextData() QQmlContextData::QQmlContextData(QQmlContext *ctxt) : engine(nullptr), isInternal(false), isJSContext(false), isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false), - publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1), + stronglyReferencedByParent(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1), contextObject(nullptr), nextChild(nullptr), prevChild(nullptr), expressions(nullptr), contextObjects(nullptr), idValues(nullptr), idValueCount(0), componentAttached(nullptr) @@ -577,7 +577,10 @@ void QQmlContextData::invalidate() while (childContexts) { Q_ASSERT(childContexts != this); - childContexts->invalidate(); + if (childContexts->stronglyReferencedByParent && !--childContexts->refCount) + childContexts->destroy(); + else + childContexts->invalidate(); } if (prevChild) { @@ -672,12 +675,16 @@ void QQmlContextData::destroy() delete this; } -void QQmlContextData::setParent(QQmlContextData *p) +void QQmlContextData::setParent(QQmlContextData *p, bool stronglyReferencedByParent) { if (p == parent) return; if (p) { + Q_ASSERT(!parent); parent = p; + this->stronglyReferencedByParent = stronglyReferencedByParent; + if (stronglyReferencedByParent) + ++refCount; // balanced in QQmlContextData::invalidate() engine = p->engine; nextChild = p->childContexts; if (nextChild) nextChild->prevChild = &nextChild; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 5dfee48848..290b7fc7ee 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -126,7 +126,7 @@ public: QQmlContextData *parent = nullptr; QQmlEngine *engine; - void setParent(QQmlContextData *); + void setParent(QQmlContextData *, bool stronglyReferencedByParent = false); void refreshExpressions(); void addObject(QObject *); @@ -144,7 +144,8 @@ public: quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name quint32 hasEmittedDestruction:1; quint32 isRootObjectInCreation:1; - quint32 dummy:26; + quint32 stronglyReferencedByParent:1; + quint32 dummy:25; QQmlContext *publicContext; // The incubator that is constructing this context if any diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7e11177caa..b27bf3779a 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1196,6 +1196,8 @@ void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) support. The factory must be set before executing the engine. + + \note QQmlEngine does not take ownership of the factory. */ void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory) { diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 8fda7f6f77..d842a7795f 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -424,7 +424,7 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm d->version_min = type.versionMinor; d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; - d->extraData.sd->singletonInstanceInfo->url = type.url; + d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); } @@ -477,7 +477,7 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm d->version_maj = type.versionMajor; d->version_min = type.versionMinor; - d->extraData.fd->url = type.url; + d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); } QQmlType::QQmlType() @@ -1710,7 +1710,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); return dtype; } @@ -1731,7 +1731,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); return dtype; } @@ -2253,8 +2253,9 @@ QQmlType QQmlMetaType::qmlType(int userType) Returns null if no such type is registered. */ -QQmlType QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */) +QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports /* = false */) { + const QUrl url = QQmlTypeLoader::normalize(unNormalizedUrl); QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index cd7afc8a01..51bf485a3e 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -96,7 +96,7 @@ public: static QQmlType qmlType(const QMetaObject *); static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); static QQmlType qmlType(int); - static QQmlType qmlType(const QUrl &url, bool includeNonFileImports = false); + static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false); static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 7051fb51da..5aaf79c9e5 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1217,9 +1217,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } ddata = QQmlData::get(instance, /*create*/true); - ddata->lineNumber = obj->location.line; - ddata->columnNumber = obj->location.column; } + ddata->lineNumber = obj->location.line; + ddata->columnNumber = obj->location.column; ddata->setImplicitDestructible(); if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation) { diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 1cab827b9f..f4c612b187 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -358,9 +358,8 @@ qreal QQmlDataBlob::progress() const /*! Returns the physical url of the data. Initially this is the same as -finalUrl(), but if a network redirect happens while fetching the data, this url -is updated to reflect the new location. Also, if a URL interceptor is set, it -will work on this URL and leave finalUrl() alone. +finalUrl(), but if a URL interceptor is set, it will work on this URL +and leave finalUrl() alone. \sa finalUrl() */ @@ -381,8 +380,12 @@ QString QQmlDataBlob::urlString() const Returns the logical URL to be used for resolving further URLs referred to in the code. -This is the blob url passed to the constructor. If a network redirect -happens while fetching the data, this url remains the same. +This is the blob url passed to the constructor. If a URL interceptor rewrites +the URL, this one stays the same. If a network redirect happens while fetching +the data, this url is updated to reflect the new location. Therefore, if both +an interception and a redirection happen, the final url will indirectly +incorporate the result of the interception, potentially breaking further +lookups. \sa url() */ @@ -1184,15 +1187,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirect.isValid()) { QUrl url = reply->url().resolved(redirect.toUrl()); - blob->m_url = url; - blob->m_urlString.clear(); + blob->m_finalUrl = url; + blob->m_finalUrlString.clear(); QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url)); QObject *nrp = m_thread->networkReplyProxy(); QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished())); m_networkReplies.insert(reply, blob); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString())); + qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->finalUrlString())); #endif return; } @@ -1648,14 +1651,24 @@ QQmlImportDatabase *QQmlTypeLoader::importDatabase() const return &QQmlEnginePrivate::get(engine())->importDatabase; } +QUrl QQmlTypeLoader::normalize(const QUrl &unNormalizedUrl) +{ + QUrl normalized(unNormalizedUrl); + if (normalized.scheme() == QLatin1String("qrc")) + normalized.setHost(QString()); // map qrc:///a.qml to qrc:/a.qml + return normalized; +} + /*! Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached. */ -QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) +QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode) { - Q_ASSERT(!url.isRelative() && - (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() || - !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url)))); + Q_ASSERT(!unNormalizedUrl.isRelative() && + (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() || + !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl)))); + + const QUrl url = normalize(unNormalizedUrl); LockHolder<QQmlTypeLoader> holder(this); @@ -1713,11 +1726,13 @@ QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, M /*! Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached. */ -QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url) +QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl) { - Q_ASSERT(!url.isRelative() && - (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() || - !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url)))); + Q_ASSERT(!unNormalizedUrl.isRelative() && + (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() || + !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl)))); + + const QUrl url = normalize(unNormalizedUrl); LockHolder<QQmlTypeLoader> holder(this); @@ -1833,15 +1848,7 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) if (*value) absoluteFilePath = path; } else { - bool exists = false; -#ifdef Q_OS_UNIX - struct stat statBuf; - // XXX Avoid encoding entire path. Should store encoded dirpath in cache - if (::stat(QFile::encodeName(path).constData(), &statBuf) == 0) - exists = S_ISREG(statBuf.st_mode); -#else - exists = QFile::exists(path); -#endif + bool exists = QFile::exists(path); fileSet->insert(fileName, new bool(exists)); if (exists) absoluteFilePath = path; @@ -3010,7 +3017,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) return; } - QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator); + QmlIR::ScriptDirectivesCollector collector(&irUnit); QList<QQmlError> errors; QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile( @@ -3026,9 +3033,6 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) unit.adopt(new QV4::CompiledData::CompilationUnit); } irUnit.javaScriptCompilationUnit = unit; - irUnit.imports = collector.imports; - if (collector.hasPragmaLibrary) - irUnit.jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit); diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5988632547..e75719866d 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -305,10 +305,12 @@ public: QQmlImportDatabase *importDatabase() const; - QQmlTypeData *getType(const QUrl &url, Mode mode = PreferSynchronous); + static QUrl normalize(const QUrl &unNormalizedUrl); + + QQmlTypeData *getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous); QQmlTypeData *getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous); - QQmlScriptBlob *getScript(const QUrl &); + QQmlScriptBlob *getScript(const QUrl &unNormalizedUrl); QQmlQmldirData *getQmldir(const QUrl &); QString absoluteFilePath(const QString &path); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 9e7c84011b..221754a29a 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1697,7 +1697,7 @@ ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value * QString scriptName = frame->source(); - int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), -1); + int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), 0); QString message = name + QLatin1String(": ") + QString::number(value); QMessageLogger(qPrintable(scriptName), frame->lineNumber(), diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 44166e4aa8..eb02e8045a 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -874,10 +874,11 @@ void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem) void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status) { - Q_Q(QQmlDelegateModel); if (!isDoneIncubating(status)) return; + const QList<QQmlError> incubationTaskErrors = incubationTask->errors(); + QQmlDelegateModelItem *cacheItem = incubationTask->incubating; cacheItem->incubationTask = nullptr; incubationTask->incubating = nullptr; @@ -891,7 +892,7 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba emitCreatedItem(incubationTask, cacheItem->object); cacheItem->releaseObject(); } else if (status == QQmlIncubator::Error) { - qmlWarning(q, m_delegate->errors()) << "Error creating delegate"; + qmlWarning(m_delegate, incubationTaskErrors + m_delegate->errors()) << "Error creating delegate"; } if (!cacheItem->isObjectReferenced()) { @@ -988,7 +989,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ if (QQmlAdaptorModelProxyInterface *proxy = qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) { ctxt = new QQmlContextData; - ctxt->setParent(cacheItem->contextData); + ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true); ctxt->contextObject = proxy->proxiedObject(); } } diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index c4e33d572d..877968faf4 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1463,8 +1463,8 @@ void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCo QQmlData *ddata = QQmlData::get(object(), /*create*/false); if (!ddata) return; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine(m_model)); - if (!ep) + // There's nothing to emit if we're a list model in a worker thread. + if (!qmlEngine(m_model)) return; for (int i = 0; i < roleCount; ++i) { const int changedRole = changedRoles[i]; |