diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-09-25 20:56:51 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-09-25 20:56:51 +0200 |
commit | f9ef039ad955db67dc3ab6e9056afc4a325aa9a3 (patch) | |
tree | 4928ff85fb630639e306ea4eb7137a2064a80c8b /src/qml/qml | |
parent | 0238c739f81911f0963cf2c40b27dcfc8e3d38b7 (diff) | |
parent | 52fb4685e95e5b44e54d2d0f8ea27dea866c75e9 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/qml/debugger/qqmldebug.cpp
Change-Id: I93de5a81b18cdece475870cf7cfba1b9baef2304
Diffstat (limited to 'src/qml/qml')
31 files changed, 228 insertions, 285 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 3613c17242..f8b737a62a 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -90,7 +90,7 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine(); if (runtimeFunction) { - m_function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction)); + m_function.set(v4, QV4::FunctionObject::createQmlFunction(ctxtdata, scopeObject(), runtimeFunction)); } else { QString code = scriptPrivate->script; createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber); diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index ff5f36bd9c..decffaf2fa 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -124,7 +124,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index); QString error; QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine); - m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error)); + m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error)); if (!error.isEmpty()) { qmlInfo(scopeObject()) << error; m_function.clear(); diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index d62aada9c6..be482b4639 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -42,7 +42,6 @@ #include "qqml.h" #include "qqmlengine.h" #include "qqmlbinding_p.h" -#include "qqmlglobal_p.h" #include <private/qqmldebugconnector_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include "qqmlincubator.h" @@ -1060,11 +1059,10 @@ namespace QV4 { namespace Heap { struct QmlIncubatorObject : Object { - QmlIncubatorObject(QV4::ExecutionEngine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); + QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); QScopedPointer<QQmlComponentIncubator> incubator; QPointer<QObject> parent; QV4::Value valuemap; - QV4::Value qmlGlobal; QV4::Value statusChanged; }; @@ -1376,14 +1374,12 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) QQmlComponentExtension *e = componentExtension(args->v4engine()); - QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QV4::QmlIncubatorObject>(args->v4engine(), mode)); + QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode)); QV4::ScopedObject p(scope, e->incubationProto.value()); r->setPrototype(p); - if (!valuemap->isUndefined()) { + if (!valuemap->isUndefined()) r->d()->valuemap = valuemap; - r->d()->qmlGlobal = args->qmlGlobal(); - } r->d()->parent = parent; QQmlIncubator *incubator = r->d()->incubator.data(); @@ -1481,10 +1477,8 @@ QQmlComponentExtension::~QQmlComponentExtension() { } -QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(ExecutionEngine *engine, QQmlIncubator::IncubationMode m) - : QV4::Heap::Object(engine) - , valuemap(QV4::Primitive::undefinedValue()) - , qmlGlobal(QV4::Primitive::undefinedValue()) +QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m) + : valuemap(QV4::Primitive::undefinedValue()) , statusChanged(QV4::Primitive::undefinedValue()) { incubator.reset(new QQmlComponentIncubator(this, m)); @@ -1506,7 +1500,6 @@ void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionE { QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that); o->valuemap.mark(e); - o->qmlGlobal.mark(e); o->statusChanged.mark(e); Object::markObjects(that, e); } diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 99a5fe56ce..0d84c3bb64 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -54,9 +54,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlContextWrapper); -Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext) - : Heap::Object(engine) - , readOnly(true) +Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext) + : readOnly(true) , ownsContext(ownsContext) , isNullWrapper(false) , context(context) @@ -74,7 +73,7 @@ ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData * { Scope valueScope(v4); - Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v4, ctxt, scope)); + Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->allocObject<QmlContextWrapper>(ctxt, scope)); return w.asReturnedValue(); } @@ -88,7 +87,7 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url) context->isInternal = true; context->isJSContext = true; - Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v4, context, (QObject*)0, true)); + Scoped<QmlContextWrapper> w(scope, v4->memoryManager->allocObject<QmlContextWrapper>(context, (QObject*)0, true)); w->d()->isNullWrapper = true; return w.asReturnedValue(); } @@ -240,7 +239,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value) uint member = wrapper->internalClass()->find(name); if (member < UINT_MAX) { - wrapper->putValue(wrapper->propertyAt(member), wrapper->internalClass()->propertyData[member], value); + wrapper->putValue(member, value); return; } @@ -248,7 +247,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value) if (wrapper && wrapper->d()->readOnly) { QString error = QLatin1String("Invalid write to global property \"") + name->toQString() + QLatin1Char('"'); - ScopedString e(scope, v4->currentContext()->engine->newString(error)); + ScopedString e(scope, v4->newString(error)); v4->throwError(e); return; } diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index 192df9aed6..9dd71b708f 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -66,7 +66,7 @@ struct QmlContextWrapper; namespace Heap { struct QmlContextWrapper : Object { - QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); + QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); ~QmlContextWrapper(); bool readOnly; bool ownsContext; diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index ebca9d2718..517f8d42ed 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -34,6 +34,7 @@ #include "qqmlcustomparser_p.h" #include "qqmlcompiler_p.h" +#include <private/qqmltypecompiler_p.h> #include <QtCore/qdebug.h> @@ -140,7 +141,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const type = result.type; } - return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; + return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; } const QMetaObject *mo = StaticQtMetaObject::get(); @@ -159,34 +160,8 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const */ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const { - return compiler->resolveType(name); -} - -int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const -{ - Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer"); - *ok = false; - - if (scope != QLatin1String("Qt")) { - QQmlType *type = 0; - imports().resolveType(scope, &type, 0, 0, 0); - return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; - } - - const QMetaObject *mo = StaticQtMetaObject::get(); - int i = mo->enumeratorCount(); - while (i--) { - int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); - if (*ok) - return v; - } - return -1; -} - -const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const -{ QQmlType *qmltype = 0; - if (!imports().resolveType(name, &qmltype, 0, 0, 0)) + if (!validator->imports().resolveType(name, &qmltype, 0, 0, 0)) return 0; if (!qmltype) return 0; diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index 88282b1bbc..8bdc73fab1 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -55,15 +55,8 @@ QT_BEGIN_NAMESPACE class QQmlCompiledData; - -struct QQmlCustomParserCompilerBackend -{ - virtual ~QQmlCustomParserCompilerBackend() {} - virtual const QQmlImports &imports() const = 0; - - int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const; - const QMetaObject *resolveType(const QString& name) const; -}; +class QQmlPropertyValidator; +class QQmlEnginePrivate; class Q_QML_PRIVATE_EXPORT QQmlCustomParser { @@ -75,8 +68,8 @@ public: }; Q_DECLARE_FLAGS(Flags, Flag) - QQmlCustomParser() : compiler(0), m_flags(NoFlag) {} - QQmlCustomParser(Flags f) : compiler(0), m_flags(f) {} + QQmlCustomParser() : engine(0), validator(0), m_flags(NoFlag) {} + QQmlCustomParser(Flags f) : engine(0), validator(0), m_flags(f) {} virtual ~QQmlCustomParser() {} void clearErrors(); @@ -100,7 +93,8 @@ protected: private: QList<QQmlError> exceptions; - const QQmlCustomParserCompilerBackend *compiler; + QQmlEnginePrivate *engine; + const QQmlPropertyValidator *validator; Flags m_flags; QBiPointer<const QQmlImports, QQmlTypeNameCache> imports; friend class QQmlPropertyValidator; diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 332b99ee8f..e9700712e9 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -69,7 +69,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu { expressionFunctionValid = true; QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine); - m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction)); + m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, me, runtimeFunction)); QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(me); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 76583846f9..d0d14d9416 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1659,8 +1659,6 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, \header \li Platform \li Valid suffixes \row \li Windows \li \c .dll \row \li Unix/Linux \li \c .so - \row \li AIX \li \c .a - \row \li HP-UX \li \c .sl, \c .so (HP-UXi) \row \li OS X \li \c .dylib, \c .bundle, \c .so \endtable @@ -1677,9 +1675,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, << QLatin1String("d.dll") // try a qmake-style debug build first # endif << QLatin1String(".dll")); -#else - -# if defined(Q_OS_DARWIN) +#elif defined(Q_OS_DARWIN) return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() @@ -1693,31 +1689,8 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, << QLatin1String(".so") << QLatin1String(".bundle"), QLatin1String("lib")); -# else // Generic Unix - QStringList validSuffixList; - -# if defined(Q_OS_HPUX) -/* - See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF": - "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit), - the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix." - */ - validSuffixList << QLatin1String(".sl"); -# if defined __ia64 - validSuffixList << QLatin1String(".so"); -# endif -# elif defined(Q_OS_AIX) - validSuffixList << QLatin1String(".a") << QLatin1String(".so"); -# elif defined(Q_OS_UNIX) - validSuffixList << QLatin1String(".so"); -# endif - - // Examples of valid library names: - // libfoo.so - - return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib")); -# endif - +# else // Unix + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".so"), QLatin1String("lib")); #endif } diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp index b9f96a724c..7a801032d3 100644 --- a/src/qml/qml/qqmlinfo.cpp +++ b/src/qml/qml/qqmlinfo.cpp @@ -109,34 +109,8 @@ QQmlInfo::~QQmlInfo() if (object) { engine = qmlEngine(d->object); - QString typeName; - QQmlType *type = QQmlMetaType::qmlType(object->metaObject()); - if (type) { - typeName = type->qmlTypeName(); - int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); - if (lastSlash != -1) - typeName = typeName.mid(lastSlash+1); - } else { - typeName = QString::fromUtf8(object->metaObject()->className()); - int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); - if (marker != -1) - typeName = typeName.left(marker); - - marker = typeName.indexOf(QLatin1String("_QML_")); - if (marker != -1) { - typeName = typeName.left(marker); - typeName += QLatin1Char('*'); - type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1())); - if (type) { - typeName = type->qmlTypeName(); - int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); - if (lastSlash != -1) - typeName = typeName.mid(lastSlash+1); - } - } - } - d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": ")); + d->buffer.prepend(QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object) + QLatin1String(": ")); QQmlData *ddata = QQmlData::get(object, false); if (ddata && ddata->outerContext) { diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 967a7e75d7..5938ebf5d7 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -365,8 +365,8 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine()); QV4::Scope scope(v4); - QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, scopeObject)); - QV4::Script script(v4, qmlScopeObject, code, filename, line); + QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, scopeObject)); + QV4::Script script(v4, qmlContext, code, filename, line); QV4::ScopedValue result(scope); script.parse(); if (!v4->hasException) @@ -395,8 +395,8 @@ void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject * QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine()); QV4::Scope scope(v4); - QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, qmlScope)); - QV4::Script script(v4, qmlScopeObject, code, filename, line); + QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, qmlScope)); + QV4::Script script(v4, qmlContext, code, filename, line); QV4::ScopedValue result(scope); script.parse(); if (!v4->hasException) diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index d09f4df54c..942f4f79e7 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -45,10 +45,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlListWrapper); -Heap::QmlListWrapper::QmlListWrapper(ExecutionEngine *engine) - : Heap::Object(engine) +Heap::QmlListWrapper::QmlListWrapper() { - QV4::Scope scope(engine); + QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->setArrayType(Heap::ArrayData::Custom); } @@ -64,7 +63,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i Scope scope(engine); - Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine)); + Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>()); r->d()->object = object; r->d()->propertyType = propType; void *args[] = { &r->d()->property, 0 }; @@ -76,7 +75,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp { Scope scope(engine); - Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine)); + Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>()); r->d()->object = prop.object; r->d()->property = prop; r->d()->propertyType = propType; diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index ff006d4302..6df3d83b2e 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -62,7 +62,7 @@ namespace QV4 { namespace Heap { struct QmlListWrapper : Object { - QmlListWrapper(ExecutionEngine *engine); + QmlListWrapper(); ~QmlListWrapper(); QPointer<QObject> object; QQmlListProperty<QObject> property; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 7f49798da6..af7b394a1b 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -806,7 +806,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale) { QV4::Scope scope(v4); QV4LocaleDataDeletable *d = localeV4Data(scope.engine); - QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->alloc<QQmlLocaleData>(v4)); + QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>()); wrapper->d()->locale = locale; QV4::ScopedObject p(scope, d->prototype.value()); wrapper->setPrototype(p); diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index cb9fe9bbef..3d2ed307d1 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -125,7 +125,7 @@ namespace QV4 { namespace Heap { struct QQmlLocaleData : Object { - inline QQmlLocaleData(ExecutionEngine *engine); + inline QQmlLocaleData() {} QLocale locale; }; @@ -175,11 +175,6 @@ struct QQmlLocaleData : public QV4::Object static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx); }; -Heap::QQmlLocaleData::QQmlLocaleData(ExecutionEngine *engine) - : Heap::Object(engine) -{ -} - } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index fbb21f4562..04c001d305 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -38,6 +38,7 @@ #include <private/qqmlcustomparser_p.h> #include <private/qhashedstring_p.h> #include <private/qqmlimport_p.h> +#include <private/qqmlcompiler_p.h> #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> @@ -217,12 +218,10 @@ public: void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle()); + v4->pushGlobalContext(); if (scriptCallback && scriptApi(e).isUndefined()) { - v4->pushGlobalContext(); setScriptApi(e, scriptCallback(e, e)); - v4->popContext(); } else if (qobjectCallback && !qobjectApi(e)) { - v4->pushGlobalContext(); QObject *o = qobjectCallback(e, e); setQObjectApi(e, o); if (!o) { @@ -230,14 +229,12 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) } // if this object can use a property cache, create it now QQmlData::ensurePropertyCache(e, o); - v4->popContext(); } else if (!url.isEmpty() && !qobjectApi(e)) { - v4->pushGlobalContext(); QQmlComponent component(e, url, QQmlComponent::PreferSynchronous); QObject *o = component.create(); setQObjectApi(e, o); - v4->popContext(); } + v4->popContext(); } void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e) @@ -477,6 +474,23 @@ QQmlType *QQmlType::superType() const return d->superType; } +int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + if (!engine) + return -1; + QQmlTypeData *td = engine->typeLoader.getType(sourceUrl()); + if (!td || !td->isComplete()) + return -1; + QQmlCompiledData *cd = td->compiledData(); + const QMetaObject *mo = cd->rootPropertyCache->firstCppMetaObject(); + QQmlType *type = QQmlMetaType::qmlType(mo); + if (!type) + return -1; + return type->enumValue(engine, name, ok); +} + static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -911,9 +925,11 @@ QUrl QQmlType::sourceUrl() const return QUrl(); } -int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const +int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const { Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeEnumValue(engine, name.toString(), ok); *ok = true; d->initEnums(); @@ -926,9 +942,11 @@ int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const return -1; } -int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const +int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const { Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeEnumValue(engine, name.toUtf16(), ok); *ok = true; d->initEnums(); @@ -941,9 +959,11 @@ int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const return -1; } -int QQmlType::enumValue(const QV4::String *name, bool *ok) const +int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const { Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeEnumValue(engine, name->toQString(), ok); *ok = true; d->initEnums(); @@ -1888,4 +1908,43 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const return 0; } +/*! + Returns the pretty QML type name (e.g. 'Item' instead of 'QtQuickItem') for the given object. + */ +QString QQmlMetaType::prettyTypeName(const QObject *object) +{ + QString typeName; + + if (!object) + return typeName; + + const QQmlType *type = QQmlMetaType::qmlType(object->metaObject()); + if (type) { + typeName = type->qmlTypeName(); + const int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash + 1); + } else { + typeName = QString::fromUtf8(object->metaObject()->className()); + int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); + if (marker != -1) + typeName = typeName.left(marker); + + marker = typeName.indexOf(QLatin1String("_QML_")); + if (marker != -1) { + typeName = typeName.left(marker); + typeName += QLatin1Char('*'); + type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1())); + if (type) { + typeName = type->qmlTypeName(); + const int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash + 1); + } + } + } + + return typeName; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 61a6567f1d..40765d461a 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QQmlType; class QQmlEngine; +class QQmlEnginePrivate; class QQmlCustomParser; class QQmlTypePrivate; class QQmlTypeModule; @@ -122,6 +123,8 @@ public: static QStringList typeRegistrationFailures(); static QMutex *typeRegistrationLock(); + + static QString prettyTypeName(const QObject *object); }; struct QQmlMetaTypeData; @@ -204,11 +207,12 @@ public: QUrl sourceUrl() const; - int enumValue(const QHashedStringRef &, bool *ok) const; - int enumValue(const QHashedCStringRef &, bool *ok) const; - int enumValue(const QV4::String *, bool *ok) const; + int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const; + int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const; + int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; private: QQmlType *superType() const; + int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; friend class QQmlTypePrivate; friend struct QQmlMetaTypeData; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 0e7ce7fb7e..765437b423 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -185,9 +185,10 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI if (subComponentIndex == -1 && compiledData->scripts.count()) { QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count())); context->importedScripts.set(v4, scripts); + QV4::ScopedValue v(scope); for (int i = 0; i < compiledData->scripts.count(); ++i) { QQmlScriptData *s = compiledData->scripts.at(i); - scripts->putIndexed(i, *s->scriptValueForContext(context).valueRef()); + scripts->putIndexed(i, (v = s->scriptValueForContext(context))); } } else if (sharedState->creationContext) { context->importedScripts = sharedState->creationContext->importedScripts; @@ -988,13 +989,9 @@ void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject * QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext() { - if (!_qmlContext->objectValue()) { - QV4::Scope valueScope(v4); - QV4::Scoped<QV4::QmlContextWrapper> qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject)); - QV4::ScopedContext global(valueScope, v4->rootContext()); - _qmlContext->setM(global->newQmlContext(qmlScope)); - v4->popContext(); - } + if (!_qmlContext->objectValue()) + _qmlContext->setM(v4->rootContext()->newQmlContext(context, _scopeObject)); + return _qmlContext->d(); } @@ -1106,6 +1103,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo if (customParser) { QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index); if (customParserBindings != compiledData->customParserBindings.constEnd()) { + customParser->engine = QQmlEnginePrivate::get(engine); customParser->imports = compiledData->importCache; QList<const QV4::CompiledData::Binding *> bindings; @@ -1115,6 +1113,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo bindings << obj->bindingTable() + i; customParser->applyBindings(instance, compiledData, bindings); + customParser->engine = 0; customParser->imports = (QQmlTypeNameCache*)0; bindingsToSkip = *customParserBindings; } diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index c1120b4542..d3f7070528 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -50,6 +50,7 @@ #include "qqmlvaluetypeproxybinding_p.h" #include <private/qjsvalue_p.h> #include <private/qv4functionobject_p.h> +#include <private/qv4runtime_p.h> #include <QStringList> #include <private/qmetaobject_p.h> @@ -1350,7 +1351,12 @@ bool QQmlPropertyPrivate::write(QObject *object, if (!ok) { v = value; - if (v.convert(propertyType)) { + if (variantType == QVariant::Double && propertyType == QVariant::String) { + QString number; + QV4::RuntimeHelpers::numberToString(&number, v.toDouble()); + v = number; + ok = true; + } else if (v.convert(propertyType)) { ok = true; } else if (v.isValid() && value.isNull()) { // For historical reasons converting a null QVariant to another type will do the trick diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index eb65f732dd..270c28c399 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2471,12 +2471,10 @@ void QQmlScriptData::initialize(QQmlEngine *engine) addref(); } -QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt) +QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt) { if (m_loaded) - return m_value; - - QV4::PersistentValue rv; + return m_value.value(); Q_ASSERT(parentCtxt && parentCtxt->engine); QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine); @@ -2526,8 +2524,9 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare } else { scriptsArray = ctxt->importedScripts.valueRef(); } + QV4::ScopedValue v(scope); for (int ii = 0; ii < scripts.count(); ++ii) - scriptsArray->putIndexed(ii, *scripts.at(ii)->scriptData()->scriptValueForContext(ctxt).valueRef()); + scriptsArray->putIndexed(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt))); if (!hasEngine()) initialize(parentCtxt->engine); @@ -2535,13 +2534,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare if (!m_program) { if (shared) m_loaded = true; - return QV4::PersistentValue(); + return QV4::Encode::undefined(); } - QV4::Scoped<QV4::QmlContextWrapper> qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0)); - qmlglobal->takeContextOwnership(); + QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, 0)); + qmlContext->takeContextOwnership(); - m_program->qml.set(scope.engine, qmlglobal); + m_program->qmlContext.set(scope.engine, qmlContext); m_program->run(); if (scope.engine->hasException) { QQmlError error = scope.engine->catchExceptionAsQmlError(); @@ -2549,13 +2548,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare ep->warning(error); } - rv.set(scope.engine, qmlglobal); + QV4::ScopedValue retval(scope, qmlContext->d()->qml); if (shared) { - m_value = rv; + m_value.set(scope.engine, retval); m_loaded = true; } - return rv; + return retval->asReturnedValue(); } void QQmlScriptData::clear() diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5be478fa65..e7b4b8f95b 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -474,7 +474,7 @@ public: QQmlTypeNameCache *importCache; QList<QQmlScriptBlob *> scripts; - QV4::PersistentValue scriptValueForContext(QQmlContextData *parentCtxt); + QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt); protected: virtual void clear(); // From QQmlCleanup diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 1d72b2da0d..d70a4019b2 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -48,12 +48,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlTypeWrapper); -Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine) - : Heap::Object(engine) - , mode(IncludeEnums) - , type(Q_NULLPTR) - , typeNamespace(Q_NULLPTR) - , importNamespace(Q_NULLPTR) +Heap::QmlTypeWrapper::QmlTypeWrapper() + : mode(IncludeEnums) { } @@ -103,7 +99,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q Q_ASSERT(t); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine)); + Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->type = t; return w.asReturnedValue(); } @@ -117,7 +113,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q Q_ASSERT(importNamespace); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine)); + Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace; t->addref(); return w.asReturnedValue(); @@ -182,7 +178,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (name->startsWithUpper()) { bool ok = false; - int value = type->enumValue(name, &ok); + int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 14741a5bad..e67b457c59 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -66,7 +66,7 @@ struct QmlTypeWrapper : Object { ExcludeEnums }; - QmlTypeWrapper(QV4::ExecutionEngine *engine); + QmlTypeWrapper(); ~QmlTypeWrapper(); TypeNameMode mode; QPointer<QObject> object; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index b0ab85199d..8ddf91ef3c 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -55,7 +55,7 @@ namespace Heap { struct QQmlValueTypeReference : QQmlValueTypeWrapper { - QQmlValueTypeReference(ExecutionEngine *engine); + QQmlValueTypeReference() {} QPointer<QObject> object; int property; }; @@ -77,11 +77,6 @@ DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference); using namespace QV4; -Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine) - : Heap::Object(engine) -{ -} - Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper() { if (gadgetPtr) { @@ -107,11 +102,6 @@ QVariant Heap::QQmlValueTypeWrapper::toVariant() const } -Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine) - : Heap::QQmlValueTypeWrapper(engine) -{ -} - bool QQmlValueTypeReference::readReferenceValue() const { if (!d()->object) @@ -164,7 +154,7 @@ bool QQmlValueTypeReference::readReferenceValue() const void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4) { - if (v4->valueTypeWrapperPrototype()->as<Object>()) + if (v4->valueTypeWrapperPrototype()->d()) return; Scope scope(v4); @@ -178,10 +168,9 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj Scope scope(engine); initProto(engine); - Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine)); - ScopedObject proto(scope, engine->valueTypeWrapperPrototype()); - r->setPrototype(proto); - r->d()->object = object; r->d()->property = property; + Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>()); + r->d()->object = object; + r->d()->property = property; r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); r->d()->gadgetPtr = 0; @@ -193,9 +182,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria Scope scope(engine); initProto(engine); - Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine)); - ScopedObject proto(scope, engine->valueTypeWrapperPrototype()); - r->setPrototype(proto); + Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>()); r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); r->d()->gadgetPtr = 0; @@ -345,12 +332,9 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha if (hasProperty) *hasProperty = true; - if (result->isFunction()) { + if (result->isFunction()) // calling a Q_INVOKABLE function of a value type - Scope scope(v4); - ScopedContext c(scope, v4->rootContext()); - return QV4::QObjectMethod::create(c, r, result->coreIndex); - } + return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex); #define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \ if (result->propType == metatype) { \ diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index 5f0edfb71d..156b4c85d8 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct QQmlValueTypeWrapper : Object { - QQmlValueTypeWrapper(ExecutionEngine *engine); + QQmlValueTypeWrapper() {} ~QQmlValueTypeWrapper(); QQmlRefPointer<QQmlPropertyCache> propertyCache; mutable void *gadgetPtr; @@ -76,6 +76,7 @@ struct QQmlValueTypeWrapper : Object { struct Q_QML_EXPORT QQmlValueTypeWrapper : Object { V4_OBJECT2(QQmlValueTypeWrapper, Object) + V4_PROTOTYPE(valueTypeWrapperPrototype) static void destroy(Heap::Base *b); public: diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 427e751f5d..dcf95b0c69 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -271,8 +271,6 @@ public: QList<QQmlVMEVariantQObjectPtr *> varObjectGuards; QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const; - - friend class QV8GCCallback; }; QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj) diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index de7741675b..8666c0db01 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -170,7 +170,7 @@ public: namespace Heap { struct NamedNodeMap : Object { - NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list); + NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list); ~NamedNodeMap() { if (d) d->release(); @@ -180,7 +180,7 @@ struct NamedNodeMap : Object { }; struct NodeList : Object { - NodeList(ExecutionEngine *engine, NodeImpl *data); + NodeList(NodeImpl *data); ~NodeList() { if (d) d->release(); @@ -189,11 +189,11 @@ struct NodeList : Object { }; struct NodePrototype : Object { - NodePrototype(ExecutionEngine *engine); + NodePrototype(); }; struct Node : Object { - Node(ExecutionEngine *engine, NodeImpl *data); + Node(NodeImpl *data); ~Node() { if (d) d->release(); @@ -217,9 +217,8 @@ public: static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); }; -Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list) - : Heap::Object(engine) - , list(list) +Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list) + : list(list) , d(data) { if (d) @@ -243,9 +242,8 @@ public: }; -Heap::NodeList::NodeList(ExecutionEngine *engine, NodeImpl *data) - : Heap::Object(engine) - , d(data) +Heap::NodeList::NodeList(NodeImpl *data) + : d(data) { if (d) d->addref(); @@ -285,10 +283,9 @@ public: }; -Heap::NodePrototype::NodePrototype(ExecutionEngine *engine) - : Heap::Object(engine) +Heap::NodePrototype::NodePrototype() { - Scope scope(engine); + Scope scope(internalClass->engine); ScopedObject o(scope, this); o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0); @@ -323,9 +320,8 @@ private: Node(const Node &o); }; -Heap::Node::Node(ExecutionEngine *engine, NodeImpl *data) - : Heap::Object(engine) - , d(data) +Heap::Node::Node(NodeImpl *data) + : d(data) { if (d) d->addref(); @@ -584,7 +580,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4) Scope scope(v4); QQmlXMLHttpRequestData *d = xhrdata(v4); if (d->nodePrototype.isUndefined()) { - ScopedObject p(scope, v4->memoryManager->alloc<NodePrototype>(v4)); + ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>()); d->nodePrototype.set(v4, p); v4->v8Engine->freezeObject(p); } @@ -595,7 +591,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data) { Scope scope(v4); - Scoped<Node> instance(scope, v4->memoryManager->alloc<Node>(v4, data)); + Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data)); ScopedObject p(scope); switch (data->type) { @@ -863,7 +859,7 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data) return Encode::null(); } - ScopedObject instance(scope, v4->memoryManager->alloc<Node>(v4, document)); + ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document)); ScopedObject p(scope); instance->setPrototype((p = Document::prototype(v4))); return instance.asReturnedValue(); @@ -916,7 +912,7 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list) { - return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue(); + return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue(); } ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty) @@ -950,7 +946,7 @@ ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty) ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data) { - return (v4->memoryManager->alloc<NodeList>(v4, data))->asReturnedValue(); + return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue(); } ReturnedValue Document::method_documentElement(CallContext *ctx) @@ -1588,7 +1584,7 @@ namespace QV4 { namespace Heap { struct QQmlXMLHttpRequestWrapper : Object { - QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request); + QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request); ~QQmlXMLHttpRequestWrapper() { delete request; } @@ -1609,9 +1605,8 @@ struct QQmlXMLHttpRequestWrapper : public Object V4_NEEDS_DESTROY }; -Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request) - : Heap::Object(engine) - , request(request) +Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request) + : request(request) { } @@ -1632,7 +1627,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject return scope.engine->throwTypeError(); QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager()); - Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(scope.engine, r)); + Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r)); ScopedObject proto(scope, ctor->d()->proto); w->setPrototype(proto); return w.asReturnedValue(); @@ -2034,7 +2029,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4) { Scope scope(v4); - Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4)); + Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4)); ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest"))); v4->globalObject->defineReadonlyProperty(s, ctor); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 239bc53f0a..5986fdbdfa 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -80,10 +80,9 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; -Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine) - : Heap::Object(v4) +Heap::QtObject::QtObject(QQmlEngine *qmlEngine) { - Scope scope(v4); + Scope scope(internalClass->engine); ScopedObject o(scope, this); // Set all the enums from the "Qt" namespace @@ -93,11 +92,11 @@ Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine) for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { QMetaEnum enumerator = qtMetaObject->enumerator(ii); for (int jj = 0; jj < enumerator.keyCount(); ++jj) { - o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj)))); + o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj)))); } } - o->put((str = v4->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0))); - o->put((str = v4->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1))); + o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0))); + o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1))); o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include); o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject); @@ -1262,7 +1261,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx) if (!f) V4THROW_TYPE("binding(): argument (binding expression) must be a function"); - return (ctx->d()->engine->memoryManager->alloc<QQmlBindingFunction>(f))->asReturnedValue(); + return (ctx->d()->engine->memoryManager->allocObject<QQmlBindingFunction>(f))->asReturnedValue(); } @@ -1315,10 +1314,9 @@ ReturnedValue QtObject::method_get_styleHints(CallContext *ctx) } -QV4::Heap::ConsoleObject::ConsoleObject(ExecutionEngine *v4) - : Heap::Object(v4) +QV4::Heap::ConsoleObject::ConsoleObject() { - QV4::Scope scope(v4); + QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->defineDefaultProperty(QStringLiteral("debug"), QV4::ConsoleObject::method_log); @@ -1609,10 +1607,10 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject) globalObject->defineDefaultProperty(QStringLiteral("print"), ConsoleObject::method_log); globalObject->defineDefaultProperty(QStringLiteral("gc"), method_gc); - ScopedObject console(scope, v4->memoryManager->alloc<QV4::ConsoleObject>(v4)); + ScopedObject console(scope, v4->memoryManager->allocObject<QV4::ConsoleObject>()); globalObject->defineDefaultProperty(QStringLiteral("console"), console); - ScopedObject qt(scope, v4->memoryManager->alloc<QV4::QtObject>(v4, qmlEngine)); + ScopedObject qt(scope, v4->memoryManager->allocObject<QV4::QtObject>(qmlEngine)); globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt); // string prototype extension @@ -1737,10 +1735,10 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) int lastDot = path.lastIndexOf(QLatin1Char('.')); int length = lastDot - (lastSlash + 1); context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString(); - } else if (ctx->d()->parent) { - ScopedContext parentCtx(scope, ctx->d()->parent); + } else { + ExecutionContext *parentCtx = scope.engine->parentContext(ctx); // The first non-empty source URL in the call stack determines the translation context. - while (parentCtx && context.isEmpty()) { + while (!!parentCtx && context.isEmpty()) { if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) { QString fileName = unit->fileName(); QUrl url(unit->fileName()); @@ -1753,7 +1751,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) } context = QFileInfo(context).baseName(); } - parentCtx = parentCtx->d()->parent; + parentCtx = scope.engine->parentContext(parentCtx); } } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index bdd53fe601..bb05376fc0 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -58,13 +58,13 @@ namespace QV4 { namespace Heap { struct QtObject : Object { - QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine); + QtObject(QQmlEngine *qmlEngine); QObject *platform; QObject *application; }; struct ConsoleObject : Object { - ConsoleObject(ExecutionEngine *engine); + ConsoleObject(); }; struct QQmlBindingFunction : FunctionObject { diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 6cb316ce9f..effc37a0eb 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -191,41 +191,47 @@ void QV8Engine::initializeGlobal() m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string); } } +} - { -#define FREEZE_SOURCE "(function freeze_recur(obj) { "\ - " if (Qt.isQtObject(obj)) return;"\ - " if (obj != Function.connect && obj != Function.disconnect && "\ - " obj instanceof Object) {"\ - " var properties = Object.getOwnPropertyNames(obj);"\ - " for (var prop in properties) { "\ - " if (prop == \"connect\" || prop == \"disconnect\") {"\ - " Object.freeze(obj[prop]); "\ - " continue;"\ - " }"\ - " freeze_recur(obj[prop]);"\ - " }"\ - " }"\ - " if (obj instanceof Object) {"\ - " Object.freeze(obj);"\ - " }"\ - "})" - - QV4::ScopedFunctionObject result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0)); - Q_ASSERT(!!result); - m_freezeObject.set(scope.engine, result); -#undef FREEZE_SOURCE +static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object) +{ + if (object->as<QV4::QObjectWrapper>()) + return; + + QV4::Scope scope(v4); + + bool instanceOfObject = false; + QV4::ScopedObject p(scope, object->prototype()); + while (p) { + if (p->d() == v4->objectPrototype()->d()) { + instanceOfObject = true; + break; + } + p = p->prototype(); + } + if (!instanceOfObject) + return; + + QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen(); + if (object->internalClass() == frozen) + return; + object->setInternalClass(frozen); + + QV4::ScopedObject o(scope); + for (uint i = 0; i < frozen->size; ++i) { + if (!frozen->nameMap.at(i)) + continue; + o = *object->propertyData(i); + if (o) + freeze_recursive(v4, o); } } void QV8Engine::freezeObject(const QV4::Value &value) { QV4::Scope scope(m_v4Engine); - QV4::ScopedFunctionObject f(scope, m_freezeObject.value()); - QV4::ScopedCallData callData(scope, 1); - callData->args[0] = value; - callData->thisObject = m_v4Engine->globalObject; - f->call(callData); + QV4::ScopedObject o(scope, value); + freeze_recursive(m_v4Engine, o); } struct QV8EngineRegistrationData diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 08bbbb8548..552470c88c 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -120,8 +120,6 @@ class QQmlV4Function public: int length() const { return callData->argc; } QV4::ReturnedValue operator[](int idx) { return (idx < callData->argc ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); } - QQmlContextData *context() { return e->qmlContextObject()->context.contextData(); } - QV4::ReturnedValue qmlGlobal() { return e->qmlContextObject()->asReturnedValue(); } void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; } QV4::ExecutionEngine *v4engine() const { return e; } private: @@ -219,8 +217,6 @@ protected: QV4::ExecutionEngine *m_v4Engine; - QV4::PersistentValue m_freezeObject; - void *m_xmlHttpRequestData; QVector<Deletable *> m_extensionData; |