diff options
author | Liang Qi <liang.qi@qt.io> | 2016-05-23 16:11:50 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-05-24 14:00:39 +0200 |
commit | 8ae479a8eac7b9ffeeba24e9e459e3e02ca20587 (patch) | |
tree | d6fdf18ddd2456835c598f40399348d247af6c97 /src/qml | |
parent | 1337e0d0827e86591e67a6dbaaeb3bd3f9ed733b (diff) | |
parent | 607320ca9fb2796a5f6f2578578fd314f7e8b99e (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4runtime_p.h
src/qml/qml/qqmldelayedcallqueue.cpp
src/qml/qml/qqmlvaluetypewrapper.cpp
src/qml/qml/qqmlvmemetaobject.cpp
src/qml/qml/v8/qv8engine_p.h
tests/auto/quick/qquicktext/tst_qquicktext.cpp
Change-Id: I3f0608c7beb88088cbbef4d0db59920f56deaea9
Diffstat (limited to 'src/qml')
37 files changed, 136 insertions, 171 deletions
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp index e6d1a218ad..23440e7529 100644 --- a/src/qml/debugger/qqmldebugconnector.cpp +++ b/src/qml/debugger/qqmldebugconnector.cpp @@ -54,14 +54,9 @@ QT_BEGIN_NAMESPACE // Connectors. We could add more plugins here, and distinguish by arguments to instance() Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugConnector) -Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebugServerFactory) -Q_QML_IMPORT_DEBUG_PLUGIN(QQmlNativeDebugConnectorFactory) // Services Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService) -Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory) -Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory) -Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebuggerServiceFactory) int QQmlDebugConnector::s_dataStreamVersion = QDataStream::Qt_4_7; diff --git a/src/qml/debugger/qqmldebugpluginmanager_p.h b/src/qml/debugger/qqmldebugpluginmanager_p.h index 2bcaf78972..8f52b65b17 100644 --- a/src/qml/debugger/qqmldebugpluginmanager_p.h +++ b/src/qml/debugger/qqmldebugpluginmanager_p.h @@ -74,15 +74,6 @@ QT_BEGIN_NAMESPACE #else // QT_NO_QML_DEBUGGER -#ifdef QT_STATIC -#define Q_QML_IMPORT_DEBUG_PLUGIN(className)\ - QT_END_NAMESPACE\ - Q_IMPORT_PLUGIN(className)\ - QT_BEGIN_NAMESPACE -#else -#define Q_QML_IMPORT_DEBUG_PLUGIN(className) -#endif // QT_STATIC - #define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, interfaceName##Loader,\ (interfaceName##Factory_iid, QLatin1String("/qmltooling")))\ diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf index 500754ead4..74b61fd6e1 100644 --- a/src/qml/doc/qtqml.qdocconf +++ b/src/qml/doc/qtqml.qdocconf @@ -4,7 +4,7 @@ project = QtQml description = Qt QML Reference Documentation version = $QT_VERSION -examplesinstallpath = qtdeclarative/qml +examplesinstallpath = qml qhp.projects = QtQml diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 257dd357fd..09e8bbda55 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -50,6 +50,7 @@ #include "private/qv4runtime_p.h" #include <private/qqmlbuiltinfunctions_p.h> #include <private/qqmldebugconnector_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <QtCore/qdatetime.h> #include <QtCore/qmetaobject.h> diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index edb23d94db..4860908bd3 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -54,7 +54,7 @@ #include "private/qv8engine_p.h" #include <private/qv4mm_p.h> #include <private/qv4scopedvalue_p.h> - +#include <private/qv4qobjectwrapper_p.h> /*! \since 5.0 diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h index 9caeccec9d..25afd9275c 100644 --- a/src/qml/jsapi/qjsvalue_p.h +++ b/src/qml/jsapi/qjsvalue_p.h @@ -56,7 +56,6 @@ #include <private/qv4value_p.h> #include <private/qv4string_p.h> #include <private/qv4engine_p.h> -#include <private/qv4object_p.h> #include <private/qflagpointer_p.h> #include <private/qv4mm_p.h> #include <private/qv4persistent_p.h> diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index f51f677636..2e6773a927 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -247,7 +247,7 @@ struct WithContext : public ExecutionContext V4_MANAGED(WithContext, ExecutionContext) }; -struct QmlContext : public ExecutionContext +struct Q_QML_EXPORT QmlContext : public ExecutionContext { V4_MANAGED(QmlContext, ExecutionContext) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 55ea1f91c3..d603a1982a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -111,85 +111,8 @@ static ReturnedValue throwTypeError(CallContext *ctx) return ctx->engine()->throwTypeError(); } -const int MinimumStackSize = 256; // in kbytes - -QT_WARNING_PUSH -QT_WARNING_DISABLE_MSVC(4172) // MSVC 2015: warning C4172: returning address of local variable or temporary: dummy - -quintptr getStackLimit() -{ - quintptr stackLimit; -#if USE(PTHREADS) && !OS(QNX) -# if OS(DARWIN) - pthread_t thread_self = pthread_self(); - void *stackTop = pthread_get_stackaddr_np(thread_self); - stackLimit = reinterpret_cast<quintptr>(stackTop); - quintptr size = 0; - if (pthread_main_np()) { - rlimit limit; - getrlimit(RLIMIT_STACK, &limit); - size = limit.rlim_cur; - } else - size = pthread_get_stacksize_np(thread_self); - stackLimit -= size; -# elif defined(__hppa) - // On some architectures the stack grows upwards. All of these are rather exotic, so simply assume - // everything is fine there. - // Known examples: - // -HP PA-RISC - stackLimit = 0; - -# else - pthread_attr_t attr; -#if HAVE(PTHREAD_NP_H) && OS(FREEBSD) - // on FreeBSD pthread_attr_init() must be called otherwise getting the attrs crashes - if (pthread_attr_init(&attr) == 0 && pthread_attr_get_np(pthread_self(), &attr) == 0) { -#else - if (pthread_getattr_np(pthread_self(), &attr) == 0) { -#endif - void *stackBottom = Q_NULLPTR; - size_t stackSize = 0; - - pthread_attr_getstack(&attr, &stackBottom, &stackSize); - pthread_attr_destroy(&attr); - -# if defined(Q_OS_ANDROID) - // Bionic pretends that the main thread has a tiny stack; work around it - if (gettid() == getpid()) { - rlimit limit; - getrlimit(RLIMIT_STACK, &limit); - stackBottom = reinterpret_cast<void*>(reinterpret_cast<quintptr>(stackBottom) + stackSize - limit.rlim_cur); - } -# endif - - stackLimit = reinterpret_cast<quintptr>(stackBottom); - } else { - int dummy; - // this is inexact, as part of the stack is used when being called here, - // but let's simply default to 1MB from where the stack is right now - stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024; - } - -# endif -// This is wrong. StackLimit is the currently committed stack size, not the real end. -// only way to get that limit is apparently by using VirtualQuery (Yuck) -//#elif OS(WINDOWS) -// PNT_TIB tib = (PNT_TIB)NtCurrentTeb(); -// stackLimit = static_cast<quintptr>(tib->StackLimit); -#else - int dummy; - // this is inexact, as part of the stack is used when being called here, - // but let's simply default to 1MB from where the stack is right now - // (Note: triggers warning C4172 as of MSVC 2015, returning address of local variable) - stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024; -#endif - - // 256k slack - return stackLimit + MinimumStackSize*1024; -} - -QT_WARNING_POP +#ifdef V4_BOOTSTRAP QJSEngine *ExecutionEngine::jsEngine() const { return v8Engine->publicEngine(); @@ -199,10 +122,14 @@ QQmlEngine *ExecutionEngine::qmlEngine() const { return v8Engine->engine(); } +#endif // V4_BOOTSTRAP + +qint32 ExecutionEngine::maxCallDepth = -1; ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) : current(0) , hasException(false) + , callDepth(0) , memoryManager(new QV4::MemoryManager(this)) , executableAllocator(new QV4::ExecutableAllocator) , regExpAllocator(new QV4::ExecutableAllocator) @@ -219,6 +146,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) , regExpCache(0) , m_multiplyWrappedQObjects(0) { + if (maxCallDepth == -1) { + bool ok = false; + maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok); + if (!ok || maxCallDepth <= 0) { + maxCallDepth = 1234; + } + } + Q_ASSERT(maxCallDepth > 0); + MemoryManager::GCBlocker gcBlocker(memoryManager); if (!factory) { @@ -267,9 +203,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) // set up stack limits jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value); - cStackLimit = getStackLimit(); - if (!recheckCStackLimits()) - qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize); identifierTable = new IdentifierTable(this); @@ -1103,22 +1036,6 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError() return error; } -bool ExecutionEngine::recheckCStackLimits() -{ - int dummy; -#ifdef Q_OS_WIN - // ### this is only required on windows, where we currently use heuristics to get the stack limit - if (cStackLimit - reinterpret_cast<quintptr>(&dummy) > 128*1024) - // we're more then 128k away from our stack limit, assume the thread has changed, and - // call getStackLimit -#endif - // this can happen after a thread change - cStackLimit = getStackLimit(); - - return (reinterpret_cast<quintptr>(&dummy) >= cStackLimit); -} - - // Variant conversion code typedef QSet<QV4::Heap::Object *> V4ObjectSet; diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 57a5952a6d..933241ea27 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -58,6 +58,10 @@ #include "qv4runtimeapi_p.h" #include <private/qintrusivelist_p.h> +#ifndef V4_BOOTSTRAP +# include <private/qv8engine_p.h> +#endif + namespace WTF { class BumpPointerAllocator; class PageAllocation; @@ -82,15 +86,11 @@ namespace CompiledData { struct CompilationUnit; } -#define CHECK_STACK_LIMITS(v4) \ - if ((v4->jsStackTop <= v4->jsStackLimit) && (reinterpret_cast<quintptr>(&v4) >= v4->cStackLimit || v4->recheckCStackLimits())) {} \ - else \ - return v4->throwRangeError(QStringLiteral("Maximum call stack size exceeded.")) - - struct Q_QML_EXPORT ExecutionEngine { private: + static qint32 maxCallDepth; + friend struct ExecutionContextSaver; friend struct ExecutionContext; friend struct Heap::ExecutionContext; @@ -99,6 +99,7 @@ public: Value *jsStackTop; quint32 hasException; + qint32 callDepth; MemoryManager *memoryManager; ExecutableAllocator *executableAllocator; @@ -108,7 +109,6 @@ public: ExecutionContext *currentContext; Value *jsStackLimit; - quintptr cStackLimit; Runtime runtime; @@ -142,8 +142,13 @@ public: Function *globalCode; +#ifdef V4_BOOTSTRAP QJSEngine *jsEngine() const; QQmlEngine *qmlEngine() const; +#else // !V4_BOOTSTRAP + QJSEngine *jsEngine() const { return v8Engine->publicEngine(); } + QQmlEngine *qmlEngine() const { return v8Engine->engine(); } +#endif // V4_BOOTSTRAP QV8Engine *v8Engine; enum JSObjects { @@ -440,8 +445,6 @@ public: InternalClass *newClass(const InternalClass &other); - bool recheckCStackLimits(); - // Exception handling Value *exceptionValue; StackTrace exceptionStackTrace; @@ -474,13 +477,19 @@ public: QV4::ReturnedValue metaTypeToJS(int type, const void *data); void assertObjectBelongsToEngine(const Heap::Base &baseObject); + + bool checkStackLimits(ReturnedValue &exception); }; // This is a trick to tell the code generators that functions taking a NoThrowContext won't // throw exceptions and therefore don't need a check after the call. +#ifndef V4_BOOTSTRAP struct NoThrowEngine : public ExecutionEngine { }; +#else +struct NoThrowEngine; +#endif inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context) @@ -526,7 +535,7 @@ inline Heap::QmlContext *ExecutionEngine::qmlContext() const if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer) ctx = parentContext(currentContext)->d(); - if (!ctx->outer) + if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer) return 0; while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext) @@ -562,7 +571,26 @@ inline void Value::mark(ExecutionEngine *e) o->mark(e); } +#define CHECK_STACK_LIMITS(v4) { ReturnedValue e; if ((v4)->checkStackLimits(e)) return e; } \ + ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); +struct ExecutionEngineCallDepthRecorder +{ + ExecutionEngine *ee; + + ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; } + ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; } +}; + +inline bool ExecutionEngine::checkStackLimits(ReturnedValue &exception) +{ + if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) { + exception = throwRangeError(QStringLiteral("Maximum call stack size exceeded.")); + return true; + } + + return false; +} } // namespace QV4 diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 5528409b40..9fe8224736 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -86,18 +86,10 @@ Heap::MathObject::MathObject() m->defineDefaultProperty(QStringLiteral("tan"), QV4::MathObject::method_tan, 1); } -#ifdef Q_OS_ANDROID -// C++11's std::copysign is missing in the std namespace, so get it from the root namespace (math.h) static Q_ALWAYS_INLINE double copySign(double x, double y) { return ::copysign(x, y); } -#else // Ok, we have a proper C++11 standard library -static Q_ALWAYS_INLINE double copySign(double x, double y) -{ - return std::copysign(x, y); -} -#endif ReturnedValue MathObject::method_abs(CallContext *context) { diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 35fcd00eb7..c888f1e44c 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -561,7 +561,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP } } -ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) +ReturnedValue QObjectWrapper::wrap_slowPath(ExecutionEngine *engine, QObject *object) { if (QQmlData::wasDeleted(object)) return QV4::Encode::null(); @@ -572,10 +572,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) Scope scope(engine); - if (ddata->jsEngineId == engine->m_engineId && !ddata->jsWrapper.isUndefined()) { - // We own the JS object - return ddata->jsWrapper.value(); - } else if (ddata->jsWrapper.isUndefined() && + if (ddata->jsWrapper.isUndefined() && (ddata->jsEngineId == engine->m_engineId || // We own the QObject ddata->jsEngineId == 0 || // No one owns the QObject !ddata->hasTaintedV4Object)) { // Someone else has used the QObject, but it isn't tainted diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 0186a8381a..d53bb88d20 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -146,8 +146,27 @@ protected: static ReturnedValue method_connect(CallContext *ctx); static ReturnedValue method_disconnect(CallContext *ctx); + +private: + static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object); }; +inline ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) +{ + if (Q_LIKELY(!QQmlData::wasDeleted(object))) { + QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object)); + if (Q_LIKELY(priv->declarativeData)) { + auto ddata = static_cast<QQmlData *>(priv->declarativeData); + if (Q_LIKELY(ddata->jsEngineId == engine->m_engineId && !ddata->jsWrapper.isUndefined())) { + // We own the JS object + return ddata->jsWrapper.value(); + } + } + } + + return wrap_slowPath(engine, object); +} + struct QQmlValueTypeWrapper; struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b7543692d5..8f377dd664 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qv4global_p.h" +#include "qv4engine_p.h" #include "qv4runtime_p.h" #ifndef V4_BOOTSTRAP #include "qv4object_p.h" diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 807fbe2f0e..975d100ef4 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE +class QQmlAccessors; + #undef QV4_COUNT_RUNTIME_FUNCTIONS namespace QV4 { @@ -102,7 +104,6 @@ enum TypeHint { STRING_HINT }; - struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { static ReturnedValue objectDefaultValue(const Object *object, int typeHint); static ReturnedValue toPrimitive(const Value &value, int typeHint); diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index f803f2fb06..14def49d0a 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -48,6 +48,7 @@ #include <private/qv4regexpobject_p.h> #include <private/qv4sequenceobject_p.h> #include <private/qv4objectproto_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 514bdafb48..a8d9b0fa71 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -56,11 +56,7 @@ #include "qv4global_p.h" #include <private/qv4heap_p.h> -/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects - are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */ -#ifdef V4_BOOTSTRAP -#define QV4_USE_64_BIT_VALUE_ENCODING -#elif QT_POINTER_SIZE == 8 +#if QT_POINTER_SIZE == 8 #define QV4_USE_64_BIT_VALUE_ENCODING #endif diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 743a11d31e..444c0a37e0 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -42,6 +42,7 @@ #include "qv4objectproto_p.h" #include <private/qqmlvaluetypewrapper_p.h> #include <private/qv8engine_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index b03edc9020..f423a7d452 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -55,6 +55,7 @@ #include "qqmlinfo.h" #include <private/qv4value_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <QtCore/qdebug.h> diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 6aa3710731..eb4f590222 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -60,6 +60,7 @@ #include <private/qv4script_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4objectiterator_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <QStack> #include <QStringList> @@ -1068,6 +1069,7 @@ struct QmlIncubatorObject : Object { QPointer<QObject> parent; QV4::Value valuemap; QV4::Value statusChanged; + Pointer<Heap::QmlContext> qmlContext; }; } @@ -1182,7 +1184,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent) */ -static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v) +static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v) { QV4::Scope scope(engine); QV4::ScopedObject object(scope); @@ -1193,6 +1195,9 @@ static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value if (engine->hasException) return; + QV4::ExecutionContextSaver saver(scope); + engine->pushContext(qmlContext); + while (1) { name = it.nextPropertyNameAsString(val); if (!name) @@ -1266,8 +1271,10 @@ void QQmlComponent::createObject(QQmlV4Function *args) QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv)); Q_ASSERT(object->isObject()); - if (!valuemap->isUndefined()) - setInitialProperties(v4, object, valuemap); + if (!valuemap->isUndefined()) { + QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->qmlContext()); + setInitialProperties(v4, qmlContext, object, valuemap); + } d->completeCreate(); @@ -1384,6 +1391,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) if (!valuemap->isUndefined()) r->d()->valuemap = valuemap; + r->d()->qmlContext = v4->qmlContext(); r->d()->parent = parent; QQmlIncubator *incubator = r->d()->incubator.data(); @@ -1397,7 +1405,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) } // XXX used by QSGLoader -void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate) +void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine()); @@ -1407,7 +1415,7 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu Q_ASSERT(object->as<QV4::Object>()); if (!valuemap.isUndefined()) - setInitialProperties(v4engine, object, valuemap); + setInitialProperties(v4engine, qmlContext, object, valuemap); } QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4) @@ -1484,6 +1492,7 @@ QQmlComponentExtension::~QQmlComponentExtension() QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m) : valuemap(QV4::Primitive::undefinedValue()) , statusChanged(QV4::Primitive::undefinedValue()) + , qmlContext(0) { incubator.reset(new QQmlComponentIncubator(this, m)); } @@ -1496,7 +1505,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o) QV4::ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o)); - setInitialProperties(v4, obj, d()->valuemap); + QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, d()->qmlContext); + setInitialProperties(v4, qmlCtxt, obj, d()->valuemap); } } @@ -1505,6 +1515,8 @@ void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionE QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that); o->valuemap.mark(e); o->statusChanged.mark(e); + if (o->qmlContext) + o->qmlContext->mark(e); Object::markObjects(that, e); } diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index ba2982d76d..039b267433 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -86,7 +86,7 @@ public: QObject *beginCreate(QQmlContextData *); void completeCreate(); - void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate); + void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate); QQmlTypeData *typeData; virtual void typeDataReady(QQmlTypeData *); diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 8613c78f6d..2d0ebad764 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -53,6 +53,7 @@ #include <private/qqmllistwrapper_p.h> #include <private/qqmljavascriptexpression_p.h> #include <private/qjsvalue_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE @@ -105,14 +106,23 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); + // In V8 the JS global object would come _before_ the QML global object, + // so simulate that here. + bool hasProp; + QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp)); + if (hasProp) { + if (hasProperty) + *hasProperty = hasProp; + return result->asReturnedValue(); + } + if (resource->d()->isNullWrapper) return Object::get(m, name, hasProperty); if (v4->callingQmlContext() != resource->d()->context) return Object::get(m, name, hasProperty); - bool hasProp; - QV4::ScopedValue result(scope, Object::get(m, name, &hasProp)); + result = Object::get(m, name, &hasProp); if (hasProp) { if (hasProperty) *hasProperty = hasProp; diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index d2c7ecdea2..ca7fcf1d75 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -54,21 +54,13 @@ #include <QtCore/qglobal.h> #include <private/qtqmlglobal_p.h> -#include <private/qv4value_p.h> #include <private/qv4object_p.h> #include <private/qqmlcontext_p.h> -#include <private/qv4functionobject_p.h> QT_BEGIN_NAMESPACE namespace QV4 { -namespace CompiledData { -struct Function; -} - -struct QmlContextWrapper; - namespace Heap { struct QmlContextWrapper : Object { diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp index 8d0fb22866..b3a0baffb4 100644 --- a/src/qml/qml/qqmldelayedcallqueue.cpp +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -43,6 +43,7 @@ #include <private/qqmljavascriptexpression_p.h> #include <private/qv4value_p.h> #include <private/qv4qobjectwrapper_p.h> +#include <private/qqmlcontextwrapper_p.h> #include <QQmlError> diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 069dadd1c9..8ba4b5eba1 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -47,6 +47,7 @@ #include <private/qv4errorobject_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qqmlglobal_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index f203dd3607..5c35866274 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -44,6 +44,7 @@ #include <qv4objectiterator_p.h> #include <private/qv4functionobject_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 6769a9a123..652a3ca0d4 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -56,6 +56,7 @@ #include <QtCore/qlocale.h> #include <QtCore/qobject.h> #include <private/qqmlglobal_p.h> +#include <private/qv4object_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 8d3c5962bd..775f8a9294 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -43,6 +43,7 @@ #include <private/qqmlvmemetaobject_p.h> #include <private/qv4function_p.h> #include <private/qv4functionobject_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <private/qqmlcontextwrapper_p.h> #include <private/qqmlbinding_p.h> #include <private/qqmlstringconverters_p.h> diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index c6299a1720..4ec3dfe6a5 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -980,7 +980,7 @@ struct CachedLoader { } void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const { - loader->m_thread->loadWithCachedUnit(blob, unit); + loader->m_thread->loadWithCachedUnitAsync(blob, unit); } }; diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 33fe655368..7892555f08 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -47,6 +47,7 @@ #include <private/qjsvalue_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4objectproto_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index fdac41a420..5cb346a462 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -51,6 +51,7 @@ #include <private/qv4variantobject_p.h> #include <private/qv4alloca_p.h> #include <private/qv4objectiterator_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index c82da696c8..3cafcb57d7 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -55,6 +55,7 @@ #include <private/qv4variantobject_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4scopedvalue_p.h> +#include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE @@ -732,9 +733,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * case QV4::CompiledData::Property::Quaternion: Q_ASSERT(fallbackMetaType != QMetaType::UnknownType); if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { - QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); - if (v) - QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], fallbackMetaType); + QVariant propertyAsVariant; + if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>()) + propertyAsVariant = v->d()->data; + QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType); } break; case QV4::CompiledData::Property::Var: diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 1f42cbf983..54c29b4b8a 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -63,6 +63,7 @@ #include <private/qv4mm_p.h> #include <private/qv4jsonobject_p.h> #include <private/qv4objectproto_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <QtCore/qstring.h> #include <QtCore/qdatetime.h> diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index d8b0ef79f8..e08ff3b979 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -70,6 +70,7 @@ #include <private/qv4value_p.h> #include <private/qv4dateobject_p.h> #include <private/qv4objectiterator_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <private/qv4mm_p.h> #include <private/qv4objectproto_p.h> #include <private/qv4globalobject_p.h> diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index c5041c54e0..390831609b 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -60,16 +60,13 @@ #include <QtCore/QElapsedTimer> #include <QtCore/QThreadStorage> -#include <qjsengine.h> +#include <QtQml/qjsengine.h> #include "private/qintrusivelist_p.h" -#include <private/qqmlpropertycache_p.h> -#include <private/qv4qobjectwrapper_p.h> #include <private/qv4value_p.h> -#include <private/qv4object_p.h> #include <private/qv4identifier_p.h> -#include <private/qqmlcontextwrapper_p.h> +#include <private/qv4context_p.h> #include <private/qqmldelayedcallqueue_p.h> QT_BEGIN_NAMESPACE @@ -77,6 +74,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct ArrayObject; struct ExecutionEngine; + struct QObjectMethod; } #define V4THROW_ERROR(string) \ diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index 76e55f718d..bf9fd99f19 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -41,7 +41,7 @@ #define QQMLDATAMODEL_P_P_H #include "qqmldelegatemodel_p.h" - +#include <private/qv4qobjectwrapper_p.h> #include <QtQml/qqmlcontext.h> #include <QtQml/qqmlincubator.h> diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index 431e6aca9f..d3ff032ae9 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -54,6 +54,7 @@ #include "qqmllistmodel_p.h" #include <private/qqmlengine_p.h> #include <private/qqmlopenmetaobject_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <qqml.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h index f9872a6ad4..1a891c0f25 100644 --- a/src/qml/types/qqmllistmodelworkeragent_p.h +++ b/src/qml/types/qqmllistmodelworkeragent_p.h @@ -53,6 +53,7 @@ #include <qqml.h> +#include <QEvent> #include <QMutex> #include <QWaitCondition> |