aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-24 01:00:07 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-24 01:00:07 +0100
commitdf8784fa1fc4792007393ea995756c2d490691d7 (patch)
treed4b8d6bdc855e4045c39f7710f206b7cfcf3d493
parentb799e061a3cbf995ac7c88b315f5916e3a687162 (diff)
parent5246b910771e0dd824b4eea7c5245e5f9f3a63f0 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
-rw-r--r--src/particles/particles.pro2
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc2
-rw-r--r--src/qml/doc/src/qmltypereference.qdoc19
-rw-r--r--src/qml/jsapi/qjsvalue.cpp2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp18
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4generatorobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4mapobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4object.cpp15
-rw-r--r--src/qml/jsruntime/qv4object_p.h2
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h9
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4setobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp10
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/qqmlimport.cpp29
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/quick/items/qquicktext.cpp26
-rw-r--r--src/quick/items/qquicktext_p_p.h1
-rw-r--r--src/quick/items/qquicktextedit.cpp15
-rw-r--r--src/quick/items/qquicktextnode.cpp2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp27
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h2
-rw-r--r--src/quick/quick.pro2
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations5
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Composite.qml5
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Singleton.qml6
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/qmldir4
-rw-r--r--tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp17
-rw-r--r--tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton1.qml6
-rw-r--r--tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton2.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Singleton.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton1.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton2.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/multisingletonuser.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/singletonuser.qml6
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp56
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp40
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp43
-rw-r--r--tests/auto/quick/qquicktext/data/contentHeight.qml7
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp14
-rw-r--r--tools/qmlscene/main.cpp16
49 files changed, 449 insertions, 87 deletions
diff --git a/src/particles/particles.pro b/src/particles/particles.pro
index ab1c854253..6a3fb1bdc4 100644
--- a/src/particles/particles.pro
+++ b/src/particles/particles.pro
@@ -6,7 +6,7 @@ CONFIG += internal_module
QT = core-private gui-private qml-private quick-private
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
-win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
+msvc:DEFINES *= _CRT_SECURE_NO_WARNINGS
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
exists("qqml_enable_gcov") {
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index eba1efd51f..171b2b6a11 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -91,7 +91,7 @@ when passed from C++ to QML and vice-versa:
\li QFont
\li \l font
\row
- \li QDate
+ \li QDateTime
\li \l date
\row
\li QPoint, QPointF
diff --git a/src/qml/doc/src/qmltypereference.qdoc b/src/qml/doc/src/qmltypereference.qdoc
index 79bfdc7042..ae36ebbcc9 100644
--- a/src/qml/doc/src/qmltypereference.qdoc
+++ b/src/qml/doc/src/qmltypereference.qdoc
@@ -91,10 +91,17 @@ provided:
The \c date type refers to a date value, including the time of the day.
-To create a \c date value, specify it as a "YYYY-MM-DD" string:
+To create a \c date value, specify it as a "YYYY-MM-DDThh:mm:ss.zzzZ" string.
+(The T is literal, YYYY is a full year number, MM and DD are month and day
+numbers, hh, mm and ss are hours, minutes and seconds, with .zzz as
+milliseconds and Z as time-zone offset. The T and following time are optional.
+If they are omitted, the date is handled as the start of UTC's day, which
+falls on other dates in some time-zones. When T is included, the :ss.zzz or
+just .zzz part can be omitted. With or without those, the zone offset can be
+omitted, in which case local time is used.) For example:
\qml
-MyDatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" }
+MyDatePicker { minDate: "2000-01-01 0:0"; maxDate: "2020-12-31 23:59" }
\endqml
To read a date value returned from a C++ extension class, use
@@ -102,7 +109,13 @@ To read a date value returned from a C++ extension class, use
When integrating with C++, note that any QDate or QDateTime value
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
-converted into a \c date value, and vice-versa.
+converted into a \c date value, and vice-versa. Note, however, that
+converting a QDate will result in UTC's start of the day, which falls on
+a different date in some other time-zones. It is usually more robust
+to convert the QDate via a QDateTime explicitly, specifying local-time
+or a relevant time-zone and selecting a time of day (such as noon)
+that reliably exists (daylight-savings transitions skip an hour, near
+one end or the other of a day).
This basic type is provided by the QML language. It can be implicitly converted
to a \l{QtQml::Date}{Date} object.
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b3ae630a95..225a4443d9 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -80,7 +80,7 @@
used to test if a value is of a certain type. The methods named
toT() (e.g. toBool(), toString()) can be used to convert a
QJSValue to another type. You can also use the generic
- QJSValue_cast() function.
+ qjsvalue_cast() function.
Object values have zero or more properties which are themselves
QJSValues. Use setProperty() to set a property of an object, and
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 2e7c994550..8637db3dfd 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -60,11 +60,13 @@ void Heap::ArrayCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Array"));
}
-ReturnedValue ArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue ArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *v4 = static_cast<const ArrayCtor *>(f)->engine();
Scope scope(v4);
ScopedArrayObject a(scope, v4->newArrayObject());
+ if (newTarget)
+ a->setProtoFromNewTarget(newTarget);
uint len;
if (argc == 1 && argv[0].isNumber()) {
bool ok;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 04ec7e1607..c959b71bc6 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -70,7 +70,7 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget);
static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 075ee1657e..3e5f51c302 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -50,10 +50,18 @@ void Heap::BooleanCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Boolean"));
}
-ReturnedValue BooleanCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *)
+ReturnedValue BooleanCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *newTarget)
{
+ auto v4 = that->engine();
bool n = argc ? argv[0].toBoolean() : false;
- return Encode(that->engine()->newBooleanObject(n));
+
+ ReturnedValue o = Encode(v4->newBooleanObject(n));
+ if (!newTarget)
+ return o;
+ Scope scope(v4);
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
ReturnedValue BooleanCtor::virtualCall(const FunctionObject *, const Value *, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index d8d428237b..21c6a5d06b 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -755,16 +755,16 @@ void Heap::DateCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Date"));
}
-ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *)
+ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *newTarget)
{
- ExecutionEngine *e = that->engine();
+ ExecutionEngine *v4 = that->engine();
double t = 0;
if (argc == 0)
t = currentTime();
else if (argc == 1) {
- Scope scope(e);
+ Scope scope(v4);
ScopedValue arg(scope, argv[0]);
if (DateObject *d = arg->as<DateObject>()) {
t = d->date();
@@ -772,7 +772,7 @@ ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, con
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
if (String *s = arg->stringValue())
- t = ParseString(s->toQString(), e->localTZA);
+ t = ParseString(s->toQString(), v4->localTZA);
else
t = TimeClip(arg->toNumber());
}
@@ -789,10 +789,16 @@ ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, con
if (year >= 0 && year <= 99)
year += 1900;
t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms));
- t = TimeClip(UTC(t, e->localTZA));
+ t = TimeClip(UTC(t, v4->localTZA));
}
- return Encode(e->newDateObject(Value::fromDouble(t)));
+ ReturnedValue o = Encode(v4->newDateObject(Value::fromDouble(t)));
+ if (!newTarget)
+ return o;
+ Scope scope(v4);
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
ReturnedValue DateCtor::virtualCall(const FunctionObject *m, const Value *, const Value *, int)
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 93cc55f8ad..dfe9d35194 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -276,7 +276,7 @@ QQmlRefPointer<CompiledData::CompilationUnit> FunctionCtor::parse(ExecutionEngin
return cg.generateCompilationUnit();
}
-ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *engine = f->engine();
@@ -286,7 +286,14 @@ ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, co
Function *vmf = compilationUnit->linkToEngine(engine);
ExecutionContext *global = engine->scriptContext();
- return Encode(FunctionObject::createScriptFunction(global, vmf));
+ ReturnedValue o = Encode(FunctionObject::createScriptFunction(global, vmf));
+
+ if (!newTarget)
+ return o;
+ Scope scope(engine);
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
// 15.3.1: This is equivalent to new Function(...)
diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp
index da87127e08..566db6fd4e 100644
--- a/src/qml/jsruntime/qv4generatorobject.cpp
+++ b/src/qml/jsruntime/qv4generatorobject.cpp
@@ -54,7 +54,7 @@ void Heap::GeneratorFunctionCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("GeneratorFunction"));
}
-ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *engine = f->engine();
@@ -64,7 +64,14 @@ ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObje
Function *vmf = compilationUnit->linkToEngine(engine);
ExecutionContext *global = engine->scriptContext();
- return Encode(GeneratorFunction::create(global, vmf));
+ ReturnedValue o = Encode(GeneratorFunction::create(global, vmf));
+
+ if (!newTarget)
+ return o;
+ Scope scope(engine);
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
// 15.3.1: This is equivalent to new Function(...)
diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp
index 7d53b36fcd..68741e7677 100644
--- a/src/qml/jsruntime/qv4mapobject.cpp
+++ b/src/qml/jsruntime/qv4mapobject.cpp
@@ -59,11 +59,14 @@ void Heap::MapCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Map"));
}
-ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *, bool weakMap)
+ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool weakMap)
{
Scope scope(f);
Scoped<MapObject> a(scope, scope.engine->memoryManager->allocate<MapObject>());
- if (weakMap) {
+ bool protoSet = false;
+ if (newTarget)
+ protoSet = a->setProtoFromNewTarget(newTarget);
+ if (!protoSet && weakMap) {
a->setPrototypeOf(scope.engine->weakMapPrototype());
scope.engine->memoryManager->registerWeakMap(a->d());
}
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 11ec53ced5..d26e888069 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -78,10 +78,18 @@ void Heap::NumberCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Number"));
}
-ReturnedValue NumberCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue NumberCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
+ auto v4 = f->engine();
double dbl = argc ? argv[0].toNumber() : 0.;
- return Encode(f->engine()->newNumberObject(dbl));
+
+ ReturnedValue o = Encode(f->engine()->newNumberObject(dbl));
+ if (!newTarget)
+ return o;
+ Scope scope(v4);
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
ReturnedValue NumberCtor::virtualCall(const FunctionObject *, const Value *, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index a7ede4627c..3d2d54f651 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -986,6 +986,21 @@ const FunctionObject *Object::speciesConstructor(Scope &scope, const FunctionObj
return static_cast<const FunctionObject *>(f);
}
+bool Object::setProtoFromNewTarget(const Value *newTarget)
+{
+ if (!newTarget || newTarget->isUndefined())
+ return false;
+
+ Q_ASSERT(newTarget->isFunctionObject());
+ Scope scope(this);
+ ScopedObject proto(scope, static_cast<const FunctionObject *>(newTarget)->protoProperty());
+ if (proto) {
+ setPrototypeOf(proto);
+ return true;
+ }
+ return false;
+}
+
DEFINE_OBJECT_VTABLE(ArrayObject);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 6753ebfcd4..ff47810994 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -373,6 +373,8 @@ public:
bool isArray() const;
const FunctionObject *speciesConstructor(Scope &scope, const FunctionObject *defaultConstructor) const;
+ bool setProtoFromNewTarget(const Value *newTarget);
+
protected:
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver,bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index a955e5eb6a..8450655334 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -364,7 +364,7 @@ void Heap::RejectWrapper::init()
}
-ReturnedValue PromiseCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue PromiseCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
Scope scope(f);
@@ -396,6 +396,9 @@ ReturnedValue PromiseCtor::virtualCallAsConstructor(const FunctionObject *f, con
a->d()->resolution.set(scope.engine, Value::fromReturnedValue(scope.engine->catchException()));
}
+ if (newTarget)
+ a->setProtoFromNewTarget(newTarget);
+
return a->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 8cdec2f6ee..9344a231ff 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -2226,9 +2226,7 @@ void QmlSignalHandler::initProto(ExecutionEngine *engine)
void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value)
{
- QV4::WeakValue v;
- v.set(value->internalClass->engine, value);
- QHash<QObject*, QV4::WeakValue>::insert(key, v);
+ QHash<QObject*, QV4::WeakValue>::operator[](key).set(value->internalClass->engine, value);
connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index be46245d5a..6465ee0fa6 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -290,7 +290,14 @@ public:
Iterator end() { return QHash<QObject*, QV4::WeakValue>::end(); }
void insert(QObject *key, Heap::Object *value);
- ReturnedValue value(QObject *key) const { return QHash<QObject*, QV4::WeakValue>::value(key).value(); }
+ ReturnedValue value(QObject *key) const
+ {
+ ConstIterator it = find(key);
+ return it == end()
+ ? QV4::WeakValue().value()
+ : it->value();
+ }
+
Iterator erase(Iterator it);
void remove(QObject *key);
void mark(QObject *key, MarkStack *markStack);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 4ef4fa2c9e..9df286065d 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -332,7 +332,13 @@ ReturnedValue RegExpCtor::virtualCallAsConstructor(const FunctionObject *fo, con
return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
}
- return Encode(scope.engine->newRegExpObject(regexp));
+ ReturnedValue o = Encode(scope.engine->newRegExpObject(regexp));
+
+ if (!newTarget)
+ return o;
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
ReturnedValue RegExpCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp
index 3c9b5031d1..088ecbe30d 100644
--- a/src/qml/jsruntime/qv4setobject.cpp
+++ b/src/qml/jsruntime/qv4setobject.cpp
@@ -59,11 +59,14 @@ void Heap::SetCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Set"));
}
-ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *, bool isWeak)
+ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool isWeak)
{
Scope scope(f);
Scoped<SetObject> a(scope, scope.engine->memoryManager->allocate<SetObject>());
- if (isWeak)
+ bool protoSet = false;
+ if (newTarget)
+ protoSet = a->setProtoFromNewTarget(newTarget);
+ if (!protoSet && isWeak)
a->setPrototypeOf(scope.engine->weakSetPrototype());
a->d()->isWeakSet = isWeak;
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 03f351b9e4..d0f6aff9d9 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -170,7 +170,7 @@ void Heap::StringCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("String"));
}
-ReturnedValue StringCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue StringCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *v4 = static_cast<const Object *>(f)->engine();
Scope scope(v4);
@@ -180,7 +180,13 @@ ReturnedValue StringCtor::virtualCallAsConstructor(const FunctionObject *f, cons
else
value = v4->newString();
CHECK_EXCEPTION();
- return Encode(v4->newStringObject(value));
+ ReturnedValue o = Encode(v4->newStringObject(value));
+
+ if (!newTarget)
+ return o;
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+ return obj->asReturnedValue();
}
ReturnedValue StringCtor::virtualCall(const FunctionObject *m, const Value *, const Value *argv, int argc)
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index a0af11b2da..94717a8f43 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -7,7 +7,7 @@ qtConfig(qml-network): \
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000
-win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
+msvc:DEFINES *= _CRT_SECURE_NO_WARNINGS
win32:!winrt:LIBS += -lshell32
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
@@ -47,7 +47,7 @@ exists("qqml_enable_gcov") {
}
# QTBUG-55238, disable new optimizer for MSVC 2015/Update 3.
-release:win32-msvc*:equals(QT_CL_MAJOR_VERSION, 19):equals(QT_CL_MINOR_VERSION, 00): \
+release:msvc:equals(QT_CL_MAJOR_VERSION, 19):equals(QT_CL_MINOR_VERSION, 00): \
greaterThan(QT_CL_PATCH_VERSION, 24212):QMAKE_CXXFLAGS += -d2SSAOptimizer-
QMAKE_DOCS = $$PWD/doc/qtqml.qdocconf
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index bc53b98b5b..e379d416fd 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -511,6 +511,20 @@ QList<QQmlImports::CompositeSingletonReference> QQmlImports::resolvedCompositeSi
findCompositeSingletons(set, compositeSingletons, baseUrl());
}
+ std::stable_sort(compositeSingletons.begin(), compositeSingletons.end(),
+ [](const QQmlImports::CompositeSingletonReference &lhs,
+ const QQmlImports::CompositeSingletonReference &rhs) {
+ if (lhs.prefix != rhs.prefix)
+ return lhs.prefix < rhs.prefix;
+
+ if (lhs.typeName != rhs.typeName)
+ return lhs.typeName < rhs.typeName;
+
+ return lhs.majorVersion != rhs.majorVersion
+ ? lhs.majorVersion < rhs.majorVersion
+ : lhs.minorVersion < rhs.minorVersion;
+ });
+
return compositeSingletons;
}
@@ -744,8 +758,10 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (majversion >= 0 && minversion >= 0) {
QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
if (t.isValid()) {
- if (vmajor) *vmajor = majversion;
- if (vminor) *vminor = minversion;
+ if (vmajor)
+ *vmajor = majversion;
+ if (vminor)
+ *vminor = minversion;
if (type_return)
*type_return = t;
return true;
@@ -804,10 +820,13 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (candidate != end) {
if (!base) // ensure we have a componentUrl
componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName);
- int major = vmajor ? *vmajor : -1;
- int minor = vminor ? *vminor : -1;
QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton,
- nullptr, major, minor);
+ nullptr, candidate->majorVersion,
+ candidate->minorVersion);
+ if (vmajor)
+ *vmajor = candidate->majorVersion;
+ if (vminor)
+ *vminor = candidate->minorVersion;
if (type_return)
*type_return = returnType;
return returnType.isValid();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 7480475ca7..cb90af4cf0 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2723,10 +2723,6 @@ void QQmlTypeData::resolveTypes()
}
}
- std::stable_sort(m_compositeSingletons.begin(), m_compositeSingletons.end(), [](const TypeReference &lhs, const TypeReference &rhs){
- return lhs.qualifiedName() < rhs.qualifiedName();
- });
-
for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_typeReferences.constBegin(), end = m_typeReferences.constEnd();
unresolvedRef != end; ++unresolvedRef) {
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 3cce30aaf6..4d4540bc36 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -343,6 +343,19 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy)
q->setBaselineOffset(baseline + yoff + q->topPadding());
}
+void QQuickTextPrivate::signalSizeChange(const QSizeF &previousSize)
+{
+ Q_Q(QQuickText);
+
+ if (layedOutTextRect.size() != previousSize) {
+ emit q->contentSizeChanged();
+ if (layedOutTextRect.width() != previousSize.width())
+ emit q->contentWidthChanged(layedOutTextRect.width());
+ if (layedOutTextRect.height() != previousSize.height())
+ emit q->contentHeightChanged(layedOutTextRect.height());
+ }
+}
+
void QQuickTextPrivate::updateSize()
{
Q_Q(QQuickText);
@@ -363,6 +376,8 @@ void QQuickTextPrivate::updateSize()
qreal hPadding = q->leftPadding() + q->rightPadding();
qreal vPadding = q->topPadding() + q->bottomPadding();
+ const QSizeF previousSize = layedOutTextRect.size();
+
if (text.isEmpty() && !isLineLaidOutConnected() && fontSizeMode() == QQuickText::FixedSize) {
// How much more expensive is it to just do a full layout on an empty string here?
// There may be subtle differences in the height and baseline calculations between
@@ -379,14 +394,13 @@ void QQuickTextPrivate::updateSize()
q->setImplicitSize(hPadding, fontHeight + vPadding);
layedOutTextRect = QRectF(0, 0, 0, fontHeight);
advance = QSizeF();
- emit q->contentSizeChanged();
+ signalSizeChange(previousSize);
updateType = UpdatePaintNode;
q->update();
return;
}
QSizeF size(0, 0);
- QSizeF previousSize = layedOutTextRect.size();
//setup instance of QTextLayout for all cases other than richtext
if (!richText) {
@@ -483,13 +497,7 @@ void QQuickTextPrivate::updateSize()
}
}
-
- if (layedOutTextRect.size() != previousSize)
- emit q->contentSizeChanged();
- if (layedOutTextRect.width() != previousSize.width())
- emit q->contentWidthChanged(layedOutTextRect.width());
- if (layedOutTextRect.height() != previousSize.height())
- emit q->contentHeightChanged(layedOutTextRect.height());
+ signalSizeChange(previousSize);
updateType = UpdatePaintNode;
q->update();
}
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index fd26d966c8..efa45e0958 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -75,6 +75,7 @@ public:
void updateBaseline(qreal baseline, qreal dy);
void updateSize();
+ void signalSizeChange(const QSizeF &previousSize);
void updateLayout();
bool determineHorizontalAlignment();
bool setHAlign(QQuickText::HAlignment, bool forceAlign = false);
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index bfc9f4c769..06a0fc396b 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -2044,11 +2044,22 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
int firstDirtyPos = 0;
if (nodeIterator != d->textNodeMap.end()) {
firstDirtyPos = nodeIterator->startPos();
+ // ### this could be optimized if the first and last dirty nodes are not connected
+ // as the intermediate text nodes would usually only need to be transformed differently.
+ int lastDirtyPos = firstDirtyPos;
+ auto it = d->textNodeMap.constEnd();
+ while (it != nodeIterator) {
+ --it;
+ if (it->dirty()) {
+ lastDirtyPos = it->startPos();
+ break;
+ }
+ }
do {
rootNode->removeChildNode(nodeIterator->textNode());
delete nodeIterator->textNode();
nodeIterator = d->textNodeMap.erase(nodeIterator);
- } while (nodeIterator != d->textNodeMap.end() && nodeIterator->dirty());
+ } while (nodeIterator != d->textNodeMap.constEnd() && nodeIterator->startPos() <= lastDirtyPos);
}
// FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
@@ -2090,7 +2101,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
QTextCharFormat format = a->formatAccessor(pos);
QTextBlock block = textFrame->firstCursorPosition().block();
engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- engine.addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
+ engine.addTextObject(block, QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
pos, textFrame->frameFormat().position());
nodeStart = pos;
} else {
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 13a8219cbd..0dd12207b7 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -205,7 +205,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QTextBlock block = textFrame->firstCursorPosition().block();
engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- engine.addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
+ engine.addTextObject(block, rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
pos, textFrame->frameFormat().position());
} else {
QTextFrame::iterator it = textFrame->begin();
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 9c91ae4896..792aa31a88 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -423,10 +423,11 @@ void QQuickTextNodeEngine::addImage(const QRectF &rect, const QImage &image, qre
QRectF searchRect = rect;
if (layoutPosition == QTextFrameFormat::InFlow) {
if (m_currentLineTree.isEmpty()) {
+ qreal y = m_currentLine.ascent() - ascent;
if (m_currentTextDirection == Qt::RightToLeft)
- searchRect.moveTopRight(m_position + m_currentLine.rect().topRight() + QPointF(0, 1));
+ searchRect.moveTopRight(m_position + m_currentLine.rect().topRight() + QPointF(0, y));
else
- searchRect.moveTopLeft(m_position + m_currentLine.position() + QPointF(0,1));
+ searchRect.moveTopLeft(m_position + m_currentLine.position() + QPointF(0, y));
} else {
const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1;
if (lastNode->glyphRun.isRightToLeft()) {
@@ -443,7 +444,7 @@ void QQuickTextNodeEngine::addImage(const QRectF &rect, const QImage &image, qre
m_hasContents = true;
}
-void QQuickTextNodeEngine::addTextObject(const QPointF &position, const QTextCharFormat &format,
+void QQuickTextNodeEngine::addTextObject(const QTextBlock &block, const QPointF &position, const QTextCharFormat &format,
SelectionState selectionState,
QTextDocument *textDocument, int pos,
QTextFrameFormat::Position layoutPosition)
@@ -476,17 +477,23 @@ void QQuickTextNodeEngine::addTextObject(const QPointF &position, const QTextCha
}
qreal ascent;
- QFontMetrics m(format.font());
+ QTextLine line = block.layout()->lineForTextPosition(pos);
switch (format.verticalAlignment())
{
- case QTextCharFormat::AlignMiddle:
- ascent = size.height() / 2 - 1;
+ case QTextCharFormat::AlignTop:
+ ascent = line.ascent();
break;
- case QTextCharFormat::AlignBaseline:
- ascent = size.height() - m.descent() - 1;
+ case QTextCharFormat::AlignMiddle: {
+ QFontMetrics m(format.font());
+ ascent = (size.height() - m.xHeight()) / 2;
+ break;
+ }
+ case QTextCharFormat::AlignBottom:
+ ascent = size.height() - line.descent();
break;
+ case QTextCharFormat::AlignBaseline:
default:
- ascent = size.height() - 1;
+ ascent = size.height();
}
addImage(QRectF(position, size), image, ascent, selectionState, layoutPosition);
@@ -1058,7 +1065,7 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
? QQuickTextNodeEngine::Selected
: QQuickTextNodeEngine::Unselected;
- addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos);
+ addTextObject(block, QPointF(), charFormat, selectionState, textDocument, textPos);
}
textPos += text.length();
} else {
diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h
index 18c624513a..49c1766045 100644
--- a/src/quick/items/qquicktextnodeengine_p.h
+++ b/src/quick/items/qquicktextnodeengine_p.h
@@ -179,7 +179,7 @@ public:
const QVarLengthArray<QTextLayout::FormatRange> &colorChanges,
int textPos, int fragmentEnd,
int selectionStart, int selectionEnd);
- void addTextObject(const QPointF &position, const QTextCharFormat &format,
+ void addTextObject(const QTextBlock &block, const QPointF &position, const QTextCharFormat &format,
SelectionState selectionState,
QTextDocument *textDocument, int pos,
QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 4db614d335..37d2ad1172 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -5,7 +5,7 @@ qtConfig(qml-network): \
QT_PRIVATE += network
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
-win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
+msvc:DEFINES *= _CRT_SECURE_NO_WARNINGS
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
win32:!winrt: LIBS += -luser32
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 02cb6acf99..ed5060a77d 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -139,7 +139,6 @@ built-ins/Date/prototype/toTimeString/invalid-date.js fails
built-ins/Date/prototype/toUTCString/day-names.js fails
built-ins/Date/prototype/toUTCString/format.js fails
built-ins/Date/prototype/toUTCString/month-names.js fails
-built-ins/Date/subclassing.js fails
built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js fails
built-ins/Function/prototype/bind/BoundFunction_restricted-properties.js fails
built-ins/Function/prototype/bind/instance-name-chained.js fails
@@ -177,14 +176,10 @@ built-ins/Object/prototype/toString/proxy-function.js fails
built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js fails
built-ins/Object/values/getter-adding-key.js fails
built-ins/Object/values/observable-operations.js fails
-built-ins/Promise/all/ctx-ctor.js fails
built-ins/Promise/prototype/catch/this-value-obj-coercible.js fails
-built-ins/Promise/prototype/then/capability-executor-called-twice.js fails
built-ins/Promise/prototype/then/capability-executor-not-callable.js fails
built-ins/Promise/prototype/then/ctor-custom.js fails
built-ins/Promise/race/ctx-ctor.js fails
-built-ins/Promise/reject/ctx-ctor.js fails
-built-ins/Promise/resolve/ctx-ctor.js fails
built-ins/Proxy/ownKeys/return-duplicate-entries-throws.js fails
built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws.js fails
built-ins/RegExp/S15.10.2.12_A2_T1.js fails
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Composite.qml b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Composite.qml
new file mode 100644
index 0000000000..b1055b6992
--- /dev/null
+++ b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Composite.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+ property int test: 0
+}
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Singleton.qml b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Singleton.qml
new file mode 100644
index 0000000000..e81b2b6cb5
--- /dev/null
+++ b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/Singleton.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQuick 2.0
+
+QtObject {
+ property Composite test: Composite {}
+}
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/qmldir b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/qmldir
new file mode 100644
index 0000000000..5a9cb1bd96
--- /dev/null
+++ b/tests/auto/qml/qmlplugindump/data/dumper/CompositeWithinSingleton/qmldir
@@ -0,0 +1,4 @@
+module dumper.CompositeWithinSingleton
+singleton Singleton 1.0 Singleton.qml
+Composite 1.0 Composite.qml
+depends QtQuick 2.0
diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
index f673fca1d7..17766a89b5 100644
--- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
+++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
@@ -45,6 +45,8 @@ private slots:
void initTestCase();
void builtins();
void singleton();
+ void compositeWithinSingleton();
+
void plugin_data();
void plugin();
@@ -118,6 +120,21 @@ void tst_qmlplugindump::singleton()
QVERIFY2(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")), qPrintable(result));
}
+void tst_qmlplugindump::compositeWithinSingleton()
+{
+ QProcess dumper;
+ QStringList args;
+ args << QLatin1String("dumper.CompositeWithinSingleton") << QLatin1String("1.0")
+ << QLatin1String(QT_QMLTEST_DIR "/data");
+ dumper.start(qmlplugindumpPath, args);
+ QVERIFY2(dumper.waitForStarted(), qPrintable(dumper.errorString()));
+ QVERIFY2(dumper.waitForFinished(), qPrintable(dumper.errorString()));
+
+ const QString &result = dumper.readAllStandardOutput();
+ QVERIFY2(result.contains(QLatin1String("exports: [\"Composite 1.0\"]")), qPrintable(result));
+ QVERIFY2(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")), qPrintable(result));
+}
+
void tst_qmlplugindump::plugin_data()
{
QTest::addColumn<QString>("import");
diff --git a/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton1.qml b/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton1.qml
new file mode 100644
index 0000000000..f4ad5e5f7a
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton1.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQuick 2.0
+
+Item {
+ property bool ok: true
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton2.qml b/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton2.qml
new file mode 100644
index 0000000000..55dd57517f
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/CppRegisteredSingleton2.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+import QtQuick 2.0
+import cppsingletonmodule 1.0
+
+Item {
+ property bool ok: CppRegisteredSingleton1.ok
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/Singleton.qml b/tests/auto/qml/qqmltypeloader/data/Singleton.qml
new file mode 100644
index 0000000000..3a1b1c1493
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Singleton.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+import QtQml 2.0
+import modulewithsingleton 1.0
+
+QtObject {
+ property bool ok: true
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton1.qml b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton1.qml
new file mode 100644
index 0000000000..34eca59f86
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton1.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+import QtQuick 2.0
+import "."
+
+Item {
+ property bool ok: true
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton2.qml b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton2.qml
new file mode 100644
index 0000000000..607d85d7fb
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/Singleton2.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+import QtQuick 2.0
+import "."
+
+Item {
+ property bool ok: Singleton1.ok
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/qmldir b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/qmldir
new file mode 100644
index 0000000000..71b889a12d
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/qmldir
@@ -0,0 +1,2 @@
+singleton Singleton1 1.0 Singleton1.qml
+singleton Singleton2 1.0 Singleton2.qml
diff --git a/tests/auto/qml/qqmltypeloader/data/multisingletonuser.qml b/tests/auto/qml/qqmltypeloader/data/multisingletonuser.qml
new file mode 100644
index 0000000000..b80e2c5223
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/multisingletonuser.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+import multisingletonmodule 1.0
+import cppsingletonmodule 1.0
+
+QtObject {
+ property bool ok: Singleton2.ok && CppRegisteredSingleton2.ok
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/singletonuser.qml b/tests/auto/qml/qqmltypeloader/data/singletonuser.qml
new file mode 100644
index 0000000000..79ca47e12f
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/singletonuser.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import modulewithsingleton 1.0
+
+QtObject {
+ property bool ok: Singleton.ok
+}
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index cf3bc8b050..3745fad470 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -31,6 +31,9 @@
#include <QtQml/qqmlnetworkaccessmanagerfactory.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
+#if QT_CONFIG(process)
+#include <QtCore/qprocess.h>
+#endif
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmltypeloader_p.h>
#include "../../shared/testhttpserver.h"
@@ -50,6 +53,8 @@ private slots:
void keepRegistrations();
void intercept();
void redirect();
+ void qmlSingletonWithinModule();
+ void multiSingletonModule();
};
void tst_QQMLTypeLoader::testLoadComplete()
@@ -428,6 +433,57 @@ void tst_QQMLTypeLoader::redirect()
QTRY_COMPARE(object->property("xy").toInt(), 323232);
}
+void tst_QQMLTypeLoader::qmlSingletonWithinModule()
+{
+ qmlClearTypeRegistrations();
+ QQmlEngine engine;
+ qmlRegisterSingletonType(testFileUrl("Singleton.qml"), "modulewithsingleton", 1, 0, "Singleton");
+
+ QQmlComponent component(&engine, testFileUrl("singletonuser.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QVERIFY(obj->property("ok").toBool());
+}
+
+void tst_QQMLTypeLoader::multiSingletonModule()
+{
+ qmlClearTypeRegistrations();
+ QQmlEngine engine;
+ engine.addImportPath(testFile("imports"));
+
+ qmlRegisterSingletonType(testFileUrl("CppRegisteredSingleton1.qml"), "cppsingletonmodule",
+ 1, 0, "CppRegisteredSingleton1");
+ qmlRegisterSingletonType(testFileUrl("CppRegisteredSingleton2.qml"), "cppsingletonmodule",
+ 1, 0, "CppRegisteredSingleton2");
+
+ QQmlComponent component(&engine, testFileUrl("multisingletonuser.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QVERIFY(obj->property("ok").toBool());
+
+#if QT_CONFIG(process)
+ const char *skipKey = "QT_TST_QQMLTYPELOADER_SKIP_MISMATCH";
+ if (qEnvironmentVariableIsSet(skipKey))
+ return;
+ for (int i = 0; i < 5; ++i) {
+ QProcess child;
+ child.setProgram(QCoreApplication::applicationFilePath());
+ child.setArguments(QStringList(QLatin1String("multiSingletonModule")));
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(QLatin1String("QT_LOGGING_RULES"), QLatin1String("qt.qml.diskcache.debug=true"));
+ env.insert(QLatin1String(skipKey), QLatin1String("1"));
+ child.setProcessEnvironment(env);
+ child.start();
+ QVERIFY(child.waitForFinished());
+ QCOMPARE(child.exitCode(), 0);
+ QVERIFY(!child.readAllStandardOutput().contains("Checksum mismatch for cached version"));
+ QVERIFY(!child.readAllStandardError().contains("Checksum mismatch for cached version"));
+ }
+#endif
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index 07f8e9f1d1..d8f4ed12e8 100644
--- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -30,6 +30,7 @@
#include <QQmlEngine>
#include <QLoggingCategory>
#include <private/qv4mm_p.h>
+#include <private/qv4qobjectwrapper_p.h>
class tst_qv4mm : public QObject
{
@@ -37,6 +38,7 @@ class tst_qv4mm : public QObject
private slots:
void gcStats();
+ void multiWrappedQObjects();
};
void tst_qv4mm::gcStats()
@@ -46,6 +48,44 @@ void tst_qv4mm::gcStats()
engine.collectGarbage();
}
+void tst_qv4mm::multiWrappedQObjects()
+{
+ QV4::ExecutionEngine engine1;
+ QV4::ExecutionEngine engine2;
+ {
+ QObject object;
+ for (int i = 0; i < 10; ++i)
+ QV4::QObjectWrapper::wrap(i % 2 ? &engine1 : &engine2, &object);
+
+ QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+ QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+ {
+ QV4::WeakValue value;
+ value.set(&engine1, QV4::QObjectWrapper::wrap(&engine1, &object));
+ }
+
+ QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
+ QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+
+ // Moves the additional WeakValue from m_multiplyWrappedQObjects to
+ // m_pendingFreedObjectWrapperValue. It's still alive after all.
+ engine1.memoryManager->runGC();
+ QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 2);
+
+ // engine2 doesn't own the object as engine1 was the first to wrap it above.
+ // Therefore, no effect here.
+ engine2.memoryManager->runGC();
+ QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+ }
+
+ // Clears m_pendingFreedObjectWrapperValue. Now it's really dead.
+ engine1.memoryManager->runGC();
+ QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+
+ engine2.memoryManager->runGC();
+ QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
+}
+
QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc"
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index 5aac91aae9..ecc3a4100c 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -40,6 +40,9 @@ private slots:
void parserMisc_data();
void parserMisc();
+
+ void subClassing_data();
+ void subClassing();
};
void tst_v4misc::tdzOptimizations_data()
@@ -130,6 +133,46 @@ void tst_v4misc::parserMisc()
QCOMPARE(result.toString(), error);
}
+void tst_v4misc::subClassing_data()
+{
+ QTest::addColumn<QString>("script");
+
+ QString code(
+ "class Foo extends %1 {"
+ " constructor() { super(); this.reset(); }"
+ " reset() { }"
+ "}"
+ "new Foo();");
+
+
+ QTest::newRow("Array") << code.arg("Array");
+ QTest::newRow("Boolean") << code.arg("Boolean");
+ QTest::newRow("Date") << code.arg("Date");
+ QTest::newRow("Function") << code.arg("Function");
+ QTest::newRow("Number") << code.arg("Number");
+ QTest::newRow("Map") << code.arg("Map");
+ QTest::newRow("Promise") << QString(
+ "class Foo extends Promise {"
+ " constructor() { super(Function()); this.reset(); }"
+ " reset() { }"
+ "}"
+ "new Foo();");
+ QTest::newRow("RegExp") << code.arg("RegExp");
+ QTest::newRow("Set") << code.arg("Set");
+ QTest::newRow("String") << code.arg("String");
+ QTest::newRow("WeakMap") << code.arg("WeakMap");
+ QTest::newRow("WeakSet") << code.arg("WeakSet");
+}
+
+void tst_v4misc::subClassing()
+{
+ QFETCH(QString, script);
+
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(script);
+ QVERIFY(!result.isError());
+}
+
QTEST_MAIN(tst_v4misc);
#include "tst_v4misc.moc"
diff --git a/tests/auto/quick/qquicktext/data/contentHeight.qml b/tests/auto/quick/qquicktext/data/contentHeight.qml
new file mode 100644
index 0000000000..472e97078e
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/contentHeight.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.9
+
+Text{
+ width: 200
+ height: contentHeight
+ text: ''
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index d8ff2f6e13..fd0ba0f49b 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -160,6 +160,8 @@ private slots:
void fontInfo();
+ void initialContentHeight();
+
private:
QStringList standard;
QStringList richText;
@@ -4384,6 +4386,18 @@ void tst_qquicktext::fontInfo()
QVERIFY(copy->font().pixelSize() < 1000);
}
+void tst_qquicktext::initialContentHeight()
+{
+ QQmlComponent component(&engine, testFile("contentHeight.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QObject *root = object.data();
+ QVERIFY(root);
+ QQuickText *text = qobject_cast<QQuickText *>(root);
+ QVERIFY(text);
+ QCOMPARE(text->height(), text->contentHeight());
+}
+
void tst_qquicktext::implicitSizeChangeRewrap()
{
QScopedPointer<QQuickView> window(new QQuickView);
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 1372bd3751..5190368e20 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -310,14 +310,6 @@ static void displayFileDialog(Options *options)
puts("No filename specified...");
}
-#if QT_CONFIG(translation)
-static void loadTranslationFile(QTranslator &translator, const QString& directory)
-{
- translator.load(QLocale(), QLatin1String("qml"), QLatin1String("_"), directory + QLatin1String("/i18n"));
- QCoreApplication::installTranslator(&translator);
-}
-#endif
-
static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
{
QDir dir(directory+"/dummydata", "*.qml");
@@ -588,10 +580,6 @@ int main(int argc, char ** argv)
if (!options.url.isEmpty()) {
if (!options.versionDetection || checkVersion(options.url)) {
-#if QT_CONFIG(translation)
- QTranslator translator;
-#endif
-
// TODO: as soon as the engine construction completes, the debug service is
// listening for connections. But actually we aren't ready to debug anything.
QQmlEngine engine;
@@ -603,7 +591,9 @@ int main(int argc, char ** argv)
if (options.url.isLocalFile()) {
QFileInfo fi(options.url.toLocalFile());
#if QT_CONFIG(translation)
- loadTranslationFile(translator, fi.path());
+ QTranslator *translator = new QTranslator(app.get());
+ if (translator->load(QLocale(), QLatin1String("qml"), QLatin1String("_"), fi.path() + QLatin1String("/i18n")))
+ QCoreApplication::installTranslator(translator);
#endif
loadDummyDataFiles(engine, fi.path());
}