diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4dateobject.cpp | 44 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 22 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 13 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4promiseobject.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 31 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 8 |
10 files changed, 103 insertions, 31 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index bba88e5c9a..cc89947cec 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -294,13 +294,28 @@ static double MakeDay(double year, double month, double day) if (month < 0) month += 12.0; - double d = DayFromYear(year); - bool leap = InLeapYear(d*msPerDay); + /* Quoting the spec: - d += DayFromMonth(month, leap); - d += day - 1; + Find a value t such that YearFromTime(t) is ym and MonthFromTime(t) is mn + and DateFromTime(t) is 1; but if this is not possible (because some + argument is out of range), return NaN. + */ + double first = DayFromYear(year); + /* Beware floating-point glitches: don't test the first millisecond of a + * year, month or day when we could test a moment firmly in the interior of + * the interval. A rounding glitch might give the first millisecond to the + * preceding interval. + */ + bool leap = InLeapYear((first + 60) * msPerDay); - return d; + first += DayFromMonth(month, leap); + const double t = first * msPerDay + msPerDay / 2; // Noon on the first of the month + Q_ASSERT(Day(t) == first); + if (YearFromTime(t) != year || MonthFromTime(t) != month || DateFromTime(t) != 1) { + qWarning("Apparently out-of-range date %.0f-%02.0f-%02.0f", year, month, day); + return qt_qnan(); + } + return first + day - 1; } static inline double MakeDate(double day, double time) @@ -601,8 +616,7 @@ static inline double ParseString(const QString &s, double localTZA) QStringLiteral("d MMMM, yyyy hh:mm:ss"), }; - for (uint i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) { - const QString &format(formats[i]); + for (const QString &format : formats) { dt = format.indexOf(QLatin1String("hh:mm")) < 0 ? QDateTime(QDate::fromString(s, format), QTime(0, 0, 0), Qt::UTC) @@ -729,14 +743,16 @@ void Heap::DateObject::init(const QTime &time) * time from it, which shall (via toQDateTime(), below) discard the date * part. We need a date for which time-zone data is likely to be sane (so * MakeDay(0, 0, 0) was a bad choice; 2 BC, December 31st is before - * time-zones were standardized), with no transition nearby in date. We - * ignore DST transitions before 1970, but even then zone transitions did - * happen. Some do happen at new year, others on DST transitions in spring - * and autumn; so pick the three hundredth anniversary of the birth of - * Giovanni Domenico Cassini (1625-06-08), whose work first let us - * synchronize clocks tolerably accurately at distant locations. + * time-zones were standardized), with no transition nearby in date. + * QDateTime ignores DST transitions before 1970, but even then zone + * transitions did happen; and DaylightSavingTA() will include DST, at odds + * with QDateTime. So pick a date since 1970 and prefer one when no zone + * was in DST. One such interval (according to the Olson database, at + * least) was 1971 March 15th to April 17th. Since converting a time to a + * date-time without specifying a date is foolish, let's use April Fools' + * day. */ - static const double d = MakeDay(1925, 5, 8); + static const double d = MakeDay(1971, 3, 1); double t = MakeTime(time.hour(), time.minute(), time.second(), time.msec()); date = TimeClip(UTC(MakeDate(d, t), internalClass->engine->localTZA)); } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index be0de09d79..590cebfa7c 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -216,15 +216,19 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) memoryManager = new QV4::MemoryManager(this); if (maxCallDepth == -1) { - ok = false; - maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok); - if (!ok || maxCallDepth <= 0) { + if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) { + maxCallDepth = std::numeric_limits<qint32>::max(); + } else { + ok = false; + maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok); + if (!ok || maxCallDepth <= 0) { #if defined(QT_NO_DEBUG) && !defined(__SANITIZE_ADDRESS__) && !QT_HAS_FEATURE(address_sanitizer) - maxCallDepth = 1234; + maxCallDepth = 1234; #else - // no (tail call) optimization is done, so there'll be a lot mare stack frames active - maxCallDepth = 200; + // no (tail call) optimization is done, so there'll be a lot mare stack frames active + maxCallDepth = 200; #endif + } } } Q_ASSERT(maxCallDepth > 0); @@ -1761,6 +1765,12 @@ ReturnedValue ExecutionEngine::global() QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const QUrl &url) { + QQmlMetaType::CachedUnitLookupError cacheError = QQmlMetaType::CachedUnitLookupError::NoError; + if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url, &cacheError)) { + return ExecutableCompilationUnit::create( + QV4::CompiledData::CompilationUnit(cachedUnit, url.fileName(), url.toString())); + } + QFile f(QQmlFile::urlToLocalFileOrQrc(url)); if (!f.open(QIODevice::ReadOnly)) { throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString())); diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index 950e0b10ea..d51e986006 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -52,6 +52,7 @@ #include <private/qv4module_p.h> #include <private/qv4compilationunitmapper_p.h> #include <private/qml_compile_hash_p.h> +#include <private/qqmltypewrapper_p.h> #include <QtQml/qqmlfile.h> #include <QtQml/qqmlpropertymap.h> @@ -291,15 +292,18 @@ void ExecutableCompilationUnit::unlink() if (runtimeLookups) { for (uint i = 0; i < data->lookupTableSize; ++i) { QV4::Lookup &l = runtimeLookups[i]; - if (l.getter == QV4::QObjectWrapper::lookupGetter) { + if (l.getter == QV4::QObjectWrapper::lookupGetter + || l.getter == QQmlTypeWrapper::lookupSingletonProperty) { if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) pc->release(); - } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) { + } else if (l.getter == QQmlValueTypeWrapper::lookupGetter + || l.getter == QQmlTypeWrapper::lookupSingletonProperty) { if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache) pc->release(); } - if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) { + if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty + || l.qmlContextPropertyGetter == QQmlContextWrapper::lookupContextObjectProperty) { if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) pc->release(); } diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 7578de4d14..31c90b31f6 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -151,6 +151,19 @@ struct Q_QML_PRIVATE_EXPORT Lookup { quintptr reserved3; ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine); } qmlContextGlobalLookup; + struct { + Heap::Object *qmlTypeWrapper; + quintptr unused2; + } qmlTypeLookup; + struct { + Heap::InternalClass *ic; + quintptr unused; + ReturnedValue encodedEnumValue; + } qmlEnumValueLookup; + struct { + Heap::InternalClass *ic; + Heap::Object *qmlScopedEnumWrapper; + } qmlScopedEnumWrapperLookup; }; uint nameIndex; diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp index 27075e96a0..17d218a6eb 100644 --- a/src/qml/jsruntime/qv4promiseobject.cpp +++ b/src/qml/jsruntime/qv4promiseobject.cpp @@ -163,6 +163,7 @@ void ReactionHandler::executeReaction(ReactionEvent *event) ScopedFunctionObject reaction(scope); if (scope.hasException()) { reaction = capability->d()->reject.as<QV4::FunctionObject>(); + result = scope.engine->catchException(); } else { reaction = capability->d()->resolve.as<QV4::FunctionObject>(); } diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index c832bff051..e2d3b98ff6 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -248,11 +248,15 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r return lookup->qmlContextPropertyGetter(lookup, v4, base); } } - return QQmlTypeWrapper::create(v4, scopeObject, r.type); + result = QQmlTypeWrapper::create(v4, scopeObject, r.type); } else if (r.importNamespace) { - return QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace); + result = QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace); } - Q_ASSERT(!"Unreachable"); + if (lookup) { + lookup->qmlTypeLookup.qmlTypeWrapper = static_cast<Heap::Object*>(result->heapObject()); + lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupType; + } + return result->asReturnedValue(); } // Fall through @@ -659,6 +663,27 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec return Encode::undefined(); } +ReturnedValue QQmlContextWrapper::lookupType(Lookup *l, ExecutionEngine *engine, Value *base) +{ + Scope scope(engine); + Scoped<QmlContext> qmlContext(scope, engine->qmlContext()); + if (!qmlContext) + return QV4::Encode::undefined(); + + QObject *scopeObject = qmlContext->qmlScope(); + if (scopeObject && QQmlData::wasDeleted(scopeObject)) + return QV4::Encode::undefined(); + + Heap::Object *heapObject = l->qmlTypeLookup.qmlTypeWrapper; + if (static_cast<Heap::QQmlTypeWrapper *>(heapObject)->object != scopeObject) { + l->qmlTypeLookup.qmlTypeWrapper = nullptr; + l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter; + return QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(l, engine, base); + } + + return Value::fromHeapObject(heapObject).asReturnedValue(); +} + void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml) { Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext); diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h index 4c8287ef2f..e3e7239fe5 100644 --- a/src/qml/jsruntime/qv4qmlcontext_p.h +++ b/src/qml/jsruntime/qv4qmlcontext_p.h @@ -112,6 +112,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object static ReturnedValue lookupContextObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base); static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base); static ReturnedValue lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base); + static ReturnedValue lookupType(Lookup *l, ExecutionEngine *engine, Value *base); }; struct Q_QML_EXPORT QmlContext : public ExecutionContext diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index c36da3815d..2b5e8bd2b9 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -2077,7 +2077,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value * if (!d()->valueTypeWrapper) return Encode::undefined(); - object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr); + object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr()); } QQmlPropertyData method; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 8a7cbdfb2a..aaa198c62a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -2050,7 +2050,7 @@ ReturnedValue Runtime::Exp::call(const Value &base, const Value &exp) double b = base.toNumber(); double e = exp.toNumber(); if (qt_is_inf(e) && (b == 1 || b == -1)) - return Encode(qt_snan()); + return Encode(qt_qnan()); return Encode(pow(b,e)); } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index b4c34d60fa..27d518f5c6 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -647,7 +647,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(LoadSuperProperty) STORE_IP(); - STORE_ACC(); acc = Runtime::LoadSuperProperty::call(engine, STACK_VALUE(property)); CHECK_EXCEPTION; MOTH_END_INSTR(LoadSuperProperty) @@ -794,12 +793,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(Construct) STORE_IP(); + STORE_ACC(); acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc); CHECK_EXCEPTION; MOTH_END_INSTR(Construct) MOTH_BEGIN_INSTR(ConstructWithSpread) STORE_IP(); + STORE_ACC(); acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc); CHECK_EXCEPTION; MOTH_END_INSTR(ConstructWithSpread) @@ -827,7 +828,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(DeadTemporalZoneCheck) if (ACC.isEmpty()) { STORE_IP(); - STORE_ACC(); Runtime::ThrowReferenceError::call(engine, name); goto handleUnwind; } @@ -970,6 +970,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(CreateRestParameter) MOTH_BEGIN_INSTR(ConvertThisToObject) + STORE_ACC(); stack[CallData::This] = Runtime::ConvertThisToObject::call(engine, stack[CallData::This]); CHECK_EXCEPTION; MOTH_END_INSTR(ConvertThisToObject) @@ -980,6 +981,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(LoadSuperConstructor) MOTH_BEGIN_INSTR(ToObject) + STORE_ACC(); acc = ACC.toObject(engine)->asReturnedValue(); CHECK_EXCEPTION; MOTH_END_INSTR(ToObject) @@ -1247,7 +1249,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, double base = left.toNumber(); double exp = ACC.toNumber(); if (qIsInf(exp) && (base == 1 || base == -1)) - acc = Encode(qSNaN()); + acc = Encode(qQNaN()); else acc = Encode(pow(base,exp)); MOTH_END_INSTR(Exp) |