aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qml/doc/src/qml-extending.qdoc2
-rw-r--r--examples/quick/text/doc/src/text.qdoc2
-rw-r--r--src/imports/localstorage/plugin.cpp17
-rw-r--r--src/particles/qquickv4particledata.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp29
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp24
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp25
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h7
-rw-r--r--src/qml/compiler/qv4ssa.cpp2
-rw-r--r--src/qml/debugger/qqmldebug.cpp2
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp6
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc2
-rw-r--r--src/qml/jsapi/qjsengine.cpp9
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp31
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp12
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h5
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp13
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h37
-rw-r--r--src/qml/jsruntime/qv4context.cpp71
-rw-r--r--src/qml/jsruntime/qv4context_p.h26
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp31
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h3
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp25
-rw-r--r--src/qml/jsruntime/qv4engine.cpp305
-rw-r--r--src/qml/jsruntime/qv4engine_p.h78
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp165
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h91
-rw-r--r--src/qml/jsruntime/qv4function.cpp31
-rw-r--r--src/qml/jsruntime/qv4function_p.h7
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp127
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h17
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h2
-rw-r--r--src/qml/jsruntime/qv4include.cpp23
-rw-r--r--src/qml/jsruntime/qv4include_p.h6
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp87
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h1
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp92
-rw-r--r--src/qml/jsruntime/qv4managed.cpp24
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp239
-rw-r--r--src/qml/jsruntime/qv4object_p.h113
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp4
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h7
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp12
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp119
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h11
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp79
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h29
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp119
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h83
-rw-r--r--src/qml/jsruntime/qv4script.cpp95
-rw-r--r--src/qml/jsruntime/qv4script_p.h30
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp23
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp11
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp26
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h11
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp9
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h7
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp14
-rw-r--r--src/qml/memory/qv4mm.cpp68
-rw-r--r--src/qml/memory/qv4mm_p.h167
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp17
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp13
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp31
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h18
-rw-r--r--src/qml/qml/qqmlexpression.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp33
-rw-r--r--src/qml/qml/qqmlinfo.cpp28
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp8
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp9
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h2
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmllocale_p.h7
-rw-r--r--src/qml/qml/qqmlmetatype.cpp77
-rw-r--r--src/qml/qml/qqmlmetatype_p.h10
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp15
-rw-r--r--src/qml/qml/qqmlproperty.cpp8
-rw-r--r--src/qml/qml/qqmltypeloader.cpp23
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp14
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp32
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h3
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp49
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp30
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp62
-rw-r--r--src/qml/qml/v8/qv8engine_p.h4
-rw-r--r--src/qml/types/qqmlbind.cpp36
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp26
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h7
-rw-r--r--src/qml/types/qqmlitemselectionmodel.qdoc2
-rw-r--r--src/qml/types/qqmllistmodel.cpp26
-rw-r--r--src/qml/types/qqmllistmodel_p.h1
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h4
-rw-r--r--src/qml/types/qquickworkerscript.cpp26
-rw-r--r--src/qml/util/qqmladaptormodel.cpp10
-rw-r--r--src/qml/util/qqmllistcompositor_p.h12
-rw-r--r--src/qml/util/qqmlpropertymap.cpp3
-rw-r--r--src/qmltest/quicktest.cpp2
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp53
-rw-r--r--src/quick/items/qquicklistview.cpp9
-rw-r--r--src/quick/items/qquickloader.cpp2
-rw-r--r--src/quick/items/qquickmousearea.cpp1
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp6
-rw-r--r--src/quick/items/qquickpainteditem.cpp117
-rw-r--r--src/quick/items/qquickpainteditem.h6
-rw-r--r--src/quick/items/qquickpainteditem_p.h1
-rw-r--r--src/quick/items/qquicktext.cpp18
-rw-r--r--src/quick/items/qquicktext_p.h2
-rw-r--r--src/quick/items/qquicktext_p_p.h2
-rw-r--r--src/quick/items/qquicktextcontrol.cpp18
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h3
-rw-r--r--src/quick/items/qquicktextedit.cpp2
-rw-r--r--src/quick/items/qquicktextinput.cpp2
-rw-r--r--src/quick/items/qquickview.cpp2
-rw-r--r--src/quick/items/qquickview_p.h12
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h6
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode.cpp62
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode_p.h29
-rw-r--r--src/quick/util/qquickimageprovider.cpp4
-rw-r--r--src/quick/util/qquickpropertychanges.cpp2
-rw-r--r--src/quickwidgets/qquickwidget.cpp5
-rw-r--r--tests/auto/qml/qqmlbinding/data/readonlyProperty.qml13
-rw-r--r--tests/auto/qml/qqmlbinding/data/unknownProperty.qml11
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp34
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_46022.js21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml7
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp11
-rw-r--r--tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h11
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp17
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp31
-rw-r--r--tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml10
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp22
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug48044.qml144
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp37
-rw-r--r--tests/auto/quick/qquicktext/data/fontSizeMode.qml4
-rw-r--r--tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml2
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp10
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp40
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp6
-rw-r--r--tests/auto/shared/testhttpserver.cpp170
-rw-r--r--tests/auto/shared/testhttpserver.h21
-rw-r--r--tests/manual/v4/crypto.js1
-rw-r--r--tests/manual/v4/typedarrays.js35
-rw-r--r--tools/qml/main.cpp3
-rw-r--r--tools/qmljs/qmljs.cpp4
-rw-r--r--tools/qmlplugindump/main.cpp2
-rw-r--r--tools/qmlscene/main.cpp53
172 files changed, 2677 insertions, 1914 deletions
diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc
index 77ccd2f1e9..e5b364e0bc 100644
--- a/examples/qml/doc/src/qml-extending.qdoc
+++ b/examples/qml/doc/src/qml-extending.qdoc
@@ -73,7 +73,7 @@ This example builds on:
\li \l {Extending QML - Adding Types Example}
\endlist
-Shows how to use \l qmlRegisterExtendedType() to provide an \l {Registering
+Shows how to use \l {QQmlEngine::}{qmlRegisterExtendedType()} to provide an \l {Registering
Extension Objects}{extension object} to a \l QLineEdit without modifying or
subclassing. The QML engine instantiates a \l QLineEdit and sets a property that
only exists on the extension type. The extension type performs calls on the \l
diff --git a/examples/quick/text/doc/src/text.qdoc b/examples/quick/text/doc/src/text.qdoc
index 7ac33da563..ea6a786e8a 100644
--- a/examples/quick/text/doc/src/text.qdoc
+++ b/examples/quick/text/doc/src/text.qdoc
@@ -60,7 +60,7 @@
\section1 Available Fonts
- \e{Available Fonts} shows how to use the QML \l{QtQml::Qt}{Qt} global object
+ \e{Available Fonts} shows how to use the \l [QML] {Qt} global object
and a list view to display all the fonts available on the system.
The \l ListView type uses the list of fonts available as its model:
\snippet text/fonts/availableFonts.qml model
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 22a3eed39d..ada50774a7 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE
QV4::ScopedString v(scope, scope.engine->newString(desc)); \
QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Primitive::fromInt32(error))); \
- args->setReturnValue(ctx->engine()->throwError(ex)); \
+ args->setReturnValue(scope.engine->throwError(ex)); \
return; \
}
@@ -97,7 +97,10 @@ namespace QV4 {
namespace Heap {
struct QQmlSqlDatabaseWrapper : public Object {
enum Type { Database, Query, Rows };
- QQmlSqlDatabaseWrapper(ExecutionEngine *e);
+ QQmlSqlDatabaseWrapper()
+ {
+ type = Database;
+ }
Type type;
QSqlDatabase database;
@@ -120,7 +123,7 @@ public:
static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
{
- return engine->memoryManager->alloc<QQmlSqlDatabaseWrapper>(engine);
+ return engine->memoryManager->allocObject<QQmlSqlDatabaseWrapper>();
}
~QQmlSqlDatabaseWrapper() {
@@ -135,11 +138,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
-QV4::Heap::QQmlSqlDatabaseWrapper::QQmlSqlDatabaseWrapper(ExecutionEngine *e)
- : QV4::Heap::Object(e)
-{
- type = Database;
-}
+
static ReturnedValue qmlsqldatabase_version(CallContext *ctx)
{
@@ -659,7 +658,6 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
{
#ifndef QT_NO_SETTINGS
QV4::Scope scope(args->v4engine());
- QV4::ScopedContext ctx(scope, args->v4engine()->currentContext());
if (scope.engine->qmlEngine()->offlineStoragePath().isEmpty())
V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled."));
@@ -721,7 +719,6 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
db->d()->version = version;
if (created && dbcreationCallback) {
- Scope scope(ctx);
ScopedCallData callData(scope, 1);
callData->thisObject = scope.engine->globalObject;
callData->args[0] = db;
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index fcab455cce..876c7214b0 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -266,9 +266,8 @@ QT_BEGIN_NAMESPACE
struct QV4ParticleData : public QV4::Object
{
struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
- : QV4::Heap::Object(engine)
- , datum(datum)
+ Data(QQuickParticleData *datum)
+ : datum(datum)
{
}
QQuickParticleData* datum;//TODO: Guard needed?
@@ -506,7 +505,7 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4ParticleDataDeletable *d = particleV4Data(scope.engine);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QV4ParticleData>(v4, datum));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QV4ParticleData>(datum));
QV4::ScopedObject p(scope, d->proto.value());
o->setPrototype(p);
m_v4Value = o;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index ff29814de6..b13c469893 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -43,32 +43,28 @@
QT_BEGIN_NAMESPACE
-QV4::Heap::CallContext *QV4DataCollector::findContext(QV4::Heap::ExecutionContext *ctxt, int frame)
+QV4::CallContext *QV4DataCollector::findContext(QV4::ExecutionEngine *engine, int frame)
{
- if (!ctxt)
- return 0;
-
- QV4::Scope scope(ctxt->engine);
- QV4::ScopedContext ctx(scope, ctxt);
+ QV4::ExecutionContext *ctx = engine->currentContext;
while (ctx) {
QV4::CallContext *cCtxt = ctx->asCallContext();
if (cCtxt && cCtxt->d()->function) {
if (frame < 1)
- return cCtxt->d();
+ return cCtxt;
--frame;
}
- ctx = ctx->d()->parent;
+ ctx = engine->parentContext(ctx);
}
return 0;
}
-QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctxt, int scope)
+QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope)
{
if (!ctxt)
return 0;
- QV4::Scope s(ctxt->engine);
+ QV4::Scope s(ctxt->d()->engine);
QV4::ScopedContext ctx(s, ctxt);
for (; scope > 0 && ctx; --scope)
ctx = ctx->d()->outer;
@@ -82,11 +78,11 @@ QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeType
QVector<QV4::Heap::ExecutionContext::ContextType> types;
QV4::Scope scope(engine);
- QV4::Scoped<QV4::CallContext> sctxt(scope, findContext(engine->currentContext(), frame));
+ QV4::CallContext *sctxt = findContext(engine, frame);
if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
return types;
- QV4::ScopedContext it(scope, sctxt->d());
+ QV4::ScopedContext it(scope, sctxt);
for (; it; it = it->d()->outer)
types.append(it->d()->type);
@@ -382,8 +378,7 @@ void ArgumentCollectJob::run()
QV4::Scope scope(engine);
QV4::Scoped<QV4::CallContext> ctxt(
- scope, QV4DataCollector::findScope(
- QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
if (!ctxt)
return;
@@ -415,8 +410,7 @@ void LocalCollectJob::run()
QV4::Scope scope(engine);
QV4::Scoped<QV4::CallContext> ctxt(
- scope, QV4DataCollector::findScope(
- QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
if (!ctxt)
return;
@@ -447,8 +441,7 @@ void ThisCollectJob::run()
bool ThisCollectJob::myRun()
{
QV4::Scope scope(engine);
- QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine->currentContext(),
- frameNr));
+ QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine, frameNr));
while (ctxt) {
if (QV4::CallContext *cCtxt = ctxt->asCallContext())
if (cCtxt->d()->activation)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index 39aed5b868..39d621e95e 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -45,8 +45,8 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::CallContext *findContext(QV4::Heap::ExecutionContext *ctxt, int frame);
- static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
+ static QV4::CallContext *findContext(QV4::ExecutionEngine *engine, int frame);
+ static QV4::Heap::CallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
static QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(
QV4::ExecutionEngine *engine, int frame);
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index 6af43b1823..d3a8d1f0d1 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -223,27 +223,21 @@ void QQmlDebugServerThread::run()
Q_ASSERT_X(m_server != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
QQmlDebugServerConnection *connection = loadQQmlDebugServerConnection(m_pluginName);
if (connection) {
- connection->setServer(m_server);
-
- if (m_fileName.isEmpty()) {
- if (!connection->setPortRange(m_portFrom, m_portTo, m_server->blockingMode(),
- m_hostAddress)) {
- delete connection;
- return;
- }
- } else {
- if (!connection->setFileName(m_fileName, m_server->blockingMode())) {
- delete connection;
- return;
- }
- }
-
{
QMutexLocker connectionLocker(&m_server->m_helloMutex);
m_server->m_connection = connection;
+ connection->setServer(m_server);
m_server->m_helloCondition.wakeAll();
}
+ if (m_fileName.isEmpty()) {
+ if (!connection->setPortRange(m_portFrom, m_portTo, m_server->blockingMode(),
+ m_hostAddress))
+ return;
+ } else if (!connection->setFileName(m_fileName, m_server->blockingMode())) {
+ return;
+ }
+
if (m_server->blockingMode())
connection->waitForConnection();
} else {
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 4b1e3601dc..7b0d4240c4 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1590,7 +1590,7 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
if (member->name->constData()->isUpper()) {
bool ok = false;
- int value = type->enumValue(*member->name, &ok);
+ int value = type->enumValue(qmlEngine, *member->name, &ok);
if (ok) {
member->setEnumValue(value);
resolver->clear();
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 80ffafda72..e36ba76326 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1163,8 +1163,6 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
if (!type && typeName != QLatin1String("Qt"))
return true;
- if (type && type->isComposite()) //No enums on composite (or composite singleton) types
- return true;
int value = 0;
bool ok = false;
@@ -1182,7 +1180,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
} else {
// Otherwise we have to search the whole type
if (type) {
- value = type->enumValue(QHashedStringRef(enumValue), &ok);
+ value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
} else {
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = StaticQtMetaObject::get();
@@ -1210,7 +1208,9 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
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;
+ if (!type)
+ return -1;
+ return type ? type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
}
const QMetaObject *mo = StaticQtMetaObject::get();
@@ -1719,17 +1719,6 @@ const QQmlImports &QQmlPropertyValidator::imports() const
return *compiler->imports();
}
-QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const
-{
- const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex);
- if (!object)
- return QString();
- int reverseIndex = object->runtimeFunctionIndices->indexOf(binding->value.compiledScriptIndex);
- if (reverseIndex == -1)
- return QString();
- return compiler->bindingAsString(object, reverseIndex);
-}
-
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
struct BindingFinder
@@ -1998,10 +1987,12 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
- customParser->compiler = this;
+ customParser->validator = this;
+ customParser->engine = enginePrivate;
customParser->imports = compiler->imports();
customParser->verifyBindings(qmlUnit, customBindings);
- customParser->compiler = 0;
+ customParser->validator = 0;
+ customParser->engine = 0;
customParser->imports = (QQmlImports*)0;
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 75987af656..09ef7aad67 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -264,7 +264,7 @@ protected:
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
};
-class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend
+class QQmlPropertyValidator : public QQmlCompilePass
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
@@ -272,9 +272,8 @@ public:
bool validate();
- // Re-implemented for QQmlCustomParser
- virtual const QQmlImports &imports() const;
- virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
+ const QQmlImports &imports() const;
+ QQmlEnginePrivate *engine() const { return enginePrivate; }
private:
bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c150666a11..32169f3352 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3504,7 +3504,7 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
}
#endif
-void cleanupBasicBlocks(IR::Function *function)
+static void cleanupBasicBlocks(IR::Function *function)
{
showMeTheCode(function, "Before basic block cleanup");
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 64004fc86a..b308f5aa29 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -147,6 +147,8 @@ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const Q
}
/*!
+ * \since 5.6
+ *
* Enables debugging for QML engines created after calling this function. The debug connector will
* connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
* engine until the connection is established if \a mode is \c WaitForClient. If \a mode is not
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index 8de734fa68..460cb8f203 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -107,9 +107,9 @@ QQmlDebugConnector *QQmlDebugConnector::instance()
if (!QQmlEnginePrivate::qml_debugging_enabled) {
if (!params->arguments.isEmpty()) {
- qWarning() << QString::fromLatin1(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging has not "
- "been enabled.").arg(params->arguments);
+ qWarning().noquote() << QString::fromLatin1(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging "
+ "has not been enabled.").arg(params->arguments);
params->arguments.clear();
}
return 0;
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 54ed3f1e6e..426848f6e6 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -314,7 +314,7 @@ merged with the original target class when used from within QML. For example:
The \c leftMargin property is a new property added to an existing C++ type, \l
QLineEdit, without modifying its source code.
-The \l qmlRegisterExtendedType() function is for registering extended types.
+The \l {QQmlEngine::}{qmlRegisterExtendedType()} function is for registering extended types.
Note that it has two forms.
\code
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 4910b6a1c6..b217d3fb4c 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -317,7 +317,9 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
{
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
- QV4::ScopedContext ctx(scope, v4->currentContext());
+ QV4::ExecutionContextSaver saver(scope);
+
+ QV4::ExecutionContext *ctx = v4->currentContext;
if (ctx->d() != v4->rootContext()->d())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -330,8 +332,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
- if (ctx->d() != v4->rootContext()->d())
- v4->popContext();
+
return QJSValue(v4, result->asReturnedValue());
}
@@ -553,7 +554,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
Creates a QJSValue with the given \a value.
- \sa fromScriptValue(), newVariant()
+ \sa fromScriptValue()
*/
/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 2f6cf40beb..698b4c325c 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -40,9 +40,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
- : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass,
- context->d()->engine->objectPrototype())
- , context(context->d())
+ : context(context->d())
, fullyCreated(false)
{
Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
@@ -56,20 +54,20 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
if (context->d()->strictMode) {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
- args->propertyAt(CalleePropertyIndex)->value = v4->thrower();
- args->propertyAt(CalleePropertyIndex)->set = v4->thrower();
- args->propertyAt(CallerPropertyIndex)->value = v4->thrower();
- args->propertyAt(CallerPropertyIndex)->set = v4->thrower();
+ *args->propertyData(CalleePropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CalleePropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
- args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
+ *args->propertyData(CalleePropertyIndex) = context->d()->function->asReturnedValue();
}
Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
- args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->callData->argc);
+ *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
}
void ArgumentsObject::fullyCreate()
@@ -84,10 +82,9 @@ void ArgumentsObject::fullyCreate()
Scope scope(engine());
Scoped<MemberData> md(scope, d()->mappedArguments);
- if (!md || md->size() < numAccessors)
- d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
+ d()->mappedArguments = md->allocate(engine(), numAccessors);
for (uint i = 0; i < numAccessors; ++i) {
- mappedArguments()->data[i] = context()->callData->args[i];
+ d()->mappedArguments->data[i] = context()->callData->args[i];
arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
}
arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
@@ -117,13 +114,13 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
map->copy(pd, mapAttrs);
setArrayAttributes(index, Attr_Data);
pd = arrayData()->getProperty(index);
- pd->value = mappedArguments()->data[index];
+ pd->value = d()->mappedArguments->data[index];
}
- bool strict = engine->currentContext()->strictMode;
- engine->currentContext()->strictMode = false;
+ bool strict = engine->current->strictMode;
+ engine->current->strictMode = false;
bool result = Object::defineOwnProperty2(scope.engine, index, desc, attrs);
- engine->currentContext()->strictMode = strict;
+ engine->current->strictMode = strict;
if (isMapped && attrs.isData()) {
Q_ASSERT(arrayData());
@@ -140,7 +137,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
}
}
- if (engine->currentContext()->strictMode && !result)
+ if (engine->current->strictMode && !result)
return engine->throwTypeError();
return result;
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index aab5e2c156..98a600fab6 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -103,7 +103,6 @@ struct ArgumentsObject: Object {
Heap::CallContext *context() const { return d()->context; }
bool fullyCreated() const { return d()->fullyCreated; }
- Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
return m->d()->vtable()->type == Type_ArgumentsObject &&
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 23c9695cf4..0a3aa414de 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -58,7 +58,7 @@ ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
if (len != dl)
return v4->throwRangeError(QLatin1String("ArrayBuffer constructor: invalid length"));
- Scoped<ArrayBuffer> a(scope, v4->memoryManager->alloc<ArrayBuffer>(v4, len));
+ Scoped<ArrayBuffer> a(scope, v4->newArrayBuffer(len));
if (scope.engine->hasException)
return Encode::undefined();
return a.asReturnedValue();
@@ -83,22 +83,20 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
+Heap::ArrayBuffer::ArrayBuffer(size_t length)
{
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
data = 0;
- e->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
+ internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
}
data->size = int(length);
memset(data->data(), 0, length + 1);
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
- , data(const_cast<QByteArray&>(array).data_ptr())
+Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array)
+ : data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
}
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index a7f9e92c80..19fd74465c 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -47,8 +47,8 @@ struct ArrayBufferCtor : FunctionObject {
};
struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object {
- ArrayBuffer(ExecutionEngine *e, size_t length);
- ArrayBuffer(ExecutionEngine *e, const QByteArray& array);
+ ArrayBuffer(size_t length);
+ ArrayBuffer(const QByteArray& array);
~ArrayBuffer();
QTypedArrayData<char> *data;
@@ -72,6 +72,7 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object
{
V4_OBJECT2(ArrayBuffer, Object)
V4_NEEDS_DESTROY
+ V4_PROTOTYPE(arrayBufferPrototype)
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index da91db6aae..ec0185de64 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -584,7 +584,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
ScopedValue v(scope);
for (const SparseArrayNode *it = os->sparse->begin();
it != os->sparse->end(); it = it->nextNode()) {
- v = otherObj->getValue(reinterpret_cast<Property *>(os->arrayData + it->value), other->d()->attrs[it->value]);
+ v = otherObj->getValue(os->arrayData[it->value], other->d()->attrs[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
@@ -607,7 +607,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
return oldSize + n;
}
-Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
+void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
@@ -622,7 +622,8 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
d->data(i) = Primitive::emptyValue();
d->len = index + 1;
}
- return reinterpret_cast<Property *>(d->arrayData + d->mappedIndex(index));
+ d->arrayData[d->mappedIndex(index)] = *v;
+ return;
}
}
@@ -632,7 +633,9 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
s = o->d()->arrayData.cast<Heap::SparseArrayData>();
- return reinterpret_cast<Property *>(s->arrayData + n->value);
+ s->arrayData[n->value] = *v;
+ if (isAccessor)
+ s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset];
}
@@ -769,7 +772,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
break;
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- d->data(i) = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ d->data(i) = thisObject->getValue(sparse->arrayData()[n->value], a);
d->attrs[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 729e657b1a..cca5bf7f20 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -101,7 +101,10 @@ struct ArrayData : public Base {
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
}
+ inline void getProperty(uint index, Property *p, PropertyAttributes *attrs);
+ inline void setProperty(uint index, const Property *p);
inline Property *getProperty(uint index);
+ inline Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
inline PropertyAttributes attributes(uint i) const;
bool isEmpty(uint i) const {
@@ -205,7 +208,7 @@ struct Q_QML_EXPORT ArrayData : public Managed
static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen);
static uint append(Object *obj, ArrayObject *otherObj, uint n);
- static Property *insert(Object *o, uint index, bool isAccessor = false);
+ static void insert(Object *o, uint index, const Value *v, bool isAccessor = false);
};
struct Q_QML_EXPORT SimpleArrayData : public ArrayData
@@ -270,6 +273,25 @@ inline SparseArrayData::~SparseArrayData()
delete sparse;
}
+void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ *attrs = attributes(index);
+ p->value = pd->value;
+ if (attrs->isAccessor())
+ p->set = pd->set;
+}
+
+void ArrayData::setProperty(uint index, const Property *p)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ pd->value = p->value;
+ if (attributes(index).isAccessor())
+ pd->set = p->set;
+}
+
inline Property *ArrayData::getProperty(uint index)
{
if (isSparse())
@@ -284,6 +306,19 @@ inline PropertyAttributes ArrayData::attributes(uint i) const
return static_cast<const SimpleArrayData *>(this)->attributes(i);
}
+Value *ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
+{
+ Property *p = getProperty(index);
+ if (!p) {
+ *attrs = Attr_Invalid;
+ return 0;
+ }
+
+ *attrs = attributes(index);
+ return attrs->isAccessor() ? &p->set : &p->value;
+}
+
+
}
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index f50c5ab017..403beacf39 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -83,21 +83,31 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi
return c;
}
-Heap::WithContext *ExecutionContext::newWithContext(Object *with)
+Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with)
{
- return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
+ return d()->engine->memoryManager->alloc<WithContext>(d(), with);
}
-Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
+Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue)
{
- return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
+ Scope scope(this);
+ ScopedValue e(scope, exceptionValue);
+ return d()->engine->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e);
}
Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- return d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
}
+Heap::QmlContext *ExecutionContext::newQmlContext(QQmlContextData *context, QObject *scopeObject)
+{
+ Scope scope(this);
+ Scoped<QmlContextWrapper> qml(scope, QmlContextWrapper::qmlScope(scope.engine, context, scopeObject));
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
+}
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
@@ -142,38 +152,38 @@ Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
global = eng->globalObject->d();
}
-Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_WithContext)
+Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_WithContext)
{
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- withObject = with ? with->d() : 0;
+ withObject = with;
}
-Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_CatchContext)
+Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_CatchContext)
{
- strictMode = parent->strictMode;
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ strictMode = outer->strictMode;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- this->exceptionVarName = exceptionVarName->d();
+ this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
-Heap::QmlContext::QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml)
- : Heap::ExecutionContext(outer->engine(), Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext)
{
+ outer = outerContext->d();
strictMode = false;
- callData = parent->callData;
- this->outer = outer->d();
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
this->qml = qml->d();
}
@@ -362,7 +372,7 @@ void ExecutionContext::setProperty(String *name, const Value &value)
if (activation) {
uint member = activation->internalClass()->find(name);
if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
+ activation->putValue(member, value);
return;
}
}
@@ -538,7 +548,7 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
{
Scope scope(d()->engine);
ScopedContext it(scope, this->d());
- for (; it; it = it->d()->parent) {
+ for (; it; it = it->d()->outer) {
if (const CallContext *callCtx = it->asCallContext())
return callCtx->d()->function;
else if (it->asCatchContext() || it->asWithContext())
@@ -560,3 +570,8 @@ QQmlContextData *QmlContext::qmlContext() const
{
return d()->qml->context;
}
+
+void QmlContext::takeContextOwnership() {
+ d()->qml->ownsContext = true;
+}
+
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 2667bbe0b2..2807d1e29c 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -89,7 +89,6 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- Pointer<ExecutionContext> parent;
Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -99,6 +98,18 @@ struct ExecutionContext : Base {
int lineNumber;
};
+inline
+ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : engine(engine)
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , type(t)
+ , strictMode(false)
+ , lineNumber(-1)
+{}
+
+
struct CallContext : ExecutionContext {
CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
: ExecutionContext(engine, t)
@@ -119,20 +130,20 @@ struct GlobalContext : ExecutionContext {
};
struct CatchContext : ExecutionContext {
- CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
+ CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
- WithContext(ExecutionEngine *engine, QV4::Object *with);
+ WithContext(ExecutionContext *outerContext, Object *with);
Pointer<Object> withObject;
};
struct QmlContextWrapper;
struct QmlContext : ExecutionContext {
- QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml);
+ QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml);
Pointer<QmlContextWrapper> qml;
};
@@ -150,9 +161,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
- Heap::WithContext *newWithContext(Object *with);
- Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
+ Heap::WithContext *newWithContext(Heap::Object *with);
+ Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
+ Heap::QmlContext *newQmlContext(QQmlContextData *context, QObject *scopeObject);
void createMutableBinding(String *name, bool deletable);
@@ -224,6 +236,8 @@ struct QmlContext : public ExecutionContext
QObject *qmlScope() const;
QQmlContextData *qmlContext() const;
+
+ void takeContextOwnership();
};
inline CallContext *ExecutionContext::asCallContext()
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index a741d61d10..8901834e76 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -62,7 +62,7 @@ ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength)
return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
- Scoped<DataView> a(scope, scope.engine->memoryManager->alloc<DataView>(scope.engine));
+ Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>());
a->d()->buffer = buffer->d();
a->d()->byteLength = byteLength;
a->d()->byteOffset = byteOffset;
@@ -76,15 +76,6 @@ ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
}
-Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype()),
- buffer(0),
- byteLength(0),
- byteOffset(0)
-{
-}
-
-
void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
{
DataView::Data *v = static_cast<DataView::Data *>(that);
@@ -103,22 +94,30 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 0);
- defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUint16"), method_get<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 0);
- defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("getUint32"), method_get<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 0);
defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 0);
defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUint8"), method_setChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 0);
- defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUint16"), method_set<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 0);
- defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUint32"), method_set<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 0);
defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 0);
+
+ // For backword compatibility
+ defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
}
ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index e98239396a..37a8363645 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -47,7 +47,7 @@ struct DataViewCtor : FunctionObject {
};
struct DataView : Object {
- DataView(ExecutionEngine *e);
+ DataView() {}
Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
@@ -66,6 +66,7 @@ struct DataViewCtor: FunctionObject
struct DataView : Object
{
V4_OBJECT2(DataView, Object)
+ V4_PROTOTYPE(dataViewPrototype)
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 3f45751695..a6e1f47d91 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -628,8 +628,7 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype())
+Heap::DateObject::DateObject(const QDateTime &date)
{
this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 7a6413e820..a324e216e4 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -46,18 +46,16 @@ namespace QV4 {
namespace Heap {
struct DateObject : Object {
- DateObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
+ DateObject()
{
date = qSNaN();
}
- DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype())
+ DateObject(const Value &date)
{
this->date = date.toNumber();
}
- DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
+ DateObject(const QDateTime &date);
double date;
};
@@ -71,6 +69,7 @@ struct DateCtor : FunctionObject {
struct DateObject: Object {
V4_OBJECT2(DateObject, Object)
Q_MANAGED_TYPE(DateObject)
+ V4_PROTOTYPE(datePrototype)
double date() const { return d()->date; }
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 6efc3793ce..79fd58f700 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -66,17 +66,16 @@ void Debugger::JavaScriptJob::run()
{
Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope);
+ ExecutionContext *ctx = engine->currentContext;
if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
+ ctx = engine->parentContext(ctx);
}
+ engine->pushContext(ctx);
}
- ScopedContext ctx(scope, engine->currentContext());
QV4::Script script(ctx, this->script);
script.strictMode = ctx->d()->strictMode;
// In order for property lookups in QML to work, we need to disable fast v4 lookups. That
@@ -151,7 +150,7 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue.set(m_engine, Encode::undefined());
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -181,7 +180,7 @@ Debugger::ExecutionState Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->lineNumber;
+ state.lineNumber = engine()->current->lineNumber;
return state;
}
@@ -206,7 +205,7 @@ void Debugger::maybeBreakAtInstruction()
switch (m_stepping) {
case StepOver:
- if (m_currentContext.asManaged()->d() != m_engine->currentContext())
+ if (m_currentContext.asManaged()->d() != m_engine->current)
break;
// fall through
case StepIn:
@@ -222,7 +221,7 @@ void Debugger::maybeBreakAtInstruction()
pauseAndWait(PauseRequest);
} else if (m_haveBreakPoints) {
if (Function *f = getFunction()) {
- const int lineNumber = engine()->currentContext()->lineNumber;
+ const int lineNumber = engine()->current->lineNumber;
if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
pauseAndWait(BreakPoint);
}
@@ -236,7 +235,7 @@ void Debugger::enteringFunction()
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
}
}
@@ -248,8 +247,8 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->currentContext()) {
- m_currentContext.set(m_engine, m_engine->currentContext()->parent);
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
@@ -270,7 +269,7 @@ void Debugger::aboutToThrow()
Function *Debugger::getFunction() const
{
Scope scope(m_engine);
- ScopedContext context(scope, m_engine->currentContext());
+ ExecutionContext *context = m_engine->currentContext;
ScopedFunctionObject function(scope, context->getFunctionObject());
if (function)
return function->function();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index caf07e8b0b..6fe14da850 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -200,6 +200,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
+ , currentContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
@@ -297,10 +298,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
- jsObjects[ObjectProto] = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
+ jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(emptyClass);
arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
- jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype());
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(arrayClass, objectPrototype());
InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
@@ -311,15 +312,17 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
Q_ASSERT(globalObject->d()->vtable());
initRootContext();
- jsObjects[StringProto] = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype());
- jsObjects[NumberProto] = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype());
- jsObjects[BooleanProto] = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype());
- jsObjects[DateProto] = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype());
+ stringClass = emptyClass->addMember(id_length(), Attr_ReadOnly);
+ Q_ASSERT(stringClass->find(id_length()) == Heap::StringObject::LengthPropertyIndex);
+ jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(stringClass, objectPrototype());
+ jsObjects[NumberProto] = memoryManager->allocObject<NumberPrototype>(emptyClass, objectPrototype());
+ jsObjects[BooleanProto] = memoryManager->allocObject<BooleanPrototype>(emptyClass, objectPrototype());
+ jsObjects[DateProto] = memoryManager->allocObject<DatePrototype>(emptyClass, objectPrototype());
uint index;
InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- jsObjects[FunctionProto] = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype());
+ jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(functionProtoClass, objectPrototype());
functionClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
@@ -329,42 +332,72 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- jsObjects[RegExpProto] = memoryManager->alloc<RegExpPrototype>(this);
+ Scope scope(this);
+ ScopedString str(scope);
+ regExpObjectClass = emptyClass->addMember(id_lastIndex(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ Q_ASSERT(index == RegExpObject::Index_LastIndex);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("source"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Source);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("global"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Global);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("ignoreCase"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_IgnoreCase);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("multiline"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Multiline);
+
+ jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(regExpObjectClass, objectPrototype());
regExpExecArrayClass = arrayClass->addMember(id_index(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- jsObjects[ErrorProto] = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype());
- jsObjects[EvalErrorProto] = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[RangeErrorProto] = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[ReferenceErrorProto] = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[SyntaxErrorProto] = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[TypeErrorProto] = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[URIErrorProto] = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype());
-
- jsObjects[VariantProto] = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype());
+ errorClass = emptyClass->addMember((str = newIdentifier(QStringLiteral("stack"))), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Stack);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_FileName);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("lineNumber"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_LineNumber);
+ errorClassWithMessage = errorClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Message);
+ errorProtoClass = emptyClass->addMember(id_constructor(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Constructor);
+ errorProtoClass = errorProtoClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Message);
+ errorProtoClass = errorProtoClass->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Name);
+
+ jsObjects[GetStack_Function] = BuiltinFunction::create(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack);
+ getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
+
+ jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(errorProtoClass, objectPrototype());
+ jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(errorProtoClass, errorPrototype());
+
+ jsObjects[VariantProto] = memoryManager->allocObject<VariantPrototype>(emptyClass, objectPrototype());
Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
- Scope scope(this);
- jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype()));
-
- ScopedContext global(scope, rootContext());
- jsObjects[Object_Ctor] = memoryManager->alloc<ObjectCtor>(global);
- jsObjects[String_Ctor] = memoryManager->alloc<StringCtor>(global);
- jsObjects[Number_Ctor] = memoryManager->alloc<NumberCtor>(global);
- jsObjects[Boolean_Ctor] = memoryManager->alloc<BooleanCtor>(global);
- jsObjects[Array_Ctor] = memoryManager->alloc<ArrayCtor>(global);
- jsObjects[Function_Ctor] = memoryManager->alloc<FunctionCtor>(global);
- jsObjects[Date_Ctor] = memoryManager->alloc<DateCtor>(global);
- jsObjects[RegExp_Ctor] = memoryManager->alloc<RegExpCtor>(global);
- jsObjects[Error_Ctor] = memoryManager->alloc<ErrorCtor>(global);
- jsObjects[EvalError_Ctor] = memoryManager->alloc<EvalErrorCtor>(global);
- jsObjects[RangeError_Ctor] = memoryManager->alloc<RangeErrorCtor>(global);
- jsObjects[ReferenceError_Ctor] = memoryManager->alloc<ReferenceErrorCtor>(global);
- jsObjects[SyntaxError_Ctor] = memoryManager->alloc<SyntaxErrorCtor>(global);
- jsObjects[TypeError_Ctor] = memoryManager->alloc<TypeErrorCtor>(global);
- jsObjects[URIError_Ctor] = memoryManager->alloc<URIErrorCtor>(global);
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(arrayClass, arrayPrototype()));
+
+ ExecutionContext *global = rootContext();
+ jsObjects[Object_Ctor] = memoryManager->allocObject<ObjectCtor>(global);
+ jsObjects[String_Ctor] = memoryManager->allocObject<StringCtor>(global);
+ jsObjects[Number_Ctor] = memoryManager->allocObject<NumberCtor>(global);
+ jsObjects[Boolean_Ctor] = memoryManager->allocObject<BooleanCtor>(global);
+ jsObjects[Array_Ctor] = memoryManager->allocObject<ArrayCtor>(global);
+ jsObjects[Function_Ctor] = memoryManager->allocObject<FunctionCtor>(global);
+ jsObjects[Date_Ctor] = memoryManager->allocObject<DateCtor>(global);
+ jsObjects[RegExp_Ctor] = memoryManager->allocObject<RegExpCtor>(global);
+ jsObjects[Error_Ctor] = memoryManager->allocObject<ErrorCtor>(global);
+ jsObjects[EvalError_Ctor] = memoryManager->allocObject<EvalErrorCtor>(global);
+ jsObjects[RangeError_Ctor] = memoryManager->allocObject<RangeErrorCtor>(global);
+ jsObjects[ReferenceError_Ctor] = memoryManager->allocObject<ReferenceErrorCtor>(global);
+ jsObjects[SyntaxError_Ctor] = memoryManager->allocObject<SyntaxErrorCtor>(global);
+ jsObjects[TypeError_Ctor] = memoryManager->allocObject<TypeErrorCtor>(global);
+ jsObjects[URIError_Ctor] = memoryManager->allocObject<URIErrorCtor>(global);
static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
@@ -388,18 +421,19 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
// typed arrays
- jsObjects[ArrayBuffer_Ctor] = memoryManager->alloc<ArrayBufferCtor>(global);
- jsObjects[ArrayBufferProto] = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>();
static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- jsObjects[DataView_Ctor] = memoryManager->alloc<DataViewCtor>(global);
- jsObjects[DataViewProto] = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype());
+ jsObjects[DataView_Ctor] = memoryManager->allocObject<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->allocObject<DataViewPrototype>();
static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
jsObjects[ValueTypeProto] = (Heap::Base *) 0;
+ jsObjects[SignalHandlerProto] = (Heap::Base *) 0;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- static_cast<Value &>(typedArrayCtors[i]) = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocObject<TypedArrayPrototype>(Heap::TypedArray::Type(i));
typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
@@ -428,19 +462,18 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
- ScopedString str(scope);
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocObject<MathObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocObject<JsonObject>()));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- jsObjects[Eval_Function] = memoryManager->alloc<EvalFunction>(global);
+ jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
@@ -508,8 +541,11 @@ void ExecutionEngine::initRootContext()
r->d()->callData->argc = 0;
r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
+ jsObjects[RootContext] = r;
+ jsObjects[IntegerNull] = Encode((int)0);
- jsObjects[RootContect] = r;
+ currentContext = static_cast<ExecutionContext *>(jsObjects + RootContext);
+ current = currentContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -517,29 +553,31 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
return new (classPool) InternalClass(other);
}
-Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
+ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- Scope scope(this);
- Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->d()->callData;
+ pushContext(rootContext()->d());
- Q_ASSERT(currentContext() == g->d());
- return g->d();
+ Q_ASSERT(current == rootContext()->d());
+ return currentContext;
+}
+
+ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const
+{
+ Value *offset = static_cast<Value *>(context) + 1;
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ return o ? context - o : 0;
}
Heap::Object *ExecutionEngine::newObject()
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(this));
- return object->d();
+ return memoryManager->allocObject<Object>();
}
Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype));
- return object->d();
+ return memoryManager->allocObject<Object>(internalClass, prototype);
}
Heap::String *ExecutionEngine::newString(const QString &s)
@@ -555,29 +593,23 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
- Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, string));
- return object->d();
+ return memoryManager->allocObject<StringObject>(string);
}
Heap::Object *ExecutionEngine::newNumberObject(double value)
{
- Scope scope(this);
- Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<NumberObject>(value);
}
Heap::Object *ExecutionEngine::newBooleanObject(bool b)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, b));
- return object->d();
+ return memoryManager->allocObject<BooleanObject>(b);
}
Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>());
if (count) {
if (count < 0x1000)
@@ -587,39 +619,60 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
return object->d();
}
+Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length)
+{
+ Scope scope(this);
+ ScopedArrayObject a(scope, memoryManager->allocObject<ArrayObject>());
+
+ if (length) {
+ size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
+ Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
+ new (d) Heap::SimpleArrayData;
+ d->alloc = length;
+ d->type = Heap::ArrayData::Simple;
+ d->offset = 0;
+ d->len = length;
+ memcpy(&d->arrayData, values, length*sizeof(Value));
+ a->d()->arrayData = d;
+ a->setArrayLengthUnchecked(length);
+ }
+ return a->d();
+}
+
Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(list));
return object->d();
}
-Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic, prototype));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(internalClass, prototype));
return object->d();
}
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
{
- Scope scope(this);
- Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array));
- return object->d();
+ return memoryManager->allocObject<ArrayBuffer>(array);
+}
+
+Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length)
+{
+ return memoryManager->allocObject<ArrayBuffer>(length);
}
Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
{
- Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<DateObject>(value);
}
Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
{
Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt));
+ Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(dt));
return object->d();
}
@@ -640,97 +693,75 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int
Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re, global);
}
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re);
}
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype(), value));
- return object->d();
+ return ErrorObject::create<ErrorObject>(this, value);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedString s(scope, newString(message));
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message);
}
-Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
+Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newTypeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<TypeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newRangeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<RangeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<URIErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v));
- return o->d();
+ return memoryManager->allocObject<VariantObject>(v);
}
Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
{
Scope scope(this);
- ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(this, o));
+ ScopedObject obj(scope, memoryManager->allocObject<ForEachIteratorObject>(o));
return obj->d();
}
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
- Heap::ExecutionContext *ctx = currentContext();
+ Heap::ExecutionContext *ctx = current;
+ // get the correct context when we're within a builtin function
if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = ctx->parent;
+ ctx = parentContext(currentContext)->d();
if (!ctx->outer)
return 0;
@@ -745,18 +776,13 @@ Heap::QmlContext *ExecutionEngine::qmlContext() const
return static_cast<Heap::QmlContext *>(ctx);
}
-Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const
+QObject *ExecutionEngine::qmlScopeObject() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
return 0;
- Q_ASSERT(ctx->qml);
- return ctx->qml;
-}
-QObject *ExecutionEngine::qmlScopeObject() const
-{
- return qmlContextObject()->scopeObject;
+ return ctx->qml->scopeObject;
}
ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
@@ -782,9 +808,11 @@ ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
QQmlContextData *ExecutionEngine::callingQmlContext() const
{
- Heap::QmlContextWrapper *w = qmlContextObject();
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
- return w ? w->context.contextData() : 0;
+ return ctx->qml->context.contextData();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -793,7 +821,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
ScopedString name(scope);
QVector<StackFrame> stack;
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
ScopedFunctionObject function(scope);
while (c && frameLimit) {
function = c->getFunctionObject();
@@ -813,7 +841,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
stack.append(frame);
--frameLimit;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (frameLimit && globalCode) {
@@ -881,8 +909,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
return src;
QUrl base;
- Scope scope(this);
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
while (c) {
CallContext *callCtx = c->asCallContext();
if (callCtx && callCtx->d()->function) {
@@ -890,7 +917,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
base.setUrl(callCtx->d()->function->function->sourceFile());
break;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (base.isEmpty() && globalCode)
@@ -920,10 +947,10 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
memcpy(argumentsAccessors, oldAccessors, oldSize*sizeof(Property));
delete [] oldAccessors;
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = rootContext();
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(global, i));
- argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(global, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocObject<ArgumentsGetterFunction>(global, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocObject<ArgumentsSetterFunction>(global, i));
}
}
}
@@ -940,16 +967,6 @@ void ExecutionEngine::markObjects()
setter->mark(this);
}
- Heap::ExecutionContext *c = currentContext();
- while (c) {
- Q_ASSERT(c->inUse());
- if (!c->isMarked()) {
- c->setMarkBit();
- c->vtable()->markObjects(c, this);
- }
- c = c->parent;
- }
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 90564a9652..ffcd904013 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -78,7 +78,6 @@ private:
friend struct Heap::ExecutionContext;
public:
Heap::ExecutionContext *current;
- Heap::ExecutionContext *currentContext() const { return current; }
Value *jsStackTop;
quint32 hasException;
@@ -88,6 +87,7 @@ public:
ExecutableAllocator *regExpAllocator;
QScopedPointer<EvalISelFactory> iselFactory;
+ ExecutionContext *currentContext;
Value *jsStackLimit;
quintptr cStackLimit;
@@ -127,7 +127,8 @@ public:
QV8Engine *v8Engine;
enum JSObjects {
- RootContect,
+ RootContext,
+ IntegerNull, // Has to come after the RootContext to make the context stack safe
ObjectProto,
ArrayProto,
StringProto,
@@ -148,6 +149,7 @@ public:
ArrayBufferProto,
DataViewProto,
ValueTypeProto,
+ SignalHandlerProto,
Object_Ctor,
String_Ctor,
@@ -168,13 +170,14 @@ public:
DataView_Ctor,
Eval_Function,
+ GetStack_Function,
ThrowerObject,
NJSObjects
};
Value *jsObjects;
enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
- GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContect); }
+ GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContext); }
FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
@@ -217,22 +220,30 @@ public:
Object *typedArrayPrototype;
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
+ Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
InternalClassPool *classPool;
InternalClass *emptyClass;
InternalClass *arrayClass;
+ InternalClass *stringClass;
InternalClass *functionClass;
InternalClass *simpleScriptFunctionClass;
InternalClass *protoClass;
InternalClass *regExpExecArrayClass;
+ InternalClass *regExpObjectClass;
InternalClass *argumentsObjectClass;
InternalClass *strictArgumentsObjectClass;
+ InternalClass *errorClass;
+ InternalClass *errorClassWithMessage;
+ InternalClass *errorProtoClass;
+
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
+ FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
Property *argumentsAccessors;
@@ -347,9 +358,11 @@ public:
void enableDebugger();
void enableProfiler();
- Heap::ExecutionContext *pushGlobalContext();
- void pushContext(CallContext *context);
- Heap::ExecutionContext *popContext();
+ ExecutionContext *pushGlobalContext();
+ void pushContext(Heap::ExecutionContext *context);
+ void pushContext(ExecutionContext *context);
+ void popContext();
+ ExecutionContext *parentContext(ExecutionContext *context) const;
Heap::Object *newObject();
Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
@@ -362,10 +375,12 @@ public:
Heap::Object *newBooleanObject(bool b);
Heap::ArrayObject *newArrayObject(int count = 0);
+ Heap::ArrayObject *newArrayObject(const Value *values, int length);
Heap::ArrayObject *newArrayObject(const QStringList &list);
Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
+ Heap::ArrayBuffer *newArrayBuffer(size_t length);
Heap::DateObject *newDateObject(const Value &value);
Heap::DateObject *newDateObject(const QDateTime &dt);
@@ -378,7 +393,7 @@ public:
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
Heap::Object *newSyntaxErrorObject(const QString &message);
Heap::Object *newReferenceErrorObject(const QString &message);
- Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
+ Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
Heap::Object *newTypeErrorObject(const QString &message);
Heap::Object *newRangeErrorObject(const QString &message);
Heap::Object *newURIErrorObject(const Value &message);
@@ -388,7 +403,6 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
Heap::QmlContext *qmlContext() const;
- QV4::Heap::QmlContextWrapper *qmlContextObject() const;
QObject *qmlScopeObject() const;
ReturnedValue qmlSingletonWrapper(String *name);
QQmlContextData *callingQmlContext() const;
@@ -442,36 +456,33 @@ public:
void assertObjectBelongsToEngine(const Heap::Base &baseObject);
};
-inline void ExecutionEngine::pushContext(CallContext *context)
+inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
{
- Q_ASSERT(current && context && context->d());
- context->d()->parent = current;
- current = context->d();
+ Q_ASSERT(currentContext && context);
+ Value *v = jsAlloca(2);
+ v[0] = Encode(context);
+ v[1] = Encode((int)(v - static_cast<Value *>(currentContext)));
+ currentContext = static_cast<ExecutionContext *>(v);
+ current = currentContext->d();
}
-inline Heap::ExecutionContext *ExecutionEngine::popContext()
+inline void ExecutionEngine::pushContext(ExecutionContext *context)
{
- Q_ASSERT(current->parent);
- current = current->parent;
- Q_ASSERT(current);
- return current;
+ pushContext(context->d());
}
-inline
-Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
- : engine(engine)
- , parent(engine->currentContext())
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
- , type(t)
- , strictMode(false)
- , lineNumber(-1)
+
+inline void ExecutionEngine::popContext()
{
- engine->current = this;
+ Q_ASSERT(jsStackTop > currentContext);
+ QV4::Value *offset = (currentContext + 1);
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ Q_ASSERT(o);
+ currentContext -= o;
+ current = currentContext->d();
}
-
inline
void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
@@ -487,11 +498,12 @@ void Heap::Base::mark(QV4::ExecutionEngine *engine)
inline void Value::mark(ExecutionEngine *e)
{
- if (!_val)
+ if (!isManaged())
return;
- Managed *m = as<Managed>();
- if (m)
- m->d()->mark(e);
+
+ Heap::Base *o = heapObject();
+ if (o)
+ o->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index a6c2a25b91..87b7a88a2b 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -61,72 +61,49 @@
using namespace QV4;
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , stack(Q_NULLPTR)
+Heap::ErrorObject::ErrorObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope, scope.engine->newString(QStringLiteral("Error")));
- e->defineDefaultProperty(QStringLiteral("name"), s);
-}
-
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t)
- : Heap::Object(ic, prototype)
-{
- errorType = t;
+ if (internalClass == scope.engine->errorProtoClass)
+ return;
- Scope scope(ic->engine);
- Scoped<QV4::ErrorObject> e(scope, this);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
-
- if (!message.isUndefined())
- e->defineDefaultProperty(QStringLiteral("message"), message);
- ScopedString s(scope);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
-
- e->d()->stackTrace = scope.engine->stackTrace();
- if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
- }
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_FileName) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
+
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
StackFrame frame;
@@ -136,12 +113,33 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const
e->d()->stackTrace.prepend(frame);
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
+}
+
+const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
+{
+ switch (t) {
+ case Heap::ErrorObject::Error:
+ return "Error";
+ case Heap::ErrorObject::EvalError:
+ return "EvalError";
+ case Heap::ErrorObject::RangeError:
+ return "RangeError";
+ case Heap::ErrorObject::ReferenceError:
+ return "ReferenceError";
+ case Heap::ErrorObject::SyntaxError:
+ return "SyntaxError";
+ case Heap::ErrorObject::TypeError:
+ return "TypeError";
+ case Heap::ErrorObject::URIError:
+ return "URIError";
+ }
+ Q_UNREACHABLE();
}
ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
@@ -181,58 +179,43 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, SyntaxError)
-{
-}
-
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, fileName, lineNumber, columnNumber, SyntaxError)
-{
-}
-
-Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype(), message, EvalError)
-{
-}
-
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg)
+ : Heap::ErrorObject(msg, SyntaxError)
{
}
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
+Heap::EvalErrorObject::EvalErrorObject(const Value &message)
+ : Heap::ErrorObject(message, EvalError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
+Heap::RangeErrorObject::RangeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, RangeError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), msg, fileName, lineNumber, columnNumber, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message)
+ : Heap::ErrorObject(message, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
+Heap::TypeErrorObject::TypeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, TypeError)
{
}
-Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype(), message, URIError)
+Heap::URIErrorObject::URIErrorObject(const Value &message)
+ : Heap::ErrorObject(message, URIError)
{
}
@@ -258,7 +241,7 @@ ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const ErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return Encode(scope.engine->newErrorObject(v));
+ return ErrorObject::create<ErrorObject>(scope.engine, v)->asReturnedValue();
}
ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
@@ -275,7 +258,7 @@ ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const EvalErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<EvalErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
@@ -287,7 +270,7 @@ ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const RangeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<RangeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
@@ -299,7 +282,7 @@ ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData
{
Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<ReferenceErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
@@ -311,7 +294,7 @@ ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<SyntaxErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
@@ -323,7 +306,7 @@ ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const TypeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<TypeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
@@ -335,19 +318,21 @@ ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const URIErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<URIErrorObject>(scope.engine, v)->asReturnedValue();
}
-void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
+void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t)
{
Scope scope(engine);
ScopedString s(scope);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
- obj->defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
- obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
+ *obj->propertyData(Index_Constructor) = ctor;
+ *obj->propertyData(Index_Message) = engine->id_empty();
+ *obj->propertyData(Index_Name) = engine->newString(QString::fromLatin1(ErrorObject::className(t)));
+ if (t == Heap::ErrorObject::Error)
+ obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index e0fbcb4d8d..7f3babaa79 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -35,6 +35,7 @@
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -55,10 +56,9 @@ struct ErrorObject : Object {
URIError
};
- ErrorObject(InternalClass *ic, QV4::Object *prototype);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ ErrorObject();
+ ErrorObject(const Value &message, ErrorType t = Error);
+ ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
ErrorType errorType;
StackTrace stackTrace;
@@ -66,32 +66,29 @@ struct ErrorObject : Object {
};
struct EvalErrorObject : ErrorObject {
- EvalErrorObject(ExecutionEngine *engine, const Value &message);
+ EvalErrorObject(const Value &message);
};
struct RangeErrorObject : ErrorObject {
- RangeErrorObject(ExecutionEngine *engine, const Value &message);
- RangeErrorObject(ExecutionEngine *engine, const QString &msg);
+ RangeErrorObject(const Value &message);
};
struct ReferenceErrorObject : ErrorObject {
- ReferenceErrorObject(ExecutionEngine *engine, const Value &message);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ ReferenceErrorObject(const Value &message);
+ ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct SyntaxErrorObject : ErrorObject {
- SyntaxErrorObject(ExecutionEngine *engine, const Value &message);
- SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ SyntaxErrorObject(const Value &message);
+ SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct TypeErrorObject : ErrorObject {
- TypeErrorObject(ExecutionEngine *engine, const Value &message);
- TypeErrorObject(ExecutionEngine *engine, const QString &msg);
+ TypeErrorObject(const Value &message);
};
struct URIErrorObject : ErrorObject {
- URIErrorObject(ExecutionEngine *engine, const Value &message);
+ URIErrorObject(const Value &message);
};
struct ErrorCtor : Heap::FunctionObject {
@@ -130,12 +127,30 @@ struct ErrorObject: Object {
IsErrorObject = true
};
+ enum {
+ Index_Stack = 0, // Accessor Property
+ Index_FileName = 2,
+ Index_LineNumber = 3,
+ Index_Message = 4
+ };
+
V4_OBJECT2(ErrorObject, Object)
Q_MANAGED_TYPE(ErrorObject)
+ V4_INTERNALCLASS(errorClass)
+ V4_PROTOTYPE(errorPrototype)
V4_NEEDS_DESTROY
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const Value &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column);
+
SyntaxErrorObject *asSyntaxError();
+ static const char *className(Heap::ErrorObject::ErrorType t);
+
static ReturnedValue method_get_stack(CallContext *ctx);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -147,34 +162,40 @@ inline const ErrorObject *Value::as() const {
struct EvalErrorObject: ErrorObject {
typedef Heap::EvalErrorObject Data;
+ V4_PROTOTYPE(evalErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct RangeErrorObject: ErrorObject {
typedef Heap::RangeErrorObject Data;
+ V4_PROTOTYPE(rangeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct ReferenceErrorObject: ErrorObject {
typedef Heap::ReferenceErrorObject Data;
+ V4_PROTOTYPE(referenceErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct SyntaxErrorObject: ErrorObject {
V4_OBJECT2(SyntaxErrorObject, ErrorObject)
+ V4_PROTOTYPE(syntaxErrorPrototype)
};
struct TypeErrorObject: ErrorObject {
typedef Heap::TypeErrorObject Data;
+ V4_PROTOTYPE(typeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct URIErrorObject: ErrorObject {
typedef Heap::URIErrorObject Data;
+ V4_PROTOTYPE(uRIErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
@@ -232,40 +253,45 @@ struct URIErrorCtor: ErrorCtor
struct ErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this); }
+ enum {
+ Index_Constructor = 0,
+ Index_Message = 1,
+ Index_Name = 2
+ };
+ void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); }
- static void init(ExecutionEngine *engine, Object *ctor, Object *obj);
+ static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t);
static ReturnedValue method_toString(CallContext *ctx);
};
struct EvalErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::EvalError); }
};
struct RangeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::RangeError); }
};
struct ReferenceErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::ReferenceError); }
};
struct SyntaxErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::SyntaxError); }
};
struct TypeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::TypeError); }
};
struct URIErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::URIError); }
};
@@ -274,6 +300,25 @@ inline SyntaxErrorObject *ErrorObject::asSyntaxError()
return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
}
+
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message) {
+ return e->memoryManager->allocObject<T>(message.isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), message);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v, filename, line, column);
+}
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 98a4490211..66b2125a4f 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -70,14 +70,45 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)));
}
}
+ nFormals = compiledFunction->nFormals;
const quint32 *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject));
}
Function::~Function()
{
}
+void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
+{
+ internalClass = engine->emptyClass;
+
+ // iterate backwards, so we get the right ordering for duplicate names
+ Scope scope(engine);
+ ScopedString arg(scope);
+ for (int i = parameters.size() - 1; i >= 0; --i) {
+ arg = engine->newString(QString::fromUtf8(parameters.at(i)));
+ while (1) {
+ InternalClass *newClass = internalClass->addMember(arg, Attr_NotConfigurable);
+ if (newClass != internalClass) {
+ internalClass = newClass;
+ break;
+ }
+ // duplicate arguments, need some trick to store them
+ arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)));
+ }
+ }
+ nFormals = parameters.size();
+
+ const quint32 *localsIndices = compiledFunction->localsTable();
+ for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
+ internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = true;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 10a03bca94..534aa1b750 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -49,11 +49,16 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
+ uint nFormals;
+ bool activationRequired;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *));
~Function();
+ // used when dynamically assigning signal handlers (QQmlConnection)
+ void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters);
+
inline Heap::String *name() {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
@@ -64,7 +69,7 @@ struct Q_QML_EXPORT Function {
inline bool isNamedExpression() const { return compiledFunction->flags & CompiledData::Function::IsNamedExpression; }
inline bool needsActivation() const
- { return compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject)); }
+ { return activationRequired; }
};
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 6412e65fa9..a94c3f6db5 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -63,8 +63,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -73,8 +72,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -84,8 +82,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -95,8 +92,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -106,8 +102,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope);
@@ -117,8 +112,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -127,15 +121,12 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
f->init(n, false);
}
-Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , scope(ic->engine->rootContext()->d())
+Heap::FunctionObject::FunctionObject()
+ : scope(internalClass->engine->rootContext()->d())
, function(Q_NULLPTR)
{
- Scope scope(ic->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(ic->engine, Index_Prototype);
- memberData->data[Index_Prototype] = Encode::undefined();
+ Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
+ *propertyData(Index_Prototype) = Encode::undefined();
}
@@ -150,14 +141,14 @@ void FunctionObject::init(String *n, bool createProto)
Scope s(internalClass()->engine);
ScopedValue protectThis(s, this);
- ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
+ Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()) == Heap::FunctionObject::Index_Prototype);
if (createProto) {
ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
- proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
- proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
- memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
+ Q_ASSERT(s.engine->protoClass->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
+ *proto->propertyData(Heap::FunctionObject::Index_ProtoConstructor) = this->asReturnedValue();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = proto.asReturnedValue();
} else {
- memberData()->data[Heap::FunctionObject::Index_Prototype] = Encode::undefined();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = Encode::undefined();
}
ScopedValue v(s, n);
@@ -202,10 +193,28 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco
function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
function->isNamedExpression())
- return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function);
- return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
+ return scope->d()->engine->memoryManager->allocObject<ScriptFunction>(scope, function);
+ return scope->d()->engine->memoryManager->allocObject<SimpleScriptFunction>(scope, function, createProto);
}
+Heap::FunctionObject *FunctionObject::createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
+{
+ ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
+ QV4::Scope valueScope(engine);
+ ExecutionContext *global = valueScope.engine->rootContext();
+ QV4::Scoped<QmlContext> wrapperContext(valueScope, global->newQmlContext(qmlContext, scopeObject));
+
+ if (!signalParameters.isEmpty()) {
+ if (error)
+ QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
+ runtimeFunction->updateInternalClass(engine, signalParameters);
+ }
+
+ QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
+ return function->d();
+}
+
+
bool FunctionObject::isBinding() const
{
return d()->vtable() == QQmlBindingFunction::staticVTable();
@@ -240,7 +249,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
Scope scope(static_cast<const Object *>(that)->engine());
Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
- ScopedContext ctx(scope, scope.engine->currentContext());
+
QString arguments;
QString body;
if (callData->argc > 0) {
@@ -251,7 +260,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
}
body = callData->args[callData->argc - 1].toQString();
}
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -281,7 +290,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = isel->compile();
Function *vmf = compilationUnit->linkToEngine(scope.engine);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return FunctionObject::createScriptFunction(global, vmf)->asReturnedValue();
}
@@ -293,8 +302,7 @@ ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
- : Heap::FunctionObject(ic, prototype)
+Heap::FunctionPrototype::FunctionPrototype()
{
}
@@ -392,12 +400,12 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
ScopedValue boundThis(scope, ctx->argument(0));
Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
if (ctx->argc() > 1) {
- boundArgs = MemberData::reallocate(scope.engine, 0, ctx->argc() - 1);
+ boundArgs = MemberData::allocate(scope.engine, ctx->argc() - 1);
boundArgs->d()->size = ctx->argc() - 1;
memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value));
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
}
@@ -416,17 +424,18 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
ScopedObject obj(scope, v4->newObject(ic, proto));
- ScopedContext context(scope, v4->currentContext());
callData->thisObject = obj.asReturnedValue();
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
@@ -448,12 +457,12 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
- ScopedContext context(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
@@ -465,7 +474,6 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype())
{
this->scope = scope->d();
@@ -482,9 +490,10 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
f->init(name, createProto);
f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
} else {
- f->ensureMemberIndex(s.engine, Index_Length);
- memberData->data[Index_Name] = function->name();
- memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount());
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_name()) == Index_Name);
+ *propertyData(Index_Name) = function->name();
+ *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount());
}
if (scope->d()->strictMode) {
@@ -504,14 +513,14 @@ ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *cal
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
callData->thisObject = v4->newObject(ic, proto);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
-
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
@@ -526,7 +535,8 @@ ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *cal
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
@@ -546,9 +556,9 @@ ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -564,7 +574,8 @@ ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
@@ -607,7 +618,7 @@ ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -616,10 +627,10 @@ ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext));
}
ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
@@ -631,7 +642,7 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -640,10 +651,10 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa
ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx, f->d()->index);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 2c6a195746..182f06f74e 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -58,10 +58,10 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name);
FunctionObject(ExecutionContext *scope, const ReturnedValue name);
- FunctionObject(InternalClass *ic, QV4::Object *prototype);
+ FunctionObject();
~FunctionObject();
- unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
+ unsigned int formalParameterCount() { return function ? function->nFormals : 0; }
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
bool needsActivation() const { return function ? function->needsActivation() : false; }
@@ -74,7 +74,7 @@ struct FunctionCtor : FunctionObject {
};
struct FunctionPrototype : FunctionObject {
- FunctionPrototype(InternalClass *ic, QV4::Object *prototype);
+ FunctionPrototype();
};
struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
@@ -115,6 +115,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
V4_OBJECT2(FunctionObject, Object)
Q_MANAGED_TYPE(FunctionObject)
+ V4_INTERNALCLASS(functionClass)
+ V4_PROTOTYPE(functionPrototype)
V4_NEEDS_DESTROY
Heap::ExecutionContext *scope() const { return d()->scope; }
@@ -134,8 +136,10 @@ struct Q_QML_EXPORT FunctionObject: Object {
static ReturnedValue call(const Managed *that, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
+ static Heap::FunctionObject *createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
+ const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
- ReturnedValue protoProperty() { return memberData()->data[Heap::FunctionObject::Index_Prototype].asReturnedValue(); }
+ ReturnedValue protoProperty() { return propertyData(Heap::FunctionObject::Index_Prototype)->asReturnedValue(); }
bool needsActivation() const { return d()->needsActivation(); }
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
@@ -178,7 +182,7 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
{
- return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
+ return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code);
}
static ReturnedValue construct(const Managed *, CallData *);
@@ -208,6 +212,7 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
+ V4_INTERNALCLASS(simpleScriptFunctionClass)
static ReturnedValue construct(const Managed *, CallData *callData);
static ReturnedValue call(const Managed *that, CallData *callData);
@@ -228,7 +233,7 @@ struct BoundFunction: FunctionObject {
static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs)
{
- return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
+ return scope->engine()->memoryManager->allocObject<BoundFunction>(scope, target, boundThis, boundArgs);
}
Heap::FunctionObject *target() const { return d()->target; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index ec7b9b3f7d..110a2c9089 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -339,11 +339,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
ExecutionEngine *v4 = engine();
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
- ScopedContext parentContext(scope, v4->currentContext());
- ExecutionContextSaver ctxSaver(scope, parentContext);
-
- ScopedContext ctx(scope, parentContext.getPointer());
+ ExecutionContext *currentContext = v4->currentContext;
+ ExecutionContext *ctx = currentContext;
if (!directCall) {
// the context for eval should be the global scope, so we fake a root
@@ -358,10 +357,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
bool inheritContext = !ctx->d()->strictMode;
Script script(ctx, code, QStringLiteral("eval code"));
- script.strictMode = (directCall && parentContext->d()->strictMode);
+ script.strictMode = (directCall && currentContext->d()->strictMode);
script.inheritContext = inheritContext;
script.parse();
- if (scope.engine->hasException)
+ if (v4->hasException)
return Encode::undefined();
Function *function = script.function();
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 138d76bf4a..a5336ee44f 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -149,6 +149,22 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
return str->identifier;
}
+Heap::String *IdentifierTable::stringFromIdentifier(Identifier *i)
+{
+ if (!i)
+ return 0;
+
+ uint idx = i->hashValue % alloc;
+ while (1) {
+ Heap::String *e = entries[idx];
+ Q_ASSERT(e);
+ if (e->identifier == i)
+ return e;
+ ++idx;
+ idx %= alloc;
+ }
+}
+
Identifier *IdentifierTable::identifier(const QString &s)
{
return insertString(s)->identifier;
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 58f808b4d5..d91ce623c1 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -74,6 +74,8 @@ public:
Identifier *identifierImpl(const Heap::String *str);
+ Heap::String *stringFromIdentifier(Identifier *i);
+
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
Heap::String *entry = entries[i];
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 2eb61081c7..90c6738c46 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -49,11 +49,12 @@
QT_BEGIN_NAMESPACE
-QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback)
- : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
+ QV4::QmlContext *qmlContext, const QV4::Value &callback)
+ : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
{
- m_qmlglobal.set(engine, qmlglobal);
+ if (qmlContext)
+ m_qmlContext.set(engine, *qmlContext);
if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
@@ -142,8 +143,8 @@ void QV4Include::finished()
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- QV4::ScopedObject qmlglobal(scope, m_qmlglobal.value());
- QV4::Script script(v4, qmlglobal, code, m_url.toString());
+ QV4::Scoped<QV4::QmlContext> qml(scope, m_qmlContext.value());
+ QV4::Script script(v4, qml, code, m_url.toString());
script.parse();
if (!scope.engine->hasException)
@@ -190,12 +191,10 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
QV4::ScopedValue result(scope);
- QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject());
+ QV4::Scoped<QV4::QmlContext> qmlcontext(scope, scope.engine->qmlContext());
if (localFile.isEmpty()) {
- QV4Include *i = new QV4Include(url, scope.engine, context,
- qmlcontextobject,
- callbackFunction);
+ QV4Include *i = new QV4Include(url, scope.engine, qmlcontext, callbackFunction);
result = i->result();
} else {
@@ -203,7 +202,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, jsUnit));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, jsUnit));
} else {
QFile f(localFile);
@@ -212,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, code, url.toString()));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, code, url.toString()));
}
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5ef4442b03..3e3cf5e770 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -76,8 +76,7 @@ private Q_SLOTS:
void finished();
private:
- QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback);
+ QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback);
~QV4Include();
QV4::ReturnedValue result();
@@ -95,8 +94,7 @@ private:
QV4::PersistentValue m_callbackFunction;
QV4::PersistentValue m_resultObject;
- QQmlGuardedContextData m_context;
- QV4::PersistentValue m_qmlglobal;
+ QV4::PersistentValue m_qmlContext;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a90e8e3689..8f0b1776d7 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -134,21 +134,64 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
Q_ASSERT(extensible);
}
+static void insertHoleIntoPropertyData(Object *object, int idx)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int from = qMax(idx, inlineSize);
+ int to = from + 1;
+ if (from < icSize)
+ memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1);
+ if (from == idx)
+ return;
+ if (inlineSize < icSize)
+ *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
+ from = idx;
+ to = from + 1;
+ if (from < inlineSize - 1)
+ memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1);
+}
+
+static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int delta = (accessor ? 2 : 1);
+ int to = idx;
+ int from = to + delta;
+ if (from < inlineSize) {
+ memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value));
+ to = inlineSize - delta;
+ from = inlineSize;
+ }
+ if (to < inlineSize && from < icSize) {
+ Q_ASSERT(from >= inlineSize);
+ memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
+ to = inlineSize;
+ from = inlineSize + delta;
+ }
+ if (from < icSize + delta) {
+ Q_ASSERT(to >= inlineSize && from > to);
+ memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
+ }
+}
+
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
- InternalClass *newClass = object->internalClass()->changeMember(string->identifier(), data, &idx);
+ InternalClass *oldClass = object->internalClass();
+ InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx);
if (index)
*index = idx;
- if (newClass->size > object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size + 1);
- memmove(object->memberData()->data + idx + 2, object->memberData()->data + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
- } else if (newClass->size < object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size - 1);
- memmove(object->memberData()->data + idx + 1, object->memberData()->data + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
- }
object->setInternalClass(newClass);
+ if (newClass->size > oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size + 1);
+ insertHoleIntoPropertyData(object, idx + 1);
+ } else if (newClass->size < oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size - 1);
+ removeFromPropertyData(object, idx + 1);
+ }
}
InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalClassTransition &t)
@@ -286,6 +329,8 @@ void InternalClass::removeMember(Object *object, Identifier *id)
Transition temp = { id, 0, -1 };
Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
+ bool accessor = oldClass->propertyData.at(propIdx).isAccessor();
+
if (t.lookup) {
object->setInternalClass(t.lookup);
} else {
@@ -300,8 +345,10 @@ void InternalClass::removeMember(Object *object, Identifier *id)
object->setInternalClass(newClass);
}
- // remove the entry in memberdata
- memmove(object->memberData()->data + propIdx, object->memberData()->data + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
+ Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1));
+
+ // remove the entry in the property data
+ removeFromPropertyData(object, propIdx, accessor);
t.lookup = object->internalClass();
Q_ASSERT(t.lookup);
@@ -352,20 +399,26 @@ InternalClass *InternalClass::frozen()
if (m_frozen)
return m_frozen;
- m_frozen = engine->emptyClass;
+ m_frozen = propertiesFrozen();
+ m_frozen = m_frozen->nonExtensible();
+
+ m_frozen->m_frozen = m_frozen;
+ m_frozen->m_sealed = m_frozen;
+ return m_frozen;
+}
+
+InternalClass *InternalClass::propertiesFrozen() const
+{
+ InternalClass *frozen = engine->emptyClass;
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
continue;
attrs.setWritable(false);
attrs.setConfigurable(false);
- m_frozen = m_frozen->addMember(nameMap.at(i), attrs);
+ frozen = frozen->addMember(nameMap.at(i), attrs);
}
- m_frozen = m_frozen->nonExtensible();
-
- m_frozen->m_frozen = m_frozen;
- m_frozen->m_sealed = m_frozen;
- return m_frozen;
+ return frozen;
}
void InternalClass::destroy()
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 80590fe72e..342870fcd6 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -233,6 +233,7 @@ struct InternalClass : public QQmlJS::Managed {
InternalClass *sealed();
InternalClass *frozen();
+ InternalClass *propertiesFrozen() const;
void destroy();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index f703e85399..f4f87f3aea 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -858,10 +858,9 @@ QString Stringify::JA(ArrayObject *a)
}
-Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype())
+Heap::JsonObject::JsonObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
@@ -943,7 +942,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return engine->currentContext()->engine->newString(value.toString())->asReturnedValue();
+ return engine->newString(value.toString())->asReturnedValue();
else if (value.isDouble())
return Encode(value.toDouble());
else if (value.isBool())
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 1ad0e2c5de..61d44f206e 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -47,7 +47,7 @@ namespace QV4 {
namespace Heap {
struct JsonObject : Object {
- JsonObject(ExecutionEngine *e);
+ JsonObject();
};
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 443427b024..d97abdb461 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -43,7 +43,7 @@ using namespace QV4;
ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs)
{
ExecutionEngine *engine = o->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
Heap::Object *obj = o->d();
while (i < Size && obj) {
@@ -53,7 +53,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -65,7 +66,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -77,7 +79,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
{
Heap::Object *obj = thisObject->d();
ExecutionEngine *engine = thisObject->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
while (i < Size && obj) {
classList[i] = obj->internalClass;
@@ -86,7 +88,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -98,7 +101,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -165,7 +169,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
{
uint idx = index.asArrayIndex();
if (idx == UINT_MAX || !object.isObject())
- return indexedGetterGeneric(l, object, index);
+ return indexedGetterFallback(l, object, index);
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
@@ -251,7 +255,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
Q_ASSERT(object.isString());
proto = engine->stringPrototype();
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (name->equals(engine->id_length())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
@@ -329,7 +333,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const V
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return o->get(name);
}
@@ -340,7 +344,7 @@ ReturnedValue Lookup::getter0(Lookup *l, ExecutionEngine *engine, const Value &o
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -353,7 +357,7 @@ ReturnedValue Lookup::getter1(Lookup *l, ExecutionEngine *engine, const Value &o
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -369,7 +373,7 @@ ReturnedValue Lookup::getter2(Lookup *l, ExecutionEngine *engine, const Value &o
if (l->classList[1] == p->internalClass) {
p = p->prototype;
if (l->classList[2] == p->internalClass)
- return p->memberData->data[l->index].asReturnedValue();
+ return p->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -384,9 +388,9 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass())
- return o->memberData()->data[l->index2].asReturnedValue();
+ return o->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -399,10 +403,10 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -416,10 +420,10 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, ExecutionEngine *engine, const V
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
return getterFallback(l, engine, object);
}
l->getter = getterFallback;
@@ -435,7 +439,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -457,7 +461,7 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->prototype->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -482,7 +486,7 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -502,7 +506,7 @@ ReturnedValue Lookup::primitiveGetter0(Lookup *l, ExecutionEngine *engine, const
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -514,7 +518,7 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, ExecutionEngine *engine, const
Object *o = l->proto;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -526,7 +530,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engin
Object *o = l->proto;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -546,7 +550,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -571,7 +575,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
if (const ArrayObject *a = object.as<ArrayObject>())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -603,7 +607,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
}
}
Scope scope(engine);
- ScopedString n(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString n(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return engine->throwReferenceError(n);
}
@@ -611,7 +615,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -622,7 +626,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -636,7 +640,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
if (l->classList[1] == o->internalClass) {
o = o->prototype;
if (l->classList[2] == o->internalClass) {
- return o->prototype->memberData->data[l->index].asReturnedValue();
+ return o->prototype->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -649,7 +653,7 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -667,7 +671,7 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -688,7 +692,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -710,7 +714,7 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, co
o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return;
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
return;
}
@@ -741,7 +745,7 @@ void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (o) {
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
}
}
@@ -750,7 +754,7 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Va
{
Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
@@ -762,10 +766,8 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, co
Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -780,10 +782,8 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -800,10 +800,8 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, co
if (p && p->internalClass == l->classList[1]) {
p = p->prototype;
if (p && p->internalClass == l->classList[2]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -818,11 +816,11 @@ void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
if (o->internalClass() == l->classList[1]) {
- o->memberData()->data[l->index2] = value;
+ *o->propertyData(l->index2) = value;
return;
}
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index bb7ee43b4e..e2de36d18e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -88,29 +88,7 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- switch (static_cast<Heap::ErrorObject *>(d())->errorType) {
- case Heap::ErrorObject::Error:
- s = "Error";
- break;
- case Heap::ErrorObject::EvalError:
- s = "EvalError";
- break;
- case Heap::ErrorObject::RangeError:
- s = "RangeError";
- break;
- case Heap::ErrorObject::ReferenceError:
- s = "ReferenceError";
- break;
- case Heap::ErrorObject::SyntaxError:
- s = "SyntaxError";
- break;
- case Heap::ErrorObject::TypeError:
- s = "TypeError";
- break;
- case Heap::ErrorObject::URIError:
- s = "URIError";
- break;
- }
+ s = ErrorObject::className(static_cast<Heap::ErrorObject *>(d())->errorType);
break;
case Type_ArgumentsObject:
s = "Arguments";
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index c498160c36..f1face007c 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -47,10 +47,9 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
-Heap::MathObject::MathObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype())
+Heap::MathObject::MathObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject m(scope, this);
m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(M_E));
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 472b2020b1..ff4fb12ee6 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -42,7 +42,7 @@ namespace QV4 {
namespace Heap {
struct MathObject : Object {
- MathObject(ExecutionEngine *e);
+ MathObject();
};
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index b3c0863e3e..ee3539c176 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -44,6 +44,7 @@
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
#include "qv4string_p.h"
+#include "qv4identifiertable_p.h"
#include <stdint.h>
@@ -51,15 +52,25 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype)
- : internalClass(internalClass),
- prototype(prototype ? prototype->d() : 0)
+void Object::setInternalClass(InternalClass *ic)
{
- if (internalClass->size) {
- Scope scope(internalClass->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(internalClass->engine, internalClass->size);
- }
+ d()->internalClass = ic;
+ ensureMemberData();
+}
+
+void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
+{
+ p->value = *propertyData(index);
+ *attrs = internalClass()->propertyData.at(index);
+ if (attrs->isAccessor())
+ p->set = *propertyData(index + SetterOffset);
+}
+
+void Object::setProperty(uint index, const Property *p)
+{
+ *propertyData(index) = p->value;
+ if (internalClass()->propertyData.at(index).isAccessor())
+ *propertyData(index + SetterOffset) = p->set;
}
bool Object::setPrototype(Object *proto)
@@ -81,28 +92,32 @@ void Object::put(ExecutionEngine *engine, const QString &name, const Value &valu
put(n, value);
}
-ReturnedValue Object::getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs)
+ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
- return p->value.asReturnedValue();
- if (!p->getter())
+ return v.asReturnedValue();
+ const QV4::FunctionObject *f = v.as<FunctionObject>();
+ if (!f)
return Encode::undefined();
- Scope scope(p->getter()->internalClass->engine);
- ScopedFunctionObject getter(scope, p->getter());
+ Scope scope(f->engine());
ScopedCallData callData(scope);
callData->thisObject = thisObject;
- return getter->call(callData);
+ return f->call(callData);
}
-void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value)
+void Object::putValue(uint memberIndex, const Value &value)
{
- if (internalClass()->engine->hasException)
+ QV4::InternalClass *ic = internalClass();
+ if (ic->engine->hasException)
return;
+ PropertyAttributes attrs = ic->propertyData[memberIndex];
+
if (attrs.isAccessor()) {
- if (Heap::FunctionObject *set = pd->setter()) {
- Scope scope(set->internalClass->engine);
+ FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
+ if (set) {
+ Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
@@ -116,11 +131,11 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
if (!attrs.isWritable())
goto reject;
- pd->value = value;
+ *propertyData(memberIndex) = value;
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -137,7 +152,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
@@ -147,7 +162,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
{
ExecutionEngine *e = engine();
Scope scope(e);
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
@@ -166,7 +181,7 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -189,6 +204,12 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Heap::Object *o = static_cast<Heap::Object *>(that);
+ if (o->inlineMemberSize) {
+ Value *v = o->propertyData(0);
+ for (uint i = 0; i < o->inlineMemberSize; ++i)
+ v[i].mark(e);
+ }
+
if (o->memberData)
o->memberData->mark(e);
if (o->arrayData)
@@ -197,9 +218,11 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
o->prototype->mark(e);
}
-void Object::ensureMemberIndex(uint idx)
+void Object::ensureMemberData()
{
- d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
+ QV4::InternalClass *ic = internalClass();
+ if (ic->size > d()->inlineMemberSize)
+ d()->memberData = MemberData::reallocate(ic->engine, d()->memberData, ic->size - d()->inlineMemberSize);
}
void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
@@ -207,15 +230,11 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
uint idx;
InternalClass::addMember(this, s, attributes, &idx);
-
- ensureMemberIndex(internalClass()->size);
-
if (attributes.isAccessor()) {
- Property *pp = propertyAt(idx);
- pp->value = p->value;
- pp->set = p->set;
+ *propertyData(idx + GetterOffset) = p->value;
+ *propertyData(idx + SetterOffset) = p->set;
} else {
- d()->memberData->data[idx] = p->value;
+ *propertyData(idx) = p->value;
}
}
@@ -229,8 +248,11 @@ void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
*attrs = internalClass()->propertyData[member];
- if (p)
- p->copy(propertyAt(member), *attrs);
+ if (p) {
+ p->value = *propertyData(member);
+ if (attrs->isAccessor())
+ p->set = *propertyData(member + SetterOffset);
+ }
return;
}
@@ -261,47 +283,44 @@ void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
}
// Section 8.12.2
-Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
{
Q_ASSERT(name->asArrayIndex() == UINT_MAX);
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
uint idx = o->internalClass->find(name);
if (idx < UINT_MAX) {
- if (attrs)
- *attrs = o->internalClass->propertyData[idx];
- return const_cast<Property *>(o->propertyAt(idx));
+ *attrs = o->internalClass->propertyData[idx];
+ return o->propertyData(attrs->isAccessor() ? idx + SetterOffset : idx);
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
-Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
*attrs = o->arrayData->attributes(index);
- return p;
+ return attrs->isAccessor() ? &p->set : &p->value;
}
if (o->vtable()->type == Type_StringObject) {
if (index < static_cast<const Heap::StringObject *>(o)->length()) {
// this is an evil hack, but it works, as the method is only ever called from putIndexed,
// where we don't use the returned pointer there for non writable attributes
*attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return reinterpret_cast<Property *>(0x1);
+ return reinterpret_cast<Value *>(0x1);
}
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
@@ -466,7 +485,7 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
{
Scope scope(static_cast<Object *>(m)->engine());
ScopedObject o(scope, static_cast<Object *>(m));
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
InternalClass *c = o->internalClass();
uint idx = c->find(name);
@@ -475,12 +494,12 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- o->memberData()->data[idx] = value;
+ *o->propertyData(idx) = value;
return;
}
if (idx != UINT_MAX) {
- o->putValue(o->propertyAt(idx), o->internalClass()->propertyData[idx], value);
+ o->putValue(idx, value);
return;
}
}
@@ -568,13 +587,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
continue;
}
- Property *p = o->propertyAt(it->memberIndex);
+ int idx = it->memberIndex;
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- name->setM(o->engine()->newString(n->string));
+ name->setM(o->engine()->identifierTable->stringFromIdentifier(n));
*attrs = a;
- pd->copy(p, a);
+ pd->value = *o->propertyData(idx);
+ if (a.isAccessor())
+ pd->set = *o->propertyData(idx + SetterOffset);
return;
}
}
@@ -598,7 +619,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(o->propertyAt(idx), o->internalClass()->propertyData.at(idx));
+ return getValue(*o->propertyData(idx), o->internalClass()->propertyData.at(idx));
}
o = o->prototype();
@@ -637,7 +658,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
if (pd) {
if (hasProperty)
*hasProperty = true;
- return getValue(pd, attrs);
+ return getValue(pd->value, attrs);
}
if (hasProperty)
@@ -659,17 +680,17 @@ void Object::internalPut(String *name, const Value &value)
name->makeIdentifier(engine());
uint member = internalClass()->find(name);
- Property *pd = 0;
+ Value *v = 0;
PropertyAttributes attrs;
if (member < UINT_MAX) {
- pd = propertyAt(member);
attrs = internalClass()->propertyData[member];
+ v = propertyData(attrs.isAccessor() ? member + SetterOffset : member);
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
@@ -685,7 +706,7 @@ void Object::internalPut(String *name, const Value &value)
if (!ok)
goto reject;
} else {
- pd->value = value;
+ *v = value;
}
return;
} else if (!prototype()) {
@@ -694,9 +715,9 @@ void Object::internalPut(String *name, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(name, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -709,11 +730,11 @@ void Object::internalPut(String *name, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- Q_ASSERT(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -725,7 +746,7 @@ void Object::internalPut(String *name, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode) {
+ if (engine()->current->strictMode) {
QString message = QStringLiteral("Cannot assign to read-only property \"");
message += name->toQString();
message += QLatin1Char('\"');
@@ -740,26 +761,24 @@ void Object::internalPutIndexed(uint index, const Value &value)
PropertyAttributes attrs;
- Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
- if (pd)
- attrs = arrayData()->attributes(index);
+ Value *v = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : 0;
- if (!pd && isStringObject()) {
+ if (!v && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
else
- pd->value = value;
+ *v = value;
return;
} else if (!prototype()) {
if (!isExtensible())
@@ -767,9 +786,9 @@ void Object::internalPutIndexed(uint index, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(index, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -782,11 +801,11 @@ void Object::internalPutIndexed(uint index, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- Q_ASSERT(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -798,7 +817,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -820,7 +839,7 @@ bool Object::internalDeleteProperty(String *name)
InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -838,7 +857,7 @@ bool Object::internalDeleteIndexedProperty(uint index)
if (!ad || ad->vtable()->del(this, index))
return true;
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -853,17 +872,16 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
Scope scope(engine);
name->makeIdentifier(scope.engine);
- Property *current;
- PropertyAttributes *cattrs;
uint memberIndex;
if (isArrayObject() && name->equals(engine->id_length())) {
Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
- Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
- cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
- if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
+ ScopedProperty lp(scope);
+ PropertyAttributes cattrs;
+ getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
return true;
- if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
+ if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
goto reject;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
@@ -876,8 +894,10 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
}
succeeded = setArrayLength(l);
}
- if (attrs.hasWritable() && !attrs.isWritable())
- cattrs->setWritable(false);
+ if (attrs.hasWritable() && !attrs.isWritable()) {
+ cattrs.setWritable(false);
+ InternalClass::changeMember(this, engine->id_length(), cattrs);
+ }
if (!succeeded)
goto reject;
return true;
@@ -885,10 +905,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
// Clause 1
memberIndex = internalClass()->find(name);
- current = (memberIndex < UINT_MAX) ? propertyAt(memberIndex) : 0;
- cattrs = internalClass()->propertyData.constData() + memberIndex;
- if (!current) {
+ if (memberIndex == UINT_MAX) {
// clause 3
if (!isExtensible())
goto reject;
@@ -902,7 +920,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -918,7 +936,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Pr
return defineOwnProperty2(engine, index, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -954,7 +972,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
return __defineOwnProperty__(engine, index, 0, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -965,13 +983,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (attrs.isEmpty())
return true;
- Property *current = 0;
+ Scope scope(engine);
+ ScopedProperty current(scope);
PropertyAttributes cattrs;
if (member) {
- current = propertyAt(index);
+ getProperty(index, current, &cattrs);
cattrs = internalClass()->propertyData[index];
} else if (arrayData()) {
- current = arrayData()->getProperty(index);
+ arrayData()->getProperty(index, current, &cattrs);
cattrs = arrayData()->attributes(index);
}
@@ -1005,7 +1024,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
initSparseArray();
Q_ASSERT(arrayData());
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->setGetter(0);
current->setSetter(0);
@@ -1016,7 +1034,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (!member) {
// need to convert the array and the slot
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->value = Primitive::undefinedValue();
}
@@ -1040,12 +1057,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
current->merge(cattrs, p, attrs);
if (member) {
InternalClass::changeMember(this, member, cattrs);
+ setProperty(index, current);
} else {
setArrayAttributes(index, cattrs);
+ arrayData()->setProperty(index, current);
}
return true;
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -1135,11 +1154,11 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype())
+Heap::ArrayObject::ArrayObject(const QStringList &list)
+ : Heap::Object()
{
init();
- Scope scope(engine);
+ Scope scope(internalClass->engine);
ScopedObject a(scope, this);
// Converts a QStringList to JS.
@@ -1150,19 +1169,19 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
a->arrayReserve(len);
ScopedValue v(scope);
for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = engine->newString(list.at(ii))));
+ a->arrayPut(ii, (v = scope.engine->newString(list.at(ii))));
a->setArrayLengthUnchecked(len);
}
ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (name->equals(scope.engine->id_length())) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1170,9 +1189,9 @@ ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].isInteger())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].integerValue();
- return Primitive::toUInt32(a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].doubleValue());
+ if (a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->isInteger())
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->integerValue();
+ return Primitive::toUInt32(a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->doubleValue());
}
QStringList ArrayObject::toQStringList() const
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index f129312819..58dab9691f 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -42,17 +42,19 @@
QT_BEGIN_NAMESPACE
+
namespace QV4 {
namespace Heap {
struct Object : Base {
- inline Object(ExecutionEngine *engine);
- Object(InternalClass *internal, QV4::Object *prototype);
+ inline Object() {}
- const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); }
- Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); }
+ const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ uint inlineMemberOffset;
+ uint inlineMemberSize;
InternalClass *internalClass;
Pointer<Object> prototype;
Pointer<MemberData> memberData;
@@ -80,6 +82,13 @@ struct Object : Base {
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
+#define V4_INTERNALCLASS(c) \
+ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \
+ { return e->c; }
+#define V4_PROTOTYPE(p) \
+ static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
+ { return e->p(); }
+
struct ObjectVTable
{
VTable vTable;
@@ -124,21 +133,26 @@ const QV4::ObjectVTable classname::static_vtbl = \
struct Q_QML_EXPORT Object: Managed {
V4_OBJECT2(Object, Object)
Q_MANAGED_TYPE(Object)
+ V4_INTERNALCLASS(emptyClass)
+ V4_PROTOTYPE(objectPrototype)
enum {
- IsObject = true
+ IsObject = true,
+ GetterOffset = 0,
+ SetterOffset = 1
};
InternalClass *internalClass() const { return d()->internalClass; }
- void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
+ void setInternalClass(InternalClass *ic);
+
+ const Value *propertyData(uint index) const { return d()->propertyData(index); }
+ Value *propertyData(uint index) { return d()->propertyData(index); }
- Heap::MemberData *memberData() { return d()->memberData; }
- const Heap::MemberData *memberData() const { return d()->memberData; }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
- const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
- Property *propertyAt(uint index) { return d()->propertyAt(index); }
+ void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
+ void setProperty(uint index, const Property *p);
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
@@ -147,8 +161,8 @@ struct Q_QML_EXPORT Object: Managed {
void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const;
+ Value *getValueOrSetter(String *name, PropertyAttributes *attrs);
+ Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -167,14 +181,14 @@ struct Q_QML_EXPORT Object: Managed {
//
void put(ExecutionEngine *engine, const QString &name, const Value &value);
- static ReturnedValue getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs);
- ReturnedValue getValue(const Property *p, PropertyAttributes attrs) const {
+ static ReturnedValue getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs);
+ ReturnedValue getValue(const Value &v, PropertyAttributes attrs) const {
Scope scope(this->engine());
ScopedValue t(scope, const_cast<Object *>(this));
- return getValue(t, p, attrs);
+ return getValue(t, v, attrs);
}
- void putValue(Property *pd, PropertyAttributes attrs, const Value &value);
+ void putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, const Value &value) {
@@ -189,10 +203,6 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
- void ensureMemberIndex(QV4::ExecutionEngine *e, uint idx) {
- d()->memberData = MemberData::reallocate(e, d()->memberData, idx);
- }
-
void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);
@@ -269,7 +279,6 @@ public:
return false;
}
- void ensureMemberIndex(uint idx);
inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
@@ -316,6 +325,8 @@ protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
+ void ensureMemberData();
+
private:
ReturnedValue internalGet(String *name, bool *hasProperty) const;
ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
@@ -330,39 +341,19 @@ private:
namespace Heap {
-inline Object::Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype()->m()))
-{
-}
-
struct BooleanObject : Object {
- BooleanObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- b(false)
- {
- }
-
- BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype()),
- b(b)
- {
- }
+ BooleanObject() {}
+ BooleanObject(bool b)
+ : b(b)
+ {}
bool b;
};
struct NumberObject : Object {
- NumberObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- value(0)
- {
- }
-
- NumberObject(ExecutionEngine *engine, double val)
- : Object(engine->emptyClass, engine->numberPrototype()),
- value(val)
- {
- }
+ NumberObject() {}
+ NumberObject(double val)
+ : value(val)
+ {}
double value;
};
@@ -371,15 +362,11 @@ struct ArrayObject : Object {
LengthPropertyIndex = 0
};
- ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype())
- { init(); }
- ArrayObject(ExecutionEngine *engine, const QStringList &list);
- ArrayObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+ ArrayObject()
{ init(); }
+ ArrayObject(const QStringList &list);
void init()
- { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); }
+ { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
};
}
@@ -387,6 +374,7 @@ struct ArrayObject : Object {
struct BooleanObject: Object {
V4_OBJECT2(BooleanObject, Object)
Q_MANAGED_TYPE(BooleanObject)
+ V4_PROTOTYPE(booleanPrototype)
bool value() const { return d()->b; }
@@ -395,6 +383,7 @@ struct BooleanObject: Object {
struct NumberObject: Object {
V4_OBJECT2(NumberObject, Object)
Q_MANAGED_TYPE(NumberObject)
+ V4_PROTOTYPE(numberPrototype)
double value() const { return d()->value; }
};
@@ -402,6 +391,8 @@ struct NumberObject: Object {
struct ArrayObject: Object {
V4_OBJECT2(ArrayObject, Object)
Q_MANAGED_TYPE(ArrayObject)
+ V4_INTERNALCLASS(arrayClass)
+ V4_PROTOTYPE(arrayPrototype)
void init(ExecutionEngine *engine);
@@ -415,7 +406,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- memberData()->data[Heap::ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+ *propertyData(Heap::ArrayObject::LengthPropertyIndex) = Primitive::fromUInt32(l);
}
inline void Object::push_back(const Value &v)
@@ -438,10 +429,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a
arrayData()->vtable()->reallocate(this, index + 1, false);
}
setArrayAttributes(index, attributes);
- Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
- pd->value = p->value;
- if (attributes.isAccessor())
- pd->set = p->set;
+ ArrayData::insert(this, index, &p->value, attributes.isAccessor());
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
@@ -453,8 +441,7 @@ inline void Object::arraySet(uint index, const Value &value)
if (index > 0x1000 && index > 2*d()->arrayData->alloc) {
initSparseArray();
}
- Property *pd = ArrayData::insert(this, index);
- pd->value = value;
+ ArrayData::insert(this, index, &value);
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 585f9f5c2e..7f97872092 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -144,7 +144,7 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
@@ -166,7 +166,7 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index bfe04b33aa..e34b641be9 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -67,7 +67,7 @@ struct Q_QML_EXPORT ObjectIterator
namespace Heap {
struct ForEachIteratorObject : Object {
- ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o);
+ ForEachIteratorObject(QV4::Object *o);
ObjectIterator it;
Value workArea[2];
};
@@ -85,9 +85,8 @@ protected:
};
inline
-Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o)
- : Heap::Object(engine)
- , it(engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
+Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o)
+ : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
{
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 1edf76e2de..df7441ef5d 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -108,7 +108,7 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
ScopedProperty p(scope);
p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
@@ -141,9 +141,9 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property desc;
- O->getOwnProperty(name, &attrs, &desc);
- return fromPropertyDescriptor(scope.engine, &desc, attrs);
+ ScopedProperty desc(scope);
+ O->getOwnProperty(name, &attrs, desc);
+ return fromPropertyDescriptor(scope.engine, desc, attrs);
}
ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
@@ -222,7 +222,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
if (attrs.isEmpty())
break;
PropertyAttributes nattrs;
- val = o->getValue(pd, attrs);
+ val = o->getValue(pd->value, attrs);
toPropertyDescriptor(scope.engine, val, n, &nattrs);
if (scope.engine->hasException)
return Encode::undefined();
@@ -630,7 +630,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs)
{
- if (!desc)
+ if (attrs.isEmpty())
return Encode::undefined();
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 82e232d28c..ee294b3678 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -228,9 +228,8 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
}
}
-Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
- : Heap::Object(engine)
- , object(object)
+Heap::QObjectWrapper::QObjectWrapper(QObject *object)
+ : object(object)
{
}
@@ -255,7 +254,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
return result;
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
+ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
@@ -264,20 +263,18 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return QV4::Encode::undefined();
}
- QV4::Scope scope(engine());
- QV4::ScopedString name(scope, n);
+ ExecutionEngine *v4 = engine();
- if (name->equals(scope.engine->id_destroy()) || name->equals(scope.engine->id_toString())) {
- int index = name->equals(scope.engine->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- ScopedContext global(scope, scope.engine->rootContext());
- QV4::ScopedValue method(scope, QV4::QObjectMethod::create(global, d()->object, index));
+ if (name->equals(v4->id_destroy()) || name->equals(v4->id_toString())) {
+ int index = name->equals(v4->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
if (hasProperty)
*hasProperty = true;
- return method->asReturnedValue();
+ ExecutionContext *global = v4->rootContext();
+ return QV4::QObjectMethod::create(global, d()->object, index);
}
QQmlPropertyData local;
- QQmlPropertyData *result = findProperty(scope.engine, qmlContext, name, revisionMode, &local);
+ QQmlPropertyData *result = findProperty(v4, qmlContext, name, revisionMode, &local);
if (!result) {
if (includeImports && name->startsWithUpper()) {
@@ -292,10 +289,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
r.type, Heap::QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
@@ -318,13 +315,11 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- return getProperty(scope.engine, d()->object, result);
+ return getProperty(v4, d()->object, result);
}
ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(engine);
-
QQmlData::flushPendingBinding(object, property->coreIndex);
if (property->isFunction() && !property->isVarProperty()) {
@@ -333,24 +328,19 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- ScopedContext global(scope, scope.engine->qmlContext());
+ Scope scope(engine);
+ ScopedContext global(scope, engine->qmlContext());
return QV4::QObjectMethod::create(global, object, property->coreIndex);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(engine, object, property->coreIndex));
-
- QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
-
- return handler.asReturnedValue();
+ QmlSignalHandler::initProto(engine);
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex)->asReturnedValue();
} else {
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex);
}
}
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (property->hasAccessors()) {
QQmlNotifier *n = 0;
@@ -359,6 +349,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
+ Scope scope(engine);
QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
@@ -390,7 +381,6 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
{
- QV4::Scope scope(engine);
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
*hasProperty = false;
@@ -403,6 +393,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
return QV4::Encode::null();
}
+ QV4::Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(engine, object));
if (!wrapper) {
if (hasProperty)
@@ -419,11 +410,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
QQmlPropertyData local;
- QQmlPropertyData *result = 0;
- {
- result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
- }
-
+ QQmlPropertyData *result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
if (!result)
return false;
@@ -433,8 +420,6 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
}
- Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
setProperty(engine, object, result, value);
return true;
}
@@ -686,7 +671,7 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
if (engine->jsEngine())
QQmlData::ensurePropertyCache(engine->jsEngine(), object);
- return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
+ return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue();
}
QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
@@ -1037,19 +1022,18 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (!h->internalClass)
return; // destroyObject already got called
- QPointer<QObject> object = h->object;
- if (object) {
- QQmlData *ddata = QQmlData::get(object, false);
+ if (h->object) {
+ QQmlData *ddata = QQmlData::get(h->object, false);
if (ddata) {
- if (!object->parent() && !ddata->indestructible) {
+ if (!h->object->parent() && !ddata->indestructible) {
if (ddata && ddata->ownContext && ddata->context)
ddata->context->emitDestruction();
// This object is notionally destroyed now
ddata->isQueuedForDeletion = true;
if (lastCall)
- delete object;
+ delete h->object;
else
- object->deleteLater();
+ h->object->deleteLater();
}
}
}
@@ -1061,9 +1045,6 @@ void QObjectWrapper::destroyObject(bool lastCall)
DEFINE_OBJECT_VTABLE(QObjectWrapper);
-// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
-// correctly in a worker thread
-
namespace {
template<typename A, typename B, typename C, typename D, typename E,
@@ -1729,24 +1710,23 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->object = object;
if (QQmlData *ddata = QQmlData::get(object))
method->d()->propertyCache = ddata->propertyCache;
method->d()->index = index;
- method->d()->valueTypeWrapper = Primitive::undefinedValue();
return method.asReturnedValue();
}
ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->propertyCache = valueType->d()->propertyCache;
method->d()->index = index;
- method->d()->valueTypeWrapper = *valueType;
+ method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
@@ -1815,8 +1795,8 @@ ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
- Scope scope(engine());
- ScopedContext context(scope, scope.engine->currentContext());
+ ExecutionEngine *v4 = engine();
+ ExecutionContext *context = v4->currentContext;
if (d()->index == DestroyMethod)
return method_destroy(context, callData->args, callData->argc);
else if (d()->index == ToStringMethod)
@@ -1824,11 +1804,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
QQmlObjectOrGadget object(d()->object.data());
if (!d()->object) {
- Scoped<QQmlValueTypeWrapper> wrapper(scope, d()->valueTypeWrapper);
- if (!wrapper)
+ if (!d()->valueTypeWrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr);
}
QQmlPropertyData method;
@@ -1860,8 +1839,9 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
}
if (method.isV4Function()) {
+ Scope scope(v4);
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
- QQmlV4Function func(callData, rv, scope.engine);
+ QQmlV4Function func(callData, rv, v4);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
@@ -1871,31 +1851,46 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
}
if (!method.isOverload()) {
- return CallPrecise(object, method, scope.engine, callData);
+ return CallPrecise(object, method, v4, callData);
} else {
- return CallOverloaded(object, method, scope.engine, callData, d()->propertyCache);
+ return CallOverloaded(object, method, v4, callData, d()->propertyCache);
}
}
void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
{
QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
- This->valueTypeWrapper.mark(e);
+ if (This->valueTypeWrapper)
+ This->valueTypeWrapper->mark(e);
FunctionObject::markObjects(that, e);
}
DEFINE_OBJECT_VTABLE(QObjectMethod);
-Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex)
- : Heap::Object(engine)
- , object(object)
+Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex)
+ : object(object)
, signalIndex(signalIndex)
{
}
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
+void QmlSignalHandler::initProto(ExecutionEngine *engine)
+{
+ if (engine->signalHandlerPrototype()->d())
+ return;
+
+ Scope scope(engine);
+ ScopedObject o(scope, engine->newObject());
+ QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
+ QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
+ o->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
+ o->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
+
+ engine->jsObjects[QV4::ExecutionEngine::SignalHandlerProto] = o->d();
+}
+
void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value)
{
QV4::WeakValue v;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index da24c81f40..1126013806 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -69,8 +69,10 @@ struct QObjectSlotDispatcher;
namespace Heap {
+struct QQmlValueTypeWrapper;
+
struct QObjectWrapper : Object {
- QObjectWrapper(QV4::ExecutionEngine *engine, QObject *object);
+ QObjectWrapper(QObject *object);
QPointer<QObject> object;
};
@@ -80,13 +82,13 @@ struct QObjectMethod : FunctionObject {
QQmlRefPointer<QQmlPropertyCache> propertyCache;
int index;
- Value valueTypeWrapper;
+ Pointer<QQmlValueTypeWrapper> valueTypeWrapper;
const QMetaObject *metaObject();
};
struct QmlSignalHandler : Object {
- QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex);
+ QmlSignalHandler(QObject *object, int signalIndex);
QPointer<QObject> object;
int signalIndex;
};
@@ -167,10 +169,13 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
struct QmlSignalHandler : public QV4::Object
{
V4_OBJECT2(QmlSignalHandler, QV4::Object)
+ V4_PROTOTYPE(signalHandlerPrototype)
V4_NEEDS_DESTROY
int signalIndex() const { return d()->signalIndex; }
QObject *object() const { return d()->object.data(); }
+
+ static void initProto(ExecutionEngine *v4);
};
class MultiplyWrappedQObjectMap : public QObject,
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 329e5d2c56..1839ff17ab 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -62,35 +62,30 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn
using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
-DEFINE_OBJECT_VTABLE(RegExpPrototype);
-Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::RegExpObject::RegExpObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(ic->engine, QString(), false, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false);
o->d()->global = false;
- o->init(ic->engine);
+ o->initProperties();
}
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype())
- , value(value->d())
+Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global)
+ : value(value->d())
, global(global)
{
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->init(engine);
+ o->initProperties();
}
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype())
+Heap::RegExpObject::RegExpObject(const QRegExp &re)
{
- value = 0;
global = false;
// Convert the pattern to a ECMAScript pattern.
@@ -130,26 +125,21 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re
pattern = ecmaPattern;
}
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
- o->init(engine);
+ o->initProperties();
}
-void RegExpObject::init(ExecutionEngine *engine)
+void RegExpObject::initProperties()
{
- Scope scope(engine);
- ScopedObject protectThis(scope, this);
+ *propertyData(Index_LastIndex) = Primitive::fromInt32(0);
- ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
- ScopedValue v(scope, Primitive::fromInt32(0));
- insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
- if (!this->value())
- return;
+ Q_ASSERT(value());
- QString p = this->value()->pattern;
+ QString p = value()->pattern;
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -157,10 +147,10 @@ void RegExpObject::init(ExecutionEngine *engine)
p.replace('/', QLatin1String("\\/"));
}
- defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
- defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global()));
- defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase));
- defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine));
+ *propertyData(Index_Source) = engine()->newString(p);
+ *propertyData(Index_Global) = Primitive::fromBoolean(global());
+ *propertyData(Index_IgnoreCase) = Primitive::fromBoolean(value()->ignoreCase);
+ *propertyData(Index_Multiline) = Primitive::fromBoolean(value()->multiLine);
}
@@ -172,10 +162,10 @@ void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-Property *RegExpObject::lastIndexProperty()
+Value *RegExpObject::lastIndexProperty()
{
Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
- return propertyAt(0);
+ return propertyData(0);
}
// Converts a JS RegExp to a QRegExp.
@@ -239,17 +229,16 @@ void Heap::RegExpCtor::clearLastMatch()
ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedContext ctx(scope, scope.engine->currentContext());
ScopedValue r(scope, callData->argument(0));
ScopedValue f(scope, callData->argument(1));
Scoped<RegExpObject> re(scope, r);
if (re) {
if (!f->isUndefined())
- return ctx->engine()->throwTypeError();
+ return scope.engine->throwTypeError();
Scoped<RegExp> regexp(scope, re->value());
- return Encode(ctx->d()->engine->newRegExpObject(regexp, re->global()));
+ return Encode(scope.engine->newRegExpObject(regexp, re->global()));
}
QString pattern;
@@ -274,16 +263,16 @@ ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
} else if (str.at(i) == QLatin1Char('m') && !multiLine) {
multiLine = true;
} else {
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
}
}
}
- Scoped<RegExp> regexp(scope, RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
+ Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine));
if (!regexp->isValid())
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid regular expression"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
- return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
+ return Encode(scope.engine->newRegExpObject(regexp, global));
}
ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
@@ -354,9 +343,9 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
return Encode::undefined();
QString s = arg->stringValue()->toQString();
- int offset = r->global() ? r->lastIndexProperty()->value.toInt32() : 0;
+ int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
if (offset < 0 || offset > s.length()) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
@@ -367,7 +356,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
@@ -383,8 +372,8 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- array->memberData()->data[Index_ArrayIndex] = Primitive::fromInt32(result);
- array->memberData()->data[Index_ArrayInput] = arg;
+ *array->propertyData(Index_ArrayIndex) = Primitive::fromInt32(result);
+ *array->propertyData(Index_ArrayInput) = arg;
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
@@ -393,7 +382,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- r->lastIndexProperty()->value = Primitive::fromInt32(matchOffsets[1]);
+ *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 29d20614de..4f803df9c8 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -57,9 +57,9 @@ namespace QV4 {
namespace Heap {
struct RegExpObject : Object {
- RegExpObject(InternalClass *ic, QV4::Object *prototype);
- RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
- RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
+ RegExpObject();
+ RegExpObject(QV4::RegExp *value, bool global);
+ RegExpObject(const QRegExp &re);
Pointer<RegExp> value;
bool global;
@@ -74,16 +74,13 @@ struct RegExpCtor : FunctionObject {
void clearLastMatch();
};
-struct RegExpPrototype : RegExpObject
-{
- inline RegExpPrototype(ExecutionEngine *e);
-};
-
}
struct RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
+ V4_INTERNALCLASS(regExpObjectClass)
+ V4_PROTOTYPE(regExpPrototype)
// needs to be compatible with the flags in qv4jsir_p.h
enum Flags {
@@ -93,6 +90,11 @@ struct RegExpObject: Object {
};
enum {
+ Index_LastIndex = 0,
+ Index_Source = 1,
+ Index_Global = 2,
+ Index_IgnoreCase = 3,
+ Index_Multiline = 4,
Index_ArrayIndex = Heap::ArrayObject::LengthPropertyIndex + 1,
Index_ArrayInput = Index_ArrayIndex + 1
};
@@ -100,9 +102,9 @@ struct RegExpObject: Object {
Heap::RegExp *value() const { return d()->value; }
bool global() const { return d()->global; }
- void init(ExecutionEngine *engine);
+ void initProperties();
- Property *lastIndexProperty();
+ Value *lastIndexProperty();
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
@@ -128,8 +130,6 @@ struct RegExpCtor: FunctionObject
struct RegExpPrototype: RegExpObject
{
- V4_OBJECT2(RegExpPrototype, RegExpObject)
-
void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_exec(CallContext *ctx);
@@ -145,11 +145,6 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
-inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype())
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 9316223696..0d7a1851b8 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -268,10 +268,9 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId)
{
- QV4::Function *clos = engine->currentContext()->compilationUnit->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->current->compilationUnit->runtimeFunctions[functionId];
Q_ASSERT(clos);
- Scope scope(engine);
- return FunctionObject::createScriptFunction(ScopedContext(scope, engine->currentContext()), clos)->asReturnedValue();
+ return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue();
}
ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, const Value &index)
@@ -292,7 +291,7 @@ ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base,
ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
return deleteMemberString(engine, base, name);
}
@@ -308,9 +307,8 @@ ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value &
ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return Encode(ctx->deleteProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return Encode(engine->currentContext->deleteProperty(name));
}
QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right)
@@ -566,7 +564,7 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left
void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object.toObject(engine));
if (!o)
return;
@@ -663,15 +661,14 @@ ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator)
void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->setProperty(name, value);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->setProperty(name, value);
}
ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object);
if (o)
@@ -691,9 +688,8 @@ ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object,
ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return ctx->getProperty(name);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return engine->currentContext->getProperty(name);
}
#endif // V4_BOOTSTRAP
@@ -909,12 +905,12 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedFunctionObject o(scope, l->globalGetter(l, engine));
if (!o)
return engine->throwTypeError();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval()))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
@@ -926,11 +922,10 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
{
Q_ASSERT(callData->thisObject.isUndefined());
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject base(scope);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue func(scope, ctx->getPropertyAndBase(name, base.getRef()));
+ ScopedValue func(scope, engine->currentContext->getPropertyAndBase(name, base.getRef()));
if (scope.engine->hasException)
return Encode::undefined();
@@ -980,7 +975,7 @@ ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject baseObject(scope, callData->thisObject);
if (!baseObject) {
Q_ASSERT(!callData->thisObject.isEmpty());
@@ -1006,7 +1001,7 @@ ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, Call
ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1046,7 +1041,7 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedObject f(scope, l->globalGetter(l, engine));
if (!f)
return engine->throwTypeError();
@@ -1058,9 +1053,8 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedValue func(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue func(scope, engine->currentContext->getProperty(name));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1084,7 +1078,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
{
Scope scope(engine);
ScopedObject thisObject(scope, callData->thisObject.toObject(engine));
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
if (scope.engine->hasException)
return Encode::undefined();
@@ -1097,7 +1091,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1145,9 +1139,8 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue prop(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue prop(scope, engine->currentContext->getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
return Runtime::typeofValue(engine, prop);
@@ -1156,7 +1149,7 @@ QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject obj(scope, base.toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1175,14 +1168,6 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &
return Runtime::typeofValue(engine, prop);
}
-void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
-{
- Scope scope(engine);
- ScopedObject obj(scope, o.toObject(engine));
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newWithContext(obj);
-}
-
ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
{
if (!engine->hasException)
@@ -1190,45 +1175,47 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
return engine->catchException(0);
}
+/* The next three methods are a bit tricky. They can't open up a Scope, as that
+ * would mess up the pushing of the context.
+ *
+ * Instead the push/pop pair acts as a non local scope.
+ */
+void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
+{
+ engine->pushContext(engine->currentContext->newWithContext(o.toObject(engine)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
+}
+
void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- Scope scope(engine);
- ScopedValue v(scope, engine->catchException(0));
- ScopedString exceptionVarName(scope, engine->currentContext()->compilationUnit->runtimeStrings[exceptionVarNameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newCatchContext(exceptionVarName, v);
+ ExecutionContext *c = engine->currentContext;
+ engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
}
void Runtime::popScope(ExecutionEngine *engine)
{
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
engine->popContext();
+ engine->jsStackTop -= 2;
}
void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->createMutableBinding(name, deletable);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->createMutableBinding(name, deletable);
}
ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
{
- Scope scope(engine);
- ScopedArrayObject a(scope, engine->newArrayObject());
-
- if (length) {
- a->arrayReserve(length);
- a->arrayPut(0, values, length);
- a->setArrayLengthUnchecked(length);
- }
- return a.asReturnedValue();
+ return engine->newArrayObject(values, length)->asReturnedValue();
}
ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
{
Scope scope(engine);
- QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
+ QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId];
ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
@@ -1238,7 +1225,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
}
for (uint i = 0; i < klass->size; ++i)
- o->memberData()->data[i] = *args++;
+ *o->propertyData(i) = *args++;
if (arrayValueCount > 0) {
ScopedValue entry(scope);
@@ -1269,10 +1256,10 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->currentContext()->type == Heap::ExecutionContext::Type_CallContext);
- Scope scope(engine);
- Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext()));
- return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
+ Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext);
+ QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext);
+ QV4::InternalClass *ic = c->d()->strictMode ? engine->strictArgumentsObjectClass : engine->argumentsObjectClass;
+ return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), c)->asReturnedValue();
}
#endif // V4_BOOTSTRAP
@@ -1363,7 +1350,7 @@ ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
+ return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1459,13 +1446,13 @@ ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
return engine->qmlSingletonWrapper(name);
}
void Runtime::convertThisToObject(ExecutionEngine *engine)
{
- Value *t = &engine->currentContext()->callData->thisObject;
+ Value *t = &engine->current->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index e19aeaf882..0c79897015 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -54,18 +54,12 @@ struct ScopedValue;
struct Scope {
inline Scope(ExecutionContext *ctx)
: engine(ctx->d()->engine)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
explicit Scope(ExecutionEngine *e)
: engine(e)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
@@ -73,6 +67,7 @@ struct Scope {
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
+ Q_ASSERT(engine->currentContext < mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
@@ -82,9 +77,6 @@ struct Scope {
}
Value *alloc(int nValues) {
-#ifndef QT_NO_DEBUG
- size += nValues;
-#endif
return engine->jsAlloca(nValues);
}
@@ -94,9 +86,6 @@ struct Scope {
ExecutionEngine *engine;
Value *mark;
-#ifndef QT_NO_DEBUG
- mutable int size;
-#endif
private:
Q_DISABLE_COPY(Scope)
@@ -108,18 +97,12 @@ struct ScopedValue
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
*ptr = v;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, Heap::Base *o)
@@ -129,27 +112,18 @@ struct ScopedValue
#if QT_POINTER_SIZE == 4
ptr->setTag(QV4::Value::Managed_Type);
#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(m->asReturnedValue());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(v);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue &operator=(const Value &v) {
@@ -213,18 +187,12 @@ struct Scoped
#if QT_POINTER_SIZE == 4
ptr->setTag(QV4::Value::Managed_Type);
#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v.as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, Heap::Base *o)
{
@@ -232,69 +200,45 @@ struct Scoped
v = o;
ptr = scope.engine->jsStackTop++;
setPointer(v.as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v.ptr->as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(value_convert<T>(scope.engine, v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v ? v->as<T>() : 0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, T *t)
{
ptr = scope.engine->jsStackTop++;
setPointer(t);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, typename T::Data *t)
{
ptr = scope.engine->jsStackTop++;
*ptr = t;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(QV4::Value::fromReturnedValue(v).as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped<T> &operator=(Heap::Base *o) {
@@ -414,29 +358,18 @@ struct ScopedProperty
struct ExecutionContextSaver
{
ExecutionEngine *engine;
- Value *savedContext;
+ ExecutionContext *savedContext;
- ExecutionContextSaver(Scope &scope, ExecutionContext *context)
- : engine(context->d()->engine)
- , savedContext(scope.alloc(1))
+ ExecutionContextSaver(Scope &scope)
+ : engine(scope.engine)
{
- savedContext->setM(context->d());
-#if QT_POINTER_SIZE == 4
- savedContext->setTag(QV4::Value::Managed_Type);
-#endif
- }
- ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
- : engine(context->engine)
- , savedContext(scope.alloc(1))
- {
- savedContext->setM(context);
-#if QT_POINTER_SIZE == 4
- savedContext->setTag(QV4::Value::Managed_Type);
-#endif
+ savedContext = engine->currentContext;
}
~ExecutionContextSaver()
{
- engine->current = static_cast<Heap::ExecutionContext *>(savedContext->heapObject());
+ Q_ASSERT(engine->jsStackTop > engine->currentContext);
+ engine->currentContext = savedContext;
+ engine->current = savedContext->d();
}
};
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 7067d10e22..7f2f22780e 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -59,11 +59,15 @@ namespace QV4 {
namespace Heap {
struct CompilationUnitHolder : Object {
- inline CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit);
+ inline CompilationUnitHolder(CompiledData::CompilationUnit *unit);
QQmlRefPointer<CompiledData::CompilationUnit> unit;
};
+struct QmlBindingWrapper : FunctionObject {
+ QmlBindingWrapper(QV4::QmlContext *scope, Function *f);
+};
+
}
struct CompilationUnitHolder : public Object
@@ -73,12 +77,17 @@ struct CompilationUnitHolder : public Object
};
inline
-Heap::CompilationUnitHolder::CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
- : Heap::Object(engine)
- , unit(unit)
+Heap::CompilationUnitHolder::CompilationUnitHolder(CompiledData::CompilationUnit *unit)
+ : unit(unit)
{
}
+struct QmlBindingWrapper : FunctionObject {
+ V4_OBJECT2(QmlBindingWrapper, FunctionObject)
+
+ static ReturnedValue call(const Managed *that, CallData *callData);
+};
+
}
QT_END_NAMESPACE
@@ -88,7 +97,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f)
: Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
Q_ASSERT(scope->inUse());
@@ -96,12 +105,6 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Functio
function = f;
if (function)
function->compilationUnit->addref();
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
-
- this->scope = scope->newQmlContext(qml);
- internalClass->engine->popContext();
}
ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
@@ -113,65 +116,33 @@ ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
QV4::Function *f = This->function();
if (!f)
return QV4::Encode::undefined();
- ScopedContext context(scope, v4->currentContext());
- Scoped<CallContext> ctx(scope, context->newCallContext(This, callData));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f));
return result->asReturnedValue();
}
-static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
-{
- QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, ctx->d()->parent.cast<Heap::CallContext>());
- Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
- return signalEmittingContext->argument(parameterIndex);
-}
-
-Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
-{
- ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
- QV4::Scope valueScope(engine);
- QV4::Scoped<QmlContextWrapper> qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
- ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QmlContext> wrapperContext(valueScope, global->newQmlContext(qmlScopeObject));
- engine->popContext();
-
- if (!signalParameters.isEmpty()) {
- if (error)
- QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
- QV4::ScopedProperty p(valueScope);
- QV4::ScopedString s(valueScope);
- int index = 0;
- foreach (const QByteArray &param, signalParameters) {
- QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapperContext, index++, signalParameterGetter));
- p->setGetter(g);
- p->setSetter(0);
- s = engine->newString(QString::fromUtf8(param));
- qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
- }
- }
-
- QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
- return function->d();
-}
-
-Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit)
+Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(v4, qml), vmFunction(0), parseAsBinding(true)
+ , vmFunction(0), parseAsBinding(true)
{
+ if (qml)
+ qmlContext.set(v4, *qml);
+
parsed = true;
vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : 0;
if (vmFunction) {
Scope valueScope(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
}
@@ -242,7 +213,7 @@ void Script::parse()
isel->setUseFastLookups(false);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
@@ -263,10 +234,10 @@ ReturnedValue Script::run()
QV4::ExecutionEngine *engine = scope->engine();
QV4::Scope valueScope(engine);
- if (qml.isUndefined()) {
+ if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- ExecutionContextSaver ctxSaver(valueScope, scope);
+ ExecutionContextSaver ctxSaver(valueScope);
ContextStateSaver stateSaver(valueScope, scope);
scope->d()->strictMode = vmFunction->isStrict();
scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
@@ -274,8 +245,8 @@ ReturnedValue Script::run()
return Q_V4_PROFILE(engine, vmFunction);
} else {
- Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedFunctionObject f(valueScope, engine->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -352,15 +323,15 @@ ReturnedValue Script::qmlBinding()
parse();
ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedObject v(valueScope, v4->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
return v.asReturnedValue();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext)
{
QV4::Scope scope(engine);
- QV4::Script qmlScript(engine, scopeObject, script, QString());
+ QV4::Script qmlScript(engine, qmlContext, script, QString());
qmlScript.parse();
QV4::ScopedValue result(scope);
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index fad011f88a..63e8239342 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -36,6 +36,7 @@
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
+#include "qv4context_p.h"
#include <QQmlError>
@@ -85,32 +86,19 @@ struct ContextStateSaver {
}
};
-namespace Heap {
-struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml);
-};
-
-}
-
-struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
- V4_OBJECT2(QmlBindingWrapper, FunctionObject)
-
- static ReturnedValue call(const Managed *that, CallData *callData);
-
- static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
- const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-};
-
struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(engine, qml), vmFunction(0), parseAsBinding(true) {}
- Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit);
+ , vmFunction(0), parseAsBinding(true) {
+ if (qml)
+ qmlContext.set(engine, *qml);
+ }
+ Script(ExecutionEngine *engine, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -120,7 +108,7 @@ struct Q_QML_EXPORT Script {
bool strictMode;
bool inheritContext;
bool parsed;
- QV4::PersistentValue qml;
+ QV4::PersistentValue qmlContext;
QV4::PersistentValue compilationUnitHolder;
Function *vmFunction;
bool parseAsBinding;
@@ -134,7 +122,7 @@ struct Q_QML_EXPORT Script {
static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source,
QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
};
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 23bbcc60e1..36ee848d00 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -207,8 +207,8 @@ namespace Heap {
template <typename Container>
struct QQmlSequence : Object {
- QQmlSequence(QV4::ExecutionEngine *engine, const Container &container);
- QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex);
+ QQmlSequence(const Container &container);
+ QQmlSequence(QObject *object, int propertyIndex);
mutable Container container;
QPointer<QObject> object;
@@ -223,6 +223,7 @@ struct QQmlSequence : public QV4::Object
{
V4_OBJECT2(QQmlSequence<Container>, QV4::Object)
Q_MANAGED_TYPE(QmlSequence)
+ V4_PROTOTYPE(sequencePrototype)
V4_NEEDS_DESTROY
public:
@@ -543,26 +544,24 @@ public:
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype())
- , container(container)
+Heap::QQmlSequence<Container>::QQmlSequence(const Container &container)
+ : container(container)
, propertyIndex(-1)
, isReference(false)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->init();
}
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype())
- , object(object)
+Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
+ : object(object)
, propertyIndex(propertyIndex)
, isReference(true)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->loadReference();
@@ -644,7 +643,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(object, propertyIndex)); \
return obj.asReturnedValue(); \
} else
@@ -662,7 +661,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 01f94eeac6..bb1d3aeb69 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -246,15 +246,12 @@ void SparseArray::deleteNode(SparseArrayNode *z)
x->setParent(y->parent());
if (root == y)
root = x;
- else if (y->parent()->left == y) {
+ else if (y->parent()->left == y)
y->parent()->left = x;
- if (x)
- x->size_left += y->size_left;
- } else {
+ else
y->parent()->right = x;
- if (x)
- x->size_left += y->size_left;
- }
+ if (x && x == y->right)
+ x->size_left += y->size_left;
y->size_left = 0;
}
if (y->color() != SparseArrayNode::Red) {
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 9fbafa7ded..757ec6c6bf 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -67,25 +67,17 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::StringObject::StringObject()
{
Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
- string = ic->engine->newString();
-
- Scope scope(ic->engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(ic->engine->id_length(), Primitive::fromInt32(0));
+ string = internalClass->engine->id_empty()->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const QV4::String *str)
- : Heap::Object(engine->emptyClass, engine->stringPrototype())
+Heap::StringObject::StringObject(const QV4::String *str)
{
string = str->d();
-
- Scope scope(engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length(), Primitive::fromUInt32(length()));
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
}
Heap::String *Heap::StringObject::getIndex(uint index) const
@@ -98,7 +90,7 @@ Heap::String *Heap::StringObject::getIndex(uint index) const
uint Heap::StringObject::length() const
{
- return string->toQString().length();
+ return string->len;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
@@ -109,7 +101,7 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
Q_ASSERT(!!o);
if (index < static_cast<uint>(o->d()->string->toQString().length())) {
- if (v4->currentContext()->strictMode)
+ if (v4->current->strictMode)
v4->throwTypeError();
return false;
}
@@ -511,7 +503,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- regExp->lastIndexProperty()->value = Primitive::fromUInt32(0);
+ *regExp->lastIndexProperty() = Primitive::fromUInt32(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index aa56a79bc3..86d77c726a 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -44,8 +44,12 @@ namespace QV4 {
namespace Heap {
struct StringObject : Object {
- StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const QV4::String *string);
+ enum {
+ LengthPropertyIndex = 0
+ };
+
+ StringObject();
+ StringObject(const QV4::String *string);
String *string;
Heap::String *getIndex(uint index) const;
@@ -61,6 +65,8 @@ struct StringCtor : FunctionObject {
struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
+ V4_INTERNALCLASS(stringClass)
+ V4_PROTOTYPE(stringPrototype)
Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index f06eeb08b9..b45bbb713c 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -216,11 +216,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
if (l != len)
scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
uint byteLength = len * operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> buffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, byteLength));
+ Scoped<ArrayBuffer> buffer(scope, scope.engine->newArrayBuffer(byteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = 0;
@@ -236,11 +236,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
uint byteLength = typedArray->d()->byteLength;
uint destByteLength = byteLength*destElementSize/srcElementSize;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, destByteLength));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(destByteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = destByteLength;
array->d()->byteOffset = 0;
@@ -290,7 +290,7 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
byteLength = (uint)l;
}
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = byteOffset;
@@ -305,11 +305,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
return scope.engine->throwTypeError();
uint elementSize = operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, l * elementSize));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(l * elementSize));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = l * elementSize;
array->d()->byteOffset = 0;
@@ -335,13 +335,17 @@ ReturnedValue TypedArrayCtor::call(const Managed *that, CallData *callData)
return construct(that, callData);
}
-Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t)
- : Heap::Object(e->emptyClass, e->typedArrayPrototype + t),
- type(operations + t),
+Heap::TypedArray::TypedArray(Type t)
+ : type(operations + t),
arrayType(t)
{
}
+Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
+{
+ return e->memoryManager->allocObject<TypedArray>(e->emptyClass, e->typedArrayPrototype + t, t);
+}
+
void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
{
static_cast<TypedArray::Data *>(that)->buffer->mark(e);
@@ -383,7 +387,7 @@ void TypedArray::putIndexed(Managed *m, uint index, const Value &value)
return;
reject:
- if (scope.engine->currentContext()->strictMode)
+ if (scope.engine->current->strictMode)
scope.engine->throwTypeError();
}
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 8e1090dcd2..74ee285da4 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -69,7 +69,7 @@ struct TypedArray : Object {
NTypes
};
- TypedArray(ExecutionEngine *e, Type t);
+ TypedArray(Type t);
const TypedArrayOperations *type;
Pointer<ArrayBuffer> buffer;
@@ -85,7 +85,7 @@ struct TypedArrayCtor : FunctionObject {
};
struct TypedArrayPrototype : Object {
- inline TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t);
+ inline TypedArrayPrototype(TypedArray::Type t);
TypedArray::Type type;
};
@@ -96,6 +96,8 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
{
V4_OBJECT2(TypedArray, Object)
+ static Heap::TypedArray *create(QV4::ExecutionEngine *e, Heap::TypedArray::Type t);
+
uint byteLength() const {
return d()->byteLength;
}
@@ -142,9 +144,8 @@ struct TypedArrayPrototype : Object
};
inline
-Heap::TypedArrayPrototype::TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t)
- : Heap::Object(e)
- , type(t)
+Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t)
+ : type(t)
{
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 6305e6dfbb..14094878d8 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -85,8 +85,8 @@ struct Q_QML_PRIVATE_EXPORT Value
Q_ALWAYS_INLINE quint64 val() const { return _val; }
Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
- Q_ALWAYS_INLINE void setValue(quint32 v) { setTagValue(tag(), v); }
- Q_ALWAYS_INLINE void setTag(quint32 t) { setTagValue(t, value()); }
+ Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); }
+ Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static inline int valueOffset() { return 0; }
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index f9e26efe71..4609373cc9 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -43,12 +43,15 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
- : Heap::Object(engine->emptyClass, engine->variantPrototype())
+Heap::VariantObject::VariantObject()
+{
+}
+
+Heap::VariantObject::VariantObject(const QVariant &value)
{
data = value;
if (isScarce())
- engine->scarceResources.insert(this);
+ internalClass->engine->scarceResources.insert(this);
}
bool VariantObject::Data::isScarce() const
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index b19f12bb98..4680912354 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -60,10 +60,8 @@ namespace Heap {
struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
{
- VariantObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
- {}
- VariantObject(QV4::ExecutionEngine *engine, const QVariant &value);
+ VariantObject();
+ VariantObject(const QVariant &value);
~VariantObject() {
if (isScarce())
node.remove();
@@ -77,6 +75,7 @@ struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
struct VariantObject : Object
{
V4_OBJECT2(VariantObject, Object)
+ V4_PROTOTYPE(variantPrototype)
V4_NEEDS_DESTROY
void addVmePropertyReference();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 0edd7378a7..68f996c4c7 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -375,8 +375,8 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
const uchar *exceptionHandler = 0;
QV4::Scope scope(engine);
- QV4::ScopedContext context(scope, engine->currentContext());
- engine->currentContext()->lineNumber = -1;
+ QV4::ExecutionContext *context = engine->currentContext;
+ engine->current->lineNumber = -1;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
@@ -650,18 +650,18 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
Runtime::pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPushCatchScope)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
Runtime::pushWithScope(VALUE(instr.arg), engine);
- context = engine->currentContext();
+ context = engine->currentContext;
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
Runtime::popScope(engine);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
@@ -889,7 +889,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
@@ -898,7 +898,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
MOTH_END_INSTR(Line)
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index b880c9c8d5..0887e43441 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -64,6 +64,8 @@
#include <pthread_np.h>
#endif
+#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT (std::size_t)128*1024
+
using namespace WTF;
QT_BEGIN_NAMESPACE
@@ -124,7 +126,7 @@ struct MemoryManager::Data
, maxShift(6)
, maxChunkSize(32*1024)
, unmanagedHeapSize(0)
- , unmanagedHeapSizeGCLimit(64 * 1024)
+ , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
, largeItems(0)
, totalLargeItemsAllocated(0)
{
@@ -219,7 +221,8 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
} // namespace
MemoryManager::MemoryManager(ExecutionEngine *engine)
- : m_d(new Data)
+ : engine(engine)
+ , m_d(new Data)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
{
@@ -246,13 +249,12 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) {
runGC();
- if (m_d->unmanagedHeapSizeGCLimit <= m_d->unmanagedHeapSize)
+ if (3*m_d->unmanagedHeapSizeGCLimit <= 4*m_d->unmanagedHeapSize)
+ // more than 75% full, raise limit
m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2;
else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit)
- m_d->unmanagedHeapSizeGCLimit /= 2;
- else if (m_d->unmanagedHeapSizeGCLimit - m_d->unmanagedHeapSize < 5 * unmanagedSize)
- // try preventing running the GC all the time when we're just below the threshold limit and manage to collect just enough to do this one allocation
- m_d->unmanagedHeapSizeGCLimit += std::max(std::size_t(8 * 1024), 5 * unmanagedSize);
+ // less than 25% full, lower limit
+ m_d->unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, m_d->unmanagedHeapSizeGCLimit/2);
didGCRun = true;
}
@@ -265,7 +267,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
// we use malloc for this
MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
- malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem),
+ malloc(Q_V4_PROFILE_ALLOC(engine, size + sizeof(MemoryManager::Data::LargeItem),
Profiling::LargeItem)));
memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
item->next = m_d->largeItems;
@@ -301,7 +303,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
PageAllocation allocation = PageAllocation::allocate(
- Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
+ Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
m_d->heapChunks.append(allocation);
@@ -335,7 +337,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_ALLOC(this, m, size);
#endif
- Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem);
+ Q_V4_PROFILE_ALLOC(engine, size, Profiling::SmallItem);
++m_d->allocCount[pos];
++m_d->totalAlloc;
@@ -356,14 +358,14 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
void MemoryManager::mark()
{
- Value *markBase = m_d->engine->jsStackTop;
-
- m_d->engine->markObjects();
+ Value *markBase = engine->jsStackTop;
- m_persistentValues->mark(m_d->engine);
+ engine->markObjects();
collectFromJSStack();
+ m_persistentValues->mark(engine);
+
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -391,13 +393,13 @@ void MemoryManager::mark()
}
if (keepAlive)
- qobjectWrapper->mark(m_d->engine);
+ qobjectWrapper->mark(engine);
- if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
- drainMarkStack(m_d->engine, markBase);
+ if (engine->jsStackTop >= engine->jsStackLimit)
+ drainMarkStack(engine, markBase);
}
- drainMarkStack(m_d->engine, markBase);
+ drainMarkStack(engine, markBase);
}
void MemoryManager::sweep(bool lastSweep)
@@ -416,7 +418,7 @@ void MemoryManager::sweep(bool lastSweep)
(*it) = Primitive::undefinedValue();
}
- if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
+ if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) {
for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
if (!it.value().isNullOrUndefined())
it = multiplyWrappedQObjects->erase(it);
@@ -432,7 +434,7 @@ void MemoryManager::sweep(bool lastSweep)
for (int i = 0; i < m_d->heapChunks.size(); ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
- chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine, &m_d->unmanagedHeapSize);
+ chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
}
QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
@@ -444,7 +446,7 @@ void MemoryManager::sweep(bool lastSweep)
// Release that chunk if it could have been spared since the last GC run without any difference.
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
- Q_V4_PROFILE_DEALLOC(m_d->engine, 0, chunkIter->size(), Profiling::HeapPage);
+ Q_V4_PROFILE_DEALLOC(engine, 0, chunkIter->size(), Profiling::HeapPage);
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_FREE(this, header);
#endif
@@ -476,17 +478,17 @@ void MemoryManager::sweep(bool lastSweep)
m->vtable()->destroy(m);
*last = i->next;
- free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
+ free(Q_V4_PROFILE_DEALLOC(engine, i, i->size + sizeof(Data::LargeItem),
Profiling::LargeItem));
i = *last;
}
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
- Heap::ExecutionContext *ctx = engine()->current;
+ QV4::ExecutionContext *ctx = engine->currentContext;
while (ctx) {
- ctx->clearMarkBit();
- ctx = ctx->parent;
+ ctx->d()->clearMarkBit();
+ ctx = engine->parentContext(ctx);
}
}
}
@@ -520,9 +522,11 @@ void MemoryManager::runGC()
int markTime = t.elapsed();
t.restart();
const size_t usedBefore = getUsedMem();
+ const size_t largeItemsBefore = getLargeItemsMem();
int chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
+ const size_t largeItemsAfter = getLargeItemsMem();
int sweepTime = t.elapsed();
qDebug() << "========== GC ==========";
@@ -533,6 +537,9 @@ void MemoryManager::runGC()
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
+ qDebug() << "Large item memory before GC:" << largeItemsBefore;
+ qDebug() << "Large item memory after GC:" << largeItemsAfter;
+ qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
qDebug() << "======== End GC ========";
}
@@ -589,10 +596,7 @@ MemoryManager::~MemoryManager()
#endif
}
-ExecutionEngine *MemoryManager::engine() const
-{
- return m_d->engine;
-}
+
void MemoryManager::dumpStats() const
{
@@ -622,13 +626,13 @@ void MemoryManager::willAllocate(std::size_t size)
void MemoryManager::collectFromJSStack() const
{
- Value *v = m_d->engine->jsStackBase;
- Value *top = m_d->engine->jsStackTop;
+ Value *v = engine->jsStackBase;
+ Value *top = engine->jsStackTop;
while (v < top) {
Managed *m = v->as<Managed>();
if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
- m->mark(m_d->engine);
+ m->mark(engine);
++v;
}
}
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index c01866ff11..c77d5e503d 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -37,6 +37,7 @@
#include <private/qv4global_p.h>
#include <private/qv4value_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4object_p.h>
//#define DETAILED_MM_STATS
@@ -91,10 +92,149 @@ public:
return static_cast<typename ManagedType::Data *>(o);
}
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject(InternalClass *ic)
+ {
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ o->internalClass = ic;
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject()
+ {
+ InternalClass *ic = ObjectType::defaultInternalClass(engine);
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ Object *prototype = ObjectType::defaultPrototype(engine);
+ o->internalClass = ic;
+ o->prototype = prototype->d();
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ManagedType, typename Arg1>
+ typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
+ (void)new (t->d()) typename ManagedType::Data(this, arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject()
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+
template <typename ManagedType>
typename ManagedType::Data *alloc()
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data();
return t->d();
@@ -103,25 +243,16 @@ public:
template <typename ManagedType, typename Arg1>
typename ManagedType::Data *alloc(Arg1 arg1)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1);
return t->d();
}
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
- {
- Scope scope(engine());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- (void)new (t->d()) typename ManagedType::Data(this, arg1);
- return t->d();
- }
-
template <typename ManagedType, typename Arg1, typename Arg2>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2);
return t->d();
@@ -130,7 +261,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
return t->d();
@@ -139,7 +270,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
return t->d();
@@ -148,7 +279,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
return t->d();
@@ -158,8 +289,6 @@ public:
void setGCBlocked(bool blockGC);
void runGC();
- ExecutionEngine *engine() const;
-
void dumpStats() const;
size_t getUsedMem() const;
@@ -182,9 +311,9 @@ private:
void mark();
void sweep(bool lastSweep = false);
-protected:
- QScopedPointer<Data> m_d;
public:
+ QV4::ExecutionEngine *engine;
+ QScopedPointer<Data> m_d;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
};
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;
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index a154da8323..df429e5bc1 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -36,6 +36,7 @@
#include <private/qqmlnullablevalue_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlmetatype_p.h>
#include <qqmlengine.h>
#include <qqmlcontext.h>
@@ -49,6 +50,29 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+void validateProperty(QObject *target, const QString &propertyName, QObject *binding)
+{
+ if (!target)
+ return;
+
+ const QMetaObject *mo = target->metaObject();
+ const int index = mo->indexOfProperty(propertyName.toUtf8());
+ if (index == -1) {
+ qmlInfo(binding) << "Property '" << propertyName << "' does not exist on " << QQmlMetaType::prettyTypeName(target) << ".";
+ return;
+ }
+
+ const QMetaProperty mp = mo->property(index);
+ if (!mp.isWritable()) {
+ qmlInfo(binding) << "Property '" << propertyName << "' on " << QQmlMetaType::prettyTypeName(target) << " is read-only.";
+ return;
+ }
+}
+
+}
+
class QQmlBindPrivate : public QObjectPrivate
{
public:
@@ -186,8 +210,10 @@ void QQmlBind::setObject(QObject *obj)
d->when = true;
}
d->obj = obj;
- if (d->componentComplete)
+ if (d->componentComplete) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
@@ -213,8 +239,10 @@ void QQmlBind::setProperty(const QString &p)
d->when = true;
}
d->propName = p;
- if (d->componentComplete)
+ if (d->componentComplete) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
@@ -253,8 +281,10 @@ void QQmlBind::componentComplete()
{
Q_D(QQmlBind);
d->componentComplete = true;
- if (!d->prop.isValid())
+ if (!d->prop.isValid()) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index bc70e68904..f2de911725 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -64,13 +64,13 @@ struct DelegateModelGroupFunction : FunctionObject {
};
struct QQmlDelegateModelGroupChange : Object {
- QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine);
+ QQmlDelegateModelGroupChange() {}
QQmlChangeSet::Change change;
};
struct QQmlDelegateModelGroupChangeArray : Object {
- QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes);
+ QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes);
QVector<QQmlChangeSet::Change> changes;
};
@@ -83,7 +83,7 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
{
- return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
+ return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code);
}
static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData)
@@ -1717,7 +1717,7 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
s = v4->newString(QStringLiteral("isUnresolved"));
QV4::ScopedFunctionObject f(scope);
- QV4::ScopedContext global(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *global = scope.engine->rootContext();
p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
p->setSetter(0);
proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -2488,7 +2488,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV8Engine *v8 = model->m_cacheMetaType->v8Engine;
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, cacheItem));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
o->setPrototype(p);
++cacheItem->scriptRef;
@@ -3233,7 +3233,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
+ return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>();
}
static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
@@ -3261,11 +3261,6 @@ struct QQmlDelegateModelGroupChange : QV4::Object
}
};
-QV4::Heap::QQmlDelegateModelGroupChange::QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
-{
-}
-
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
struct QQmlDelegateModelGroupChangeArray : public QV4::Object
@@ -3275,7 +3270,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object
public:
static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
- return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
+ return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes);
}
quint32 count() const { return d()->changes.count(); }
@@ -3321,11 +3316,10 @@ public:
}
};
-QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- : QV4::Heap::Object(engine)
- , changes(changes)
+QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes)
+ : changes(changes)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
}
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 5c28021c0e..3a19163cbd 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -154,7 +154,7 @@ protected:
namespace QV4 {
namespace Heap {
struct QQmlDelegateModelItemObject : Object {
- inline QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item);
+ inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item);
~QQmlDelegateModelItemObject();
QQmlDelegateModelItem *item;
};
@@ -168,9 +168,8 @@ struct QQmlDelegateModelItemObject : QV4::Object
V4_NEEDS_DESTROY
};
-QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
- : QV4::Heap::Object(engine)
- , item(item)
+QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QQmlDelegateModelItem *item)
+ : item(item)
{
}
diff --git a/src/qml/types/qqmlitemselectionmodel.qdoc b/src/qml/types/qqmlitemselectionmodel.qdoc
index 185ffb5fa4..441d219de8 100644
--- a/src/qml/types/qqmlitemselectionmodel.qdoc
+++ b/src/qml/types/qqmlitemselectionmodel.qdoc
@@ -103,7 +103,7 @@
*/
/*!
- \qmlmethod QItemSelection selection()
+ \qmlmethod QItemSelection ItemSelectionModel::selection()
*/
/*!
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 799f7a0b8a..a4c0f7043f 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -1875,6 +1875,30 @@ QVariant QQmlListModel::data(const QModelIndex &index, int role) const
return data(index.row(), role);
}
+bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (row >= count() || row < 0)
+ return false;
+
+ if (m_dynamicRoles) {
+ const QByteArray property = m_roles.at(role).toUtf8();
+ if (m_modelObjects[row]->setValue(property, value)) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ } else {
+ const ListLayout::Role &r = m_listModel->getExistingRole(role);
+ const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
+ if (roleIndex != -1) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ }
+
+ return false;
+}
+
QVariant QQmlListModel::data(int index, int role) const
{
QVariant v;
@@ -2252,7 +2276,7 @@ QQmlV4Handle QQmlListModel::get(int index) const
result = QV4::QObjectWrapper::wrap(scope.engine, object);
} else {
QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- result = scope.engine->memoryManager->alloc<QV4::ModelObject>(scope.engine, object, const_cast<QQmlListModel *>(this), index);
+ result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index);
}
}
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index b5a5ef3265..21de392234 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -71,6 +71,7 @@ public:
QModelIndex index(int row, int column, const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QHash<int,QByteArray> roleNames() const;
QVariant data(int index, int role) const;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index bd0f028e7a..d7e0defaec 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -155,8 +155,8 @@ namespace QV4 {
namespace Heap {
struct ModelObject : public QObjectWrapper {
- ModelObject(QV4::ExecutionEngine *engine, QObject *object, QQmlListModel *model, int elementIndex)
- : QObjectWrapper(engine, object)
+ ModelObject(QObject *object, QQmlListModel *model, int elementIndex)
+ : QObjectWrapper(object)
, m_model(model)
, m_elementIndex(elementIndex)
{}
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 0aa5dc4ef6..03915ab414 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -165,7 +165,7 @@ public:
QUrl source;
bool initialized;
QQuickWorkerScript *owner;
- QV4::PersistentValue object;
+ QV4::PersistentValue qmlContext;
};
QHash<int, WorkerScript *> workers;
@@ -221,7 +221,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
"})"
QV4::Scope scope(m_v4Engine);
- QV4::ScopedContext globalContext(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *globalContext = scope.engine->rootContext();
onmessage.set(scope.engine, QV4::Script(globalContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
QV4::Script createsendscript(globalContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
@@ -291,7 +291,6 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call
return QV4::Encode::undefined();
}
-// Requires handle scope and context scope
QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
{
if (!script->initialized) {
@@ -300,9 +299,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
QV4::Scope scope(v4);
- script->object.set(v4, QV4::QmlContextWrapper::urlScope(v4, script->source));
-
- QV4::Scoped<QV4::QmlContextWrapper> w(scope, script->object.value());
+ QV4::Scoped<QV4::QmlContextWrapper> w(scope, QV4::QmlContextWrapper::urlScope(v4, script->source));
Q_ASSERT(!!w);
w->setReadOnly(false);
@@ -312,9 +309,11 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))), api);
w->setReadOnly(true);
+
+ script->qmlContext.set(v4, v4->rootContext()->newQmlContext(w));
}
- return script->object.value();
+ return script->qmlContext.value();
}
bool QQuickWorkerScriptEnginePrivate::event(QEvent *event)
@@ -354,10 +353,12 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value());
QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value());
+ Q_ASSERT(!!qmlContext);
QV4::ScopedCallData callData(scope, 2);
callData->thisObject = workerEngine->global();
- callData->args[0] = script->object.value();
+ callData->args[0] = qmlContext->d()->qml; // ###
callData->args[1] = value;
f->call(callData);
if (scope.hasException()) {
@@ -382,13 +383,12 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
return;
script->source = url;
- QV4::ScopedObject activation(scope, getWorker(script));
- if (!activation)
- return;
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, getWorker(script));
+ Q_ASSERT(!!qmlContext);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- program.reset(new QV4::Script(v4, activation, jsUnit));
+ program.reset(new QV4::Script(v4, qmlContext, jsUnit));
} else {
QFile f(fileName);
if (!f.open(QIODevice::ReadOnly)) {
@@ -400,7 +400,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
QString sourceCode = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(sourceCode);
- program.reset(new QV4::Script(v4, activation, sourceCode, url.toString()));
+ program.reset(new QV4::Script(v4, qmlContext, sourceCode, url.toString()));
program->parse();
}
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index f83798488c..29398ff98c 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -221,9 +221,9 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ScopedContext global(scope, v4->rootContext());
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
+ QV4::ExecutionContext *global = v4->rootContext();
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
p->setGetter(g);
p->setSetter(s);
proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
@@ -428,7 +428,7 @@ public:
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->alloc<QQmlDelegateModelItemObject>(proto->engine(), this));
+ QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
o->setPrototype(proto);
++scriptRef;
return o.asReturnedValue();
@@ -606,7 +606,7 @@ public:
{
QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, this));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
QV4::ScopedObject p(scope, data->listItemProto.value());
o->setPrototype(p);
++scriptRef;
diff --git a/src/qml/util/qqmllistcompositor_p.h b/src/qml/util/qqmllistcompositor_p.h
index 8e10cb1546..2ddbc5d5a1 100644
--- a/src/qml/util/qqmllistcompositor_p.h
+++ b/src/qml/util/qqmllistcompositor_p.h
@@ -166,7 +166,7 @@ public:
struct Change
{
inline Change() {}
- inline Change(iterator it, int count, uint flags, int moveId = -1);
+ inline Change(const iterator &it, int count, uint flags, int moveId = -1);
int count;
uint flags;
int moveId;
@@ -188,14 +188,14 @@ public:
struct Insert : public Change
{
Insert() {}
- Insert(iterator it, int count, uint flags, int moveId = -1)
+ Insert(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
struct Remove : public Change
{
Remove() {}
- Remove(iterator it, int count, uint flags, int moveId = -1)
+ Remove(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
@@ -224,14 +224,14 @@ public:
void setFlags(iterator from, int count, Group group, uint flags, QVector<Insert> *inserts = 0);
void setFlags(Group fromGroup, int from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(fromGroup, from, count, fromGroup, flags, inserts); }
- void setFlags(iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
+ void setFlags(const iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(from, count, from.group, flags, inserts); }
void clearFlags(Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(iterator from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(Group fromGroup, int from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(fromGroup, from, count, fromGroup, flags, removals); }
- void clearFlags(iterator from, int count, uint flags, QVector<Remove> *removals = 0) {
+ void clearFlags(const iterator &from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(from, count, from.group, flags, removals); }
bool verifyMoveTo(Group fromGroup, int from, Group toGroup, int to, int count, Group group) const;
@@ -347,7 +347,7 @@ inline QQmlListCompositor::insert_iterator::insert_iterator(
Range *range, int offset, Group group, int groupCount)
: iterator(range, offset, group, groupCount) {}
-inline QQmlListCompositor::Change::Change(iterator it, int count, uint flags, int moveId)
+inline QQmlListCompositor::Change::Change(const iterator &it, int count, uint flags, int moveId)
: count(count), flags(flags), moveId(moveId)
{
for (int i = 0; i < MaximumGroupCount; ++i)
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 2e95ab7cb5..28f3c8f215 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -172,8 +172,7 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu
modify or clear its associated value.
\note When deriving a class from QQmlPropertyMap, use the
- \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)}
- {protected two-argument constructor}
+ \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)} {protected two-argument constructor}
which ensures that the class is correctly registered with the Qt \l {Meta-Object System}.
*/
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 5e9712d202..c90308cf1a 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -315,6 +315,8 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
return 1;
}
+ qputenv("QT_QTESTLIB_RUNNING", "1");
+
// Register the test object
qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject);
// Scan through all of the "tst_*.qml" files and run each of them
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 8ef77dac4c..0a8fc2ab0a 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -585,7 +585,7 @@ with multiple windows.
\section1 Batch Roots
- In addition to mergin compatible primitives into batches, the
+ In addition to merging compatible primitives into batches, the
default renderer also tries to minimize the amount of data that
needs to be sent to the GPU for every frame. The default renderer
identifies subtrees which belong together and tries to put these
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index e44ba2116e..1c021e7dc6 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -475,17 +475,20 @@ namespace QV4 {
namespace Heap {
struct QQuickJSContext2D : Object {
- QQuickJSContext2D(QV4::ExecutionEngine *engine);
+ QQuickJSContext2D() {}
QQuickContext2D* context;
};
struct QQuickJSContext2DPrototype : Object {
- QQuickJSContext2DPrototype(ExecutionEngine *e)
- : Object(e) {}
+ QQuickJSContext2DPrototype() {}
};
struct QQuickContext2DStyle : Object {
- QQuickContext2DStyle(QV4::ExecutionEngine *e);
+ QQuickContext2DStyle()
+ {
+ patternRepeatX = false;
+ patternRepeatY = false;
+ }
QBrush brush;
bool patternRepeatX:1;
@@ -493,13 +496,13 @@ struct QQuickContext2DStyle : Object {
};
struct QQuickJSContext2DPixelData : Object {
- QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine);
+ QQuickJSContext2DPixelData();
QImage image;
};
struct QQuickJSContext2DImageData : Object {
- QQuickJSContext2DImageData(QV4::ExecutionEngine *engine);
+ QQuickJSContext2DImageData();
QV4::Value pixelData;
};
@@ -552,11 +555,6 @@ struct QQuickJSContext2D : public QV4::Object
static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickJSContext2D::QQuickJSContext2D(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
-{
-}
-
DEFINE_OBJECT_VTABLE(QQuickJSContext2D);
@@ -567,7 +565,7 @@ public:
static QV4::Heap::QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine)
{
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->alloc<QQuickJSContext2DPrototype>(engine));
+ QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->allocObject<QQuickJSContext2DPrototype>());
o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
@@ -675,12 +673,7 @@ struct QQuickContext2DStyle : public QV4::Object
static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickContext2DStyle::QQuickContext2DStyle(QV4::ExecutionEngine *e)
- : QV4::Heap::Object(e)
-{
- patternRepeatX = false;
- patternRepeatY = false;
-}
+
DEFINE_OBJECT_VTABLE(QQuickContext2DStyle);
@@ -890,10 +883,9 @@ struct QQuickJSContext2DPixelData : public QV4::Object
static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
+QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData()
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
}
@@ -914,12 +906,11 @@ struct QQuickJSContext2DImageData : public QV4::Object
}
};
-QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
+QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData()
{
pixelData = QV4::Primitive::undefinedValue();
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, 0);
@@ -933,7 +924,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
{
QV4::Scope scope(v4);
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DPixelData>(v4));
+ QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DPixelData>());
QV4::ScopedObject p(scope, ed->pixelArrayProto.value());
pixelData->setPrototype(p);
@@ -945,7 +936,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
- QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DImageData>(v4));
+ QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DImageData>());
imageData->d()->pixelData = pixelData.asReturnedValue();
return imageData.asReturnedValue();
}
@@ -1553,7 +1544,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
}
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
@@ -1604,7 +1595,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
@@ -1647,7 +1638,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QConicalGradient(x, y, angle);
@@ -1706,7 +1697,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
CHECK_CONTEXT(r)
if (ctx->argc() >= 2) {
- QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QColor color = scope.engine->toVariant(ctx->args()[0], qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
@@ -4324,7 +4315,7 @@ void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine)
QQuickContext2DEngineData *ed = engineData(engine);
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->alloc<QQuickJSContext2D>(engine));
+ QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocObject<QQuickJSContext2D>());
QV4::ScopedObject p(scope, ed->contextPrototype.value());
wrapper->setPrototype(p);
wrapper->d()->context = this;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index a1d765d6ec..2958c0a67a 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1401,6 +1401,15 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
if (!q->isComponentComplete())
return;
+ if (currentItem && currentItem->item == item) {
+ const bool contentFlowReversed = isContentFlowReversed();
+ const qreal pos = position();
+ const qreal sz = size();
+ const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning;
+ const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd;
+ QQuickItemPrivate::get(currentItem->item)->setCulled(currentItem->endPosition() < from || currentItem->position() > to);
+ }
+
if (item != contentItem && (!highlight || item != highlight->item)) {
if ((orient == QQuickListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QQuickListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 466f4698cb..0040843929 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -949,7 +949,7 @@ QUrl QQuickLoaderPrivate::resolveSourceUrl(QQmlV4Function *args)
if (arg.isEmpty())
return QUrl();
- QQmlContextData *context = args->context();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
return context->resolvedUrl(QUrl(arg));
}
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 4a44760035..b933dc240a 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -921,6 +921,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent(&mouseEvent);
+ stealThisEvent = d->stealMouse;
break;
default:
break;
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index e6b63d32f2..13ace44f9a 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -451,6 +451,12 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
break;
}
+ case QEvent::TouchCancel:
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ break;
default:
QQuickItem::touchEvent(event);
break;
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index 8d93c577ab..4172b83419 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -67,15 +67,11 @@ public:
To enable QPainter to do anti-aliased rendering, use setAntialiasing().
- To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
- start by implementing its only pure virtual public function: paint(), which implements
- the actual painting. To get the size of the area painted by the item, use
- contentsBoundingRect().
-
- Starting Qt 5.4, the QQuickPaintedItem is a
- \l{QSGTextureProvider}{texture provider}
- and can be used directly in \l {ShaderEffect}{ShaderEffects} and other
- classes that consume texture providers.
+ To write your own painted item, you first create a subclass of
+ QQuickPaintedItem, and then start by implementing its only pure virtual
+ public function: paint(), which implements the actual painting. The
+ painting will be inside the rectangle spanning from 0,0 to
+ width(),height().
*/
/*!
@@ -109,11 +105,12 @@ public:
This enum describes flags that you can enable to improve rendering
performance in QQuickPaintedItem. By default, none of these flags are set.
- \value FastFBOResizing If your item gets resized often and you are using the
- QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
- item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
- is a costly operation, by enabling this property the Framebuffer Object will use a texture
- larger than the actual size of the item to avoid as much as possible resizing it.
+ \value FastFBOResizing Resizing an FBO can be a costly operation on a few
+ OpenGL driver implementations. To work around this, one can set this flag
+ to let the QQuickPaintedItem allocate one large framebuffer object and
+ instead draw into a subregion of it. This saves the resize at the cost of
+ using more memory. Please note that this is not a common problem.
+
*/
/*!
@@ -332,16 +329,47 @@ void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints
update();
}
+QSize QQuickPaintedItem::textureSize() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->textureSize;
+}
+
/*!
- This function returns the outer bounds of the item as a rectangle; all painting must be
- restricted to inside an item's bounding rect.
+ \property QQuickPaintedItem::textureSize
+
+ \brief Defines the size of the texture.
- If the contents size has not been set it reflects the size of the item; otherwise
- it reflects the contents size scaled by the contents scale.
+ Changing the texture's size does not affect the coordinate system used in
+ paint(). A scale factor is instead applied so painting should still happen
+ inside 0,0 to width(),height().
- Use this function to know the area painted by the item.
+ By default, the texture size will have the same size as this item.
- \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
+ \note If the item is on a window with a device pixel ratio different from
+ 1, this scale factor will be implicitly applied to the texture size.
+
+ */
+void QQuickPaintedItem::setTextureSize(const QSize &size)
+{
+ Q_D(QQuickPaintedItem);
+ if (d->textureSize == size)
+ return;
+ d->textureSize = size;
+ emit textureSizeChanged();
+}
+
+#if QT_VERSION >= 0x060000
+#warning "Remove: QQuickPaintedItem::contentsBoundingRect, contentsScale, contentsSize. Also remove them from qsgadaptationlayer_p.h and qsgdefaultpainternode.h/cpp."
+#endif
+
+/*!
+ \obsolete
+
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
+
+ \sa width(), height(), textureSize()
*/
QRectF QQuickPaintedItem::contentsBoundingRect() const
{
@@ -360,11 +388,13 @@ QRectF QQuickPaintedItem::contentsBoundingRect() const
/*!
\property QQuickPaintedItem::contentsSize
- \brief The size of the contents
+ \brief Obsolete method for setting the contents size.
+ \obsolete
+
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
- The contents size is the size of the item in regards to how it is painted
- using the paint() function. This is distinct from the size of the
- item in regards to height() and width().
+ \sa width(), height(), textureSize()
*/
QSize QQuickPaintedItem::contentsSize() const
{
@@ -386,6 +416,7 @@ void QQuickPaintedItem::setContentsSize(const QSize &size)
}
/*!
+ \obsolete
This convenience function is equivalent to calling setContentsSize(QSize()).
*/
void QQuickPaintedItem::resetContentsSize()
@@ -395,12 +426,13 @@ void QQuickPaintedItem::resetContentsSize()
/*!
\property QQuickPaintedItem::contentsScale
- \brief The scale of the contents
+ \brief Obsolete method for scaling the contents.
+ \obsolete
- All painting happening in paint() is scaled by the contents scale. This is distinct
- from the scale of the item in regards to scale().
+ This function is provided for compatibility, use size() in combination
+ with textureSize() to decide the size of what you are drawing.
- The default value is 1.
+ \sa width(), height(), textureSize()
*/
qreal QQuickPaintedItem::contentsScale() const
{
@@ -487,6 +519,9 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
This function, which is usually called by the QML Scene Graph, paints the
contents of an item in local coordinates.
+ The underlying texture will have a size defined by textureSize when set,
+ or the item's size, multiplied by the window's device pixel ratio.
+
The function is called after the item has been filled with the fillColor.
Reimplement this function in a QQuickPaintedItem subclass to provide the
@@ -500,6 +535,8 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
\warning Extreme caution must be used when creating QObjects, emitting signals, starting
timers and similar inside this function as these will have affinity to the rendering thread.
+
+ \sa width(), height(), textureSize
*/
/*!
@@ -525,17 +562,35 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->node = node;
}
- QRectF br = contentsBoundingRect();
+ bool hasTextureSize = d->textureSize.width() > 0 && d->textureSize.height() > 0;
+
+ // Use the compat mode if any of the compat things are set and
+ // textureSize is 0x0.
+ if (!hasTextureSize
+ && (d->contentsScale != 1
+ || (d->contentsSize.width() > 0 && d->contentsSize.height() > 0))) {
+ QRectF br = contentsBoundingRect();
+ node->setContentsScale(d->contentsScale);
+ QSize size = QSize(qRound(br.width()), qRound(br.height()));
+ node->setSize(size);
+ node->setTextureSize(size);
+ } else {
+ // The default, use textureSize or item's size * device pixel ratio
+ node->setContentsScale(1);
+ QSize itemSize(qRound(width()), qRound(height()));
+ node->setSize(itemSize);
+ QSize textureSize = (hasTextureSize ? d->textureSize : itemSize)
+ * window()->effectiveDevicePixelRatio();
+ node->setTextureSize(textureSize);
+ }
node->setPreferredRenderTarget(d->renderTarget);
node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
- node->setSize(QSize(qRound(br.width()), qRound(br.height())));
node->setSmoothPainting(d->antialiasing);
node->setLinearFiltering(d->smooth);
node->setMipmapping(d->mipmap);
node->setOpaquePainting(d->opaquePainting);
node->setFillColor(d->fillColor);
- node->setContentsScale(d->contentsScale);
node->setDirty(d->dirtyRect);
node->update();
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index 28eb3398a0..8c9ae2eebb 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -48,6 +48,8 @@ class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
+ Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+
public:
QQuickPaintedItem(QQuickItem *parent = 0);
virtual ~QQuickPaintedItem();
@@ -88,6 +90,9 @@ public:
qreal contentsScale() const;
void setContentsScale(qreal);
+ QSize textureSize() const;
+ void setTextureSize(const QSize &size);
+
QColor fillColor() const;
void setFillColor(const QColor&);
@@ -104,6 +109,7 @@ Q_SIGNALS:
void contentsSizeChanged();
void contentsScaleChanged();
void renderTargetChanged();
+ void textureSizeChanged();
protected:
QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index 2759d9d683..e77254c0e6 100644
--- a/src/quick/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
@@ -52,6 +52,7 @@ public:
QColor fillColor;
QQuickPaintedItem::RenderTarget renderTarget;
QQuickPaintedItem::PerformanceHints performanceHints;
+ QSize textureSize;
QRect dirtyRect;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 924c455872..895a616cb7 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1371,6 +1371,13 @@ QQuickText::QQuickText(QQuickItem *parent)
d->init();
}
+QQuickText::QQuickText(QQuickTextPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickText);
+ d->init();
+}
+
QQuickText::~QQuickText()
{
}
@@ -1451,7 +1458,7 @@ QQuickText::~QQuickText()
Sets the style name of the font.
The style name is case insensitive. If set, the font will be matched against style name instead
- of the font properties \l weight, \l bold and \l italic.
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
*/
/*!
@@ -2292,18 +2299,19 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
bool widthMaximum = newGeometry.width() >= oldGeometry.width() && !d->widthExceeded;
bool heightMaximum = newGeometry.height() >= oldGeometry.height() && !d->heightExceeded;
+ bool verticalPositionChanged = heightChanged && d->vAlign != AlignTop;
+
if ((!widthChanged && !heightChanged) || d->internalWidthUpdate)
goto geomChangeDone;
- if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged)
- || (vAlign() != QQuickText::AlignTop && heightChanged)) {
+ if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged) || verticalPositionChanged) {
// If the width has changed and we're not left aligned do an update so the text is
// repositioned even if a full layout isn't required. And the same for vertical.
d->updateType = QQuickTextPrivate::UpdatePaintNode;
update();
}
- if (!wrapped && !elide && !scaleFont)
+ if (!wrapped && !elide && !scaleFont && !verticalPositionChanged)
goto geomChangeDone; // left aligned unwrapped text without eliding never needs relayout
if (elide // eliding and dimensions were and remain invalid;
@@ -2312,7 +2320,7 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
goto geomChangeDone;
}
- if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected()) // Size is sufficient and growing.
+ if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected() && !verticalPositionChanged) // Size is sufficient and growing.
goto geomChangeDone;
if (!(widthChanged || widthMaximum) && !d->isLineLaidOutConnected()) { // only height has changed
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index f92927c9c4..6a4b128f6e 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -264,6 +264,8 @@ Q_SIGNALS:
Q_REVISION(6) void bottomPaddingChanged();
protected:
+ QQuickText(QQuickTextPrivate &dd, QQuickItem *parent = 0);
+
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index f43df691b5..21086f1c3f 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QTextLayout;
class QQuickTextDocumentWithImageResources;
-class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QQuickText)
public:
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 7bc5fab677..04e43c017e 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -106,7 +106,9 @@ QQuickTextControlPrivate::QQuickTextControlPrivate()
hadSelectionOnMousePress(false),
wordSelectionEnabled(false),
hasImState(false),
- cursorRectangleChanged(false)
+ cursorRectangleChanged(false),
+ lastSelectionStart(-1),
+ lastSelectionEnd(-1)
{}
bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
@@ -403,11 +405,19 @@ void QQuickTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /
}
bool current = cursor.hasSelection();
- if (current == lastSelectionState)
+ int selectionStart = cursor.selectionStart();
+ int selectionEnd = cursor.selectionEnd();
+ if (current == lastSelectionState && (!current || (selectionStart == lastSelectionStart && selectionEnd == lastSelectionEnd)))
return;
- lastSelectionState = current;
- emit q->copyAvailable(current);
+ if (lastSelectionState != current) {
+ lastSelectionState = current;
+ emit q->copyAvailable(current);
+ }
+
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+
if (!forceEmitSelectionChanged) {
#ifndef QT_NO_IM
if (hasFocus)
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index 4c3e03a552..3c2e579737 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -156,6 +156,9 @@ public:
bool hasImState : 1;
bool cursorRectangleChanged : 1;
+ int lastSelectionStart;
+ int lastSelectionEnd;
+
void _q_copyLink();
};
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 0a26f0119f..5523beb72a 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -212,7 +212,7 @@ QString QQuickTextEdit::text() const
Sets the style name of the font.
The style name is case insensitive. If set, the font will be matched against style name instead
- of the font properties \l weight, \l bold and \l italic.
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
*/
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 041baa4199..d69c489b2d 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -235,7 +235,7 @@ QString QQuickTextInputPrivate::realText() const
Sets the style name of the font.
The style name is case insensitive. If set, the font will be matched against style name instead
- of the font properties \l weight, \l bold and \l italic.
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
*/
/*!
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index b0b24ca69a..867f7d9d15 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -54,7 +54,7 @@ DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker);
QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
{
QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
- return e->memoryManager->alloc<QQuickRootItemMarker>(e, window);
+ return e->memoryManager->allocObject<QQuickRootItemMarker>(window);
}
void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 6f673368d5..57aafd086a 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -98,7 +98,10 @@ namespace QV4 {
namespace Heap {
struct QQuickRootItemMarker : Object {
- inline QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window);
+ inline QQuickRootItemMarker(QQuickWindow *window)
+ : window(window)
+ {
+ }
QQuickWindow *window;
};
@@ -115,12 +118,7 @@ struct QQuickRootItemMarker : public Object
};
-inline
-Heap::QQuickRootItemMarker::QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window)
- : Heap::Object(engine)
- , window(window)
-{
-}
+
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index d19fa0e17d..6e52d6a849 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -546,8 +546,8 @@ public:
};
protected:
- void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
- void render();
+ void nodeChanged(QSGNode *node, QSGNode::DirtyState state) Q_DECL_OVERRIDE;
+ void render() Q_DECL_OVERRIDE;
private:
enum ClipTypeBit
@@ -616,7 +616,7 @@ private:
void visualizeOverdraw();
void visualizeOverdraw_helper(Node *node);
void visualizeDrawGeometry(const QSGGeometry *g);
- void setCustomRenderMode(const QByteArray &mode);
+ void setCustomRenderMode(const QByteArray &mode) Q_DECL_OVERRIDE;
QSet<Node *> m_taggedRoots;
QDataBuffer<Element *> m_opaqueRenderList;
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index fde3fa06b2..ceb455fb28 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -160,6 +160,7 @@ public:
virtual void setFillColor(const QColor &c) = 0;
virtual void setContentsScale(qreal s) = 0;
virtual void setFastFBOResizing(bool dynamic) = 0;
+ virtual void setTextureSize(const QSize &size) = 0;
virtual QImage toImage() const = 0;
virtual void update() = 0;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 14bc0fad07..9f8788123b 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -73,7 +73,7 @@ static inline int qsg_device_pixel_ratio(QOpenGLContext *ctx)
else
devicePixelRatio = w->devicePixelRatio();
} else {
- devicePixelRatio = ctx->screen()->devicePixelRatio();
+ devicePixelRatio = ctx->screen() ? ctx->screen()->devicePixelRatio() : qGuiApp->devicePixelRatio();
}
return devicePixelRatio;
}
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
index be8deb2aa3..38bcc7a3f3 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
@@ -76,6 +76,8 @@ QSGDefaultPainterNode::QSGDefaultPainterNode(QQuickPaintedItem *item)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
, m_texture(0)
, m_gl_device(0)
+ , m_fillColor(Qt::transparent)
+ , m_contentsScale(1.0)
, m_dirtyContents(false)
, m_opaquePainting(false)
, m_linear_filtering(false)
@@ -84,8 +86,6 @@ QSGDefaultPainterNode::QSGDefaultPainterNode(QQuickPaintedItem *item)
, m_extensionsChecked(false)
, m_multisamplingSupported(false)
, m_fastFBOResizing(false)
- , m_fillColor(Qt::transparent)
- , m_contentsScale(1.0)
, m_dirtyGeometry(false)
, m_dirtyRenderTarget(false)
, m_dirtyTexture(false)
@@ -136,18 +136,35 @@ void QSGDefaultPainterNode::paint()
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
}
- painter.scale(m_contentsScale, m_contentsScale);
-
- QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
- qFloor(dirtyRect.y()/m_contentsScale),
- qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
- qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ QRect clipRect;
+ QRect dirtyTextureRect;
+
+ if (m_contentsScale == 1) {
+ qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
+ qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
+ painter.scale(scaleX, scaleY);
+ clipRect = dirtyRect;
+ dirtyTextureRect = QRectF(dirtyRect.x() * scaleX,
+ dirtyRect.y() * scaleY,
+ dirtyRect.width() * scaleX,
+ dirtyRect.height() * scaleY).toAlignedRect();
+ } else {
+ painter.scale(m_contentsScale, m_contentsScale);
+ QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
+ qFloor(dirtyRect.y()/m_contentsScale),
+ qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
+ qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ clipRect = sclip;
+ dirtyTextureRect = dirtyRect;
+ }
- if (!m_dirtyRect.isNull())
- painter.setClipRect(sclip);
+ // only clip if we were originally updating only a subrect
+ if (!m_dirtyRect.isNull()) {
+ painter.setClipRect(clipRect);
+ }
painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(sclip, m_fillColor);
+ painter.fillRect(clipRect, m_fillColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_item->paint(&painter);
@@ -155,9 +172,9 @@ void QSGDefaultPainterNode::paint()
if (m_actualRenderTarget == QQuickPaintedItem::Image) {
m_texture->setImage(m_image);
- m_texture->setDirtyRect(dirtyRect);
+ m_texture->setDirtyRect(dirtyTextureRect);
} else if (m_multisampledFbo) {
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyTextureRect, m_multisampledFbo, dirtyTextureRect);
}
if (m_multisampledFbo)
@@ -276,7 +293,7 @@ void QSGDefaultPainterNode::updateRenderTarget()
if (!m_image.isNull() && !m_dirtyGeometry)
return;
- m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
+ m_image = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied);
m_image.fill(Qt::transparent);
}
@@ -302,12 +319,12 @@ void QSGDefaultPainterNode::updateFBOSize()
int fboWidth;
int fboHeight;
if (m_fastFBOResizing) {
- fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.width() - 1));
- fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.height() - 1));
+ fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.width() - 1));
+ fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.height() - 1));
} else {
QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize();
- fboWidth = qMax(minimumFBOSize.width(), m_size.width());
- fboHeight = qMax(minimumFBOSize.height(), m_size.height());
+ fboWidth = qMax(minimumFBOSize.width(), m_textureSize.width());
+ fboHeight = qMax(minimumFBOSize.height(), m_textureSize.height());
}
m_fboSize = QSize(fboWidth, fboHeight);
@@ -331,6 +348,15 @@ void QSGDefaultPainterNode::setSize(const QSize &size)
return;
m_size = size;
+ m_dirtyGeometry = true;
+}
+
+void QSGDefaultPainterNode::setTextureSize(const QSize &size)
+{
+ if (size == m_textureSize)
+ return;
+
+ m_textureSize = size;
updateFBOSize();
if (m_fbo)
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
index 62daa54432..115ddc66f2 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
@@ -94,6 +94,9 @@ public:
void setFastFBOResizing(bool dynamic);
bool fastFBOResizing() const { return m_fastFBOResizing; }
+ void setTextureSize(const QSize &textureSize);
+ QSize textureSize() const { return m_textureSize; }
+
QImage toImage() const;
void update();
@@ -126,21 +129,25 @@ private:
QSize m_size;
QSize m_fboSize;
- bool m_dirtyContents;
+ QSize m_textureSize;
QRect m_dirtyRect;
- bool m_opaquePainting;
- bool m_linear_filtering;
- bool m_mipmapping;
- bool m_smoothPainting;
- bool m_extensionsChecked;
- bool m_multisamplingSupported;
- bool m_fastFBOResizing;
QColor m_fillColor;
+#if QT_VERSION >= 0x060000
+#warning "Remove m_contentsScale and assume 1 everywhere"
+#endif
qreal m_contentsScale;
- bool m_dirtyGeometry;
- bool m_dirtyRenderTarget;
- bool m_dirtyTexture;
+ bool m_dirtyContents : 1;
+ bool m_opaquePainting : 1;
+ bool m_linear_filtering : 1;
+ bool m_mipmapping : 1;
+ bool m_smoothPainting : 1;
+ bool m_extensionsChecked : 1;
+ bool m_multisamplingSupported : 1;
+ bool m_fastFBOResizing : 1;
+ bool m_dirtyGeometry : 1;
+ bool m_dirtyRenderTarget : 1;
+ bool m_dirtyTexture : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index 5d492a4e75..ff851dac30 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -99,7 +99,9 @@ QImage QQuickTextureFactory::image() const
}
/*!
- Returns a QQuickTextureFactory holding given the image.
+ Returns a QQuickTextureFactory holding the given image.
+
+ This is typically used as a helper in QQuickImageResponse::textureFactory.
\since 5.6
*/
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 58d78a5d84..bda341412b 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -451,7 +451,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
QQmlBinding *newBinding = 0;
if (e.id != QQmlBinding::Invalid) {
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::QmlBindingWrapper::createQmlCallableForFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
newBinding = new QQmlBinding(function, object(), context);
}
// QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this)) : 0;
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 70c9309ab0..47bcabc115 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -206,6 +206,11 @@ void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec
void QQuickWidgetPrivate::render(bool needsSync)
{
+ // createFramebufferObject() bails out when the size is empty. In this case
+ // we cannot render either.
+ if (!fbo)
+ return;
+
if (!context->makeCurrent(offscreenSurface)) {
qWarning("QQuickWidget: Cannot render due to failing makeCurrent()");
return;
diff --git a/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml b/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml
new file mode 100644
index 0000000000..fa8d93d355
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ readonly property string name: "John"
+
+ Binding {
+ target: root
+ property: "name"
+ value: "Doe"
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/unknownProperty.qml b/tests/auto/qml/qqmlbinding/data/unknownProperty.qml
new file mode 100644
index 0000000000..36157bb4e7
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/unknownProperty.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ Binding {
+ target: root
+ property: "unknown"
+ value: 42
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 2d267cc668..3e49f3b3c4 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -50,6 +50,8 @@ private slots:
void restoreBindingWithLoop();
void restoreBindingWithoutCrash();
void deletedObject();
+ void warningOnUnknownProperty();
+ void warningOnReadOnlyProperty();
private:
QQmlEngine engine;
@@ -224,6 +226,38 @@ void tst_qqmlbinding::deletedObject()
delete rect;
}
+void tst_qqmlbinding::warningOnUnknownProperty()
+{
+ QQmlTestMessageHandler messageHandler;
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("unknownProperty.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+ delete item;
+
+ QCOMPARE(messageHandler.messages().count(), 1);
+
+ const QString expectedMessage = c.url().toString() + QLatin1String(":6:5: QML Binding: Property 'unknown' does not exist on Item.");
+ QCOMPARE(messageHandler.messages().first(), expectedMessage);
+}
+
+void tst_qqmlbinding::warningOnReadOnlyProperty()
+{
+ QQmlTestMessageHandler messageHandler;
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("readonlyProperty.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+ delete item;
+
+ QCOMPARE(messageHandler.messages().count(), 1);
+
+ const QString expectedMessage = c.url().toString() + QLatin1String(":8:5: QML Binding: Property 'name' on Item is read-only.");
+ QCOMPARE(messageHandler.messages().first(), expectedMessage);
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js
new file mode 100644
index 0000000000..385d7f9e97
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js
@@ -0,0 +1,21 @@
+var obj = {}
+obj[5289] = 0
+obj[5290] = 0
+obj[5288] = 0
+obj[5287] = 0
+delete obj[5288]
+
+var a = Object.getOwnPropertyNames(obj)
+var test1 = a.every(function(key) {
+ return obj.hasOwnProperty(key)
+})
+
+obj = {}
+obj[8187] = 0
+obj[8188] = 0
+delete obj[8187]
+
+var b = Object.getOwnPropertyNames(obj)
+var test2 = b.every(function(key) {
+ return obj.hasOwnProperty(key)
+})
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml
new file mode 100644
index 0000000000..2d2375de3e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml
@@ -0,0 +1,7 @@
+import "qtbug_46022.js" as Test
+import QtQuick 2.0
+
+QtObject {
+ property bool test1: Test.test1
+ property bool test2: Test.test2
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index a1038b0f52..e186c364c3 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -326,6 +326,7 @@ private slots:
void readUnregisteredQObjectProperty();
void writeUnregisteredQObjectProperty();
void switchExpression();
+ void qtbug_46022();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7876,6 +7877,16 @@ void tst_qqmlecmascript::switchExpression()
QCOMPARE(v.toBool(), true);
}
+void tst_qqmlecmascript::qtbug_46022()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_46022.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test1").toBool(), true);
+ QCOMPARE(obj->property("test2").toBool(), true);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml
new file mode 100644
index 0000000000..6a14e72a31
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml
@@ -0,0 +1,4 @@
+import Test 1.0
+
+MyCompositeBaseType {
+}
diff --git a/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml
new file mode 100644
index 0000000000..5f8c11e5f6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+RegisteredCompositeTypeWithEnum {
+ property int enumValue0: RegisteredCompositeTypeWithEnum.EnumValue0
+ property int enumValue42: RegisteredCompositeTypeWithEnum.EnumValue42
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 6fc4bae438..95a98788c3 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -91,6 +91,8 @@ void registerTypes()
qmlRegisterCustomExtendedType<SimpleObjectWithCustomParser, SimpleObjectExtension>("Test", 1, 0, "SimpleExtendedObjectWithCustomParser", new SimpleObjectCustomParser);
qmlRegisterType<RootObjectInCreationTester>("Test", 1, 0, "RootObjectInCreationTester");
+
+ qmlRegisterType<MyCompositeBaseType>("Test", 1, 0, "MyCompositeBaseType");
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -121,7 +123,7 @@ void CustomBinding::componentComplete()
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::QmlBindingWrapper::createQmlCallableForFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
QQmlProperty property(m_target, name, qmlContext(this));
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index b8792a892f..985acc2539 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1079,9 +1079,19 @@ class MyEnumDerivedClass : public MyEnum2Class
Q_OBJECT
};
+class MyCompositeBaseType : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(CompositeEnum)
+
+public:
+ enum CompositeEnum { EnumValue0, EnumValue42 = 42 };
+};
+
Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
Q_DECLARE_METATYPE(Qt::TextFormat)
+Q_DECLARE_METATYPE(MyCompositeBaseType::CompositeEnum)
QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered)
QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered)
@@ -1089,6 +1099,7 @@ QML_DECLARE_TYPE(MyRevisionedClass)
QML_DECLARE_TYPE(MyRevisionedSubclass)
QML_DECLARE_TYPE(MySubclass)
QML_DECLARE_TYPE(MyReceiversTestObject)
+QML_DECLARE_TYPE(MyCompositeBaseType)
class CustomBinding : public QObject, public QQmlParserStatus
{
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 7893114500..6b6d52ca34 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -159,6 +159,7 @@ private slots:
void readonlyObjectProperties();
void receivers();
void registeredCompositeType();
+ void registeredCompositeTypeWithEnum();
void implicitImportsLast();
void basicRemote_data();
@@ -3172,6 +3173,7 @@ void tst_qqmllanguage::initTestCase()
qmlRegisterType(testFileUrl("CompositeType.qml"), "Test", 1, 0, "RegisteredCompositeType");
qmlRegisterType(testFileUrl("CompositeType.DoesNotExist.qml"), "Test", 1, 0, "RegisteredCompositeType2");
qmlRegisterType(testFileUrl("invalidRoot.1.qml"), "Test", 1, 0, "RegisteredCompositeType3");
+ qmlRegisterType(testFileUrl("CompositeTypeWithEnum.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithEnum");
// Registering the TestType class in other modules should have no adverse effects
qmlRegisterType<TestType>("org.qtproject.TestPre", 1, 0, "Test");
@@ -3348,6 +3350,21 @@ void tst_qqmllanguage::registeredCompositeType()
delete o;
}
+// QTBUG-43582
+void tst_qqmllanguage::registeredCompositeTypeWithEnum()
+{
+ QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeWithEnum.qml"));
+
+ VERIFY_ERRORS(0);
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->property("enumValue0").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue0));
+ QCOMPARE(o->property("enumValue42").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue42));
+
+ delete o;
+}
+
// QTBUG-18268
void tst_qqmllanguage::remoteLoadCrash()
{
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 5c252013ea..519ee7ac26 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -125,6 +125,7 @@ private slots:
void datetime();
void datetime_data();
void about_to_be_signals();
+ void modify_through_delegate();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -1427,6 +1428,36 @@ void tst_qqmllistmodel::about_to_be_signals()
QCOMPARE(tester.rowsRemovedCount, 0);
}
+void tst_qqmllistmodel::modify_through_delegate()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ " ListModel {\n"
+ " id: testModel\n"
+ " objectName: \"testModel\"\n"
+ " ListElement { name: \"Joe\"; age: 22 }\n"
+ " ListElement { name: \"Doe\"; age: 33 }\n"
+ " }\n"
+ " ListView {\n"
+ " model: testModel\n"
+ " delegate: Item {\n"
+ " Component.onCompleted: model.age = 18;\n"
+ " }\n"
+ " }\n"
+ "}\n", QUrl());
+
+ QObject *scene = component.create();
+ QQmlListModel *model = scene->findChild<QQmlListModel*>("testModel");
+
+ const QHash<int, QByteArray> roleNames = model->roleNames();
+
+ QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("age")).toInt(), 18);
+ QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("age")).toInt(), 18);
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml
new file mode 100644
index 0000000000..a0429e0cc8
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+QtObject {
+ property double a: 3.4
+ property string b: a
+
+ property double c: 0.035003945
+ property string d: c
+}
+
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index d6b1c86b88..6ada14ce79 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -147,6 +147,7 @@ private slots:
void registeredCompositeTypeProperty();
void deeplyNestedObject();
void readOnlyDynamicProperties();
+ void floatToStringPrecision();
void copy();
private:
@@ -2054,6 +2055,27 @@ void tst_qqmlproperty::readOnlyDynamicProperties()
delete obj;
}
+void tst_qqmlproperty::floatToStringPrecision()
+{
+ QQmlComponent comp(&engine, testFileUrl("floatToStringPrecision.qml"));
+ QObject *obj = comp.create();
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->property("a").toDouble(), 3.4);
+ QEXPECT_FAIL("", "QVariant's double-to-string conversion is worse than V4's.", Continue);
+ QCOMPARE(obj->property("a").toString(), QLatin1String("3.4"));
+ QCOMPARE(obj->property("b").toDouble(), 3.4);
+ QCOMPARE(obj->property("b").toString(), QLatin1String("3.4"));
+
+ QCOMPARE(obj->property("c").toDouble(), 0.035003945);
+ QEXPECT_FAIL("", "QVariant's double-to-string conversion is worse than V4's.", Continue);
+ QCOMPARE(obj->property("c").toString(), QLatin1String("0.035003945"));
+ QCOMPARE(obj->property("d").toDouble(), 0.035003945);
+ QCOMPARE(obj->property("d").toString(), QLatin1String("0.035003945"));
+
+ delete obj;
+}
+
void tst_qqmlproperty::initTestCase()
{
QQmlDataTest::initTestCase();
diff --git a/tests/auto/quick/qquicklistview/data/qtbug48044.qml b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
new file mode 100644
index 0000000000..d318643c1c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
@@ -0,0 +1,144 @@
+import QtQuick 2.0
+
+Item {
+ width: 200
+ height: 442
+
+ ListModel {
+ id: listModel
+ ListElement {
+ name: "h1"
+ txt: "Header 1"
+ header: true
+ collapsed: true
+ }
+ ListElement {
+ name: "h2"
+ txt: "Header 2"
+ header: true
+ collapsed: true
+ }
+ ListElement {
+ name: "h3"
+ txt: "Header 3"
+ header: true
+ collapsed: true
+ }
+
+ function indexFromName(name) {
+ for (var i = 0; i < count; i++)
+ if (get(i).name === name)
+ return i
+
+ console.warn("Did not find index for name " + name)
+ return -1
+ }
+ }
+
+ function populateModel(prefix, index, n) {
+ for (var k = 1; k <= n; k++) {
+ var name = prefix + k
+ var data = {
+ "collapsed": false,
+ "name": name,
+ "txt": name,
+ "header": false
+ }
+ listModel.insert(index + k, data)
+ }
+ }
+
+ function h2(open) {
+ var i = listModel.indexFromName("h2")
+ if (listModel.get(i).collapsed === !open)
+ return
+
+ listModel.setProperty(i, "collapsed", !open)
+
+ var n = 15
+ if (open) {
+ h3(false)
+ populateModel("c2_", listModel.indexFromName("h2"), n)
+ } else {
+ listModel.remove(i + 1, n)
+ }
+
+ }
+
+ function h3(open) {
+ var i = listModel.indexFromName("h3")
+ if (listModel.get(i).collapsed === !open)
+ return
+
+ listModel.setProperty(i, "collapsed", !open)
+
+ var n = 6
+ if (open) {
+ h2(false)
+ populateModel("c3_", listModel.indexFromName("h3"), n)
+ } else {
+ listModel.remove(i + 1, n)
+ }
+ }
+
+ ListView {
+ id: listView
+ width: parent.width
+ height: parent.height
+ cacheBuffer: 0
+ model: listModel
+
+ property bool transitionsDone: false
+ property int runningTransitions: 0
+ onRunningTransitionsChanged: {
+ if (runningTransitions === 0)
+ transitionsDone = true
+ }
+
+ displaced: Transition {
+ id: dispTrans
+ SequentialAnimation {
+ ScriptAction {
+ script: listView.runningTransitions++
+ }
+ NumberAnimation {
+ property: "y";
+ duration: 250
+ }
+ ScriptAction {
+ script: listView.runningTransitions--
+ }
+ }
+ }
+
+ delegate: Rectangle {
+ id: rect
+ color: header ? "yellow" : "cyan"
+ border.color: "black"
+ height: 50
+ width: parent.width
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 20
+ text: txt
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ listView.currentIndex = index
+ var i = listModel.indexFromName("h3")
+ if (i === -1)
+ return;
+ var isCollapsed = listModel.get(i).collapsed
+ if (name === "h2")
+ h2(isCollapsed)
+ else if (name === "h3")
+ h3(isCollapsed)
+ }
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 8e7f93849c..e02c053208 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -247,6 +247,8 @@ private slots:
void contentHeightWithDelayRemove();
void contentHeightWithDelayRemove_data();
+ void QTBUG_48044_currentItemNotVisibleAfterTransition();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -8231,6 +8233,41 @@ void tst_QQuickListView::contentHeightWithDelayRemove()
delete window;
}
+void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("qtbug48044.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ // Expand 2nd header
+ listview->setProperty("transitionsDone", QVariant(false));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, 75));
+ QTRY_VERIFY(listview->property("transitionsDone").toBool());
+
+ // Flick listview to the bottom
+ flick(window, QPoint(window->width() / 2, 400), QPoint(window->width() / 2, 0), 100);
+ QTRY_VERIFY(!listview->isMoving());
+
+ // Expand 3rd header
+ listview->setProperty("transitionsDone", QVariant(false));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() - 25));
+ QTRY_VERIFY(listview->property("transitionsDone").toBool());
+
+ // Check current item is what we expect
+ QCOMPARE(listview->currentIndex(), 2);
+ QQuickItem *currentItem = listview->currentItem();
+ QVERIFY(currentItem);
+ QVERIFY(currentItem->isVisible());
+
+ // This is the actual test
+ QQuickItemPrivate *currentPriv = QQuickItemPrivate::get(currentItem);
+ QVERIFY(!currentPriv->culled);
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquicktext/data/fontSizeMode.qml b/tests/auto/quick/qquicktext/data/fontSizeMode.qml
index 84f7ce8d50..48e7c7b6d0 100644
--- a/tests/auto/quick/qquicktext/data/fontSizeMode.qml
+++ b/tests/auto/quick/qquicktext/data/fontSizeMode.qml
@@ -13,10 +13,10 @@ Item {
id: myText
objectName: "myText"
width: 250
- height: 41
+ height: 35
minimumPointSize: 8
minimumPixelSize: 8
- font.pixelSize: 30
+ font.pixelSize: 25
font.family: "Helvetica"
}
}
diff --git a/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml b/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml
index 9c9318d3cc..45255691fb 100644
--- a/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml
+++ b/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml
@@ -1,7 +1,7 @@
import QtQuick 2.0
Rectangle {
- width: 200
+ width: 220
height: 100
Text {
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index c1f10f9788..6042c08891 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -913,7 +913,7 @@ void tst_qquicktext::hAlignImplicitWidth()
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
- const int windowWidth = 200;
+ const int windowWidth = 220;
const int textWidth = qCeil(text->implicitWidth());
QVERIFY2(textWidth < windowWidth, "System font too large.");
const int sectionWidth = textWidth / 3;
@@ -3756,8 +3756,8 @@ void tst_qquicktext::baselineOffset_data()
<< "<b>hello world</b>"
<< "<b>hello<br/>world</b>"
<< QByteArray("height: 200")
- << &expectedBaselineTop
- << &expectedBaselineBold;
+ << &expectedBaselineBold
+ << &expectedBaselineTop;
QTest::newRow("richText")
<< "<b>hello world</b>"
@@ -3852,8 +3852,8 @@ void tst_qquicktext::baselineOffset_data()
<< "<b>hello world</b>"
<< "<b>hello<br/>world</b>"
<< QByteArray("height: 200; topPadding: 10; bottomPadding: 20")
- << &expectedBaselineTop
- << &expectedBaselineBold;
+ << &expectedBaselineBold
+ << &expectedBaselineTop;
QTest::newRow("richText with padding")
<< "<b>hello world</b>"
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 5ec8fa2e83..eda3be5c1d 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -201,6 +201,7 @@ private slots:
void emptytags_QTBUG_22058();
void cursorRectangle_QTBUG_38947();
void textCached_QTBUG_41583();
+ void doubleSelect_QTBUG_38704();
void padding();
@@ -4044,7 +4045,7 @@ void tst_qquicktextedit::append_data()
<< QString("Hello")
<< standard.at(0) + QString("\nHello")
<< 18 << standard.at(0).length() + 6 << standard.at(0).length() + 6
- << false << true;
+ << true << true;
QTest::newRow("reversed selection kept intact")
<< standard.at(0) << QQuickTextEdit::PlainText
@@ -4126,11 +4127,8 @@ void tst_qquicktextedit::append()
if (selectionStart > selectionEnd)
qSwap(selectionStart, selectionEnd);
- QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
QCOMPARE(selectionSpy.count() > 0, selectionChanged);
QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
- QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
QCOMPARE(textSpy.count() > 0, text != expectedText);
QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
@@ -4213,7 +4211,7 @@ void tst_qquicktextedit::insert_data()
<< QString("Hello")
<< QString("Hello") + standard.at(0)
<< 19 << 24 << 24
- << false << true;
+ << true << true;
QTest::newRow("before reversed selection")
<< standard.at(0) << QQuickTextEdit::PlainText
@@ -4221,7 +4219,7 @@ void tst_qquicktextedit::insert_data()
<< QString("Hello")
<< QString("Hello") + standard.at(0)
<< 19 << 24 << 19
- << false << true;
+ << true << true;
QTest::newRow("after selection")
<< standard.at(0) << QQuickTextEdit::PlainText
@@ -4344,11 +4342,8 @@ void tst_qquicktextedit::insert()
if (selectionStart > selectionEnd)
qSwap(selectionStart, selectionEnd);
- QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
QCOMPARE(selectionSpy.count() > 0, selectionChanged);
QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
- QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
QCOMPARE(textSpy.count() > 0, text != expectedText);
QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
@@ -4458,7 +4453,7 @@ void tst_qquicktextedit::remove_data()
<< 0 << 5
<< standard.at(0).mid(5)
<< 9 << 14 << 14
- << false << true;
+ << true << true;
QTest::newRow("before reversed selection")
<< standard.at(0) << QQuickTextEdit::PlainText
@@ -4466,7 +4461,7 @@ void tst_qquicktextedit::remove_data()
<< 0 << 5
<< standard.at(0).mid(5)
<< 9 << 14 << 9
- << false << true;
+ << true << true;
QTest::newRow("after selection")
<< standard.at(0) << QQuickTextEdit::PlainText
@@ -4588,11 +4583,8 @@ void tst_qquicktextedit::remove()
QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
- QEXPECT_FAIL("from selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("from reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
QCOMPARE(selectionSpy.count() > 0, selectionChanged);
QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
- QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
QCOMPARE(textSpy.count() > 0, text != expectedText);
@@ -5374,6 +5366,26 @@ void tst_qquicktextedit::textCached_QTBUG_41583()
QVERIFY(!textedit->property("empty").toBool());
}
+void tst_qquicktextedit::doubleSelect_QTBUG_38704()
+{
+ QString componentStr = "import QtQuick 2.2\nTextEdit { text: \"TextEdit\" }";
+ QQmlComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
+
+ textEdit->select(0,1); //Select some text initially
+ QCOMPARE(selectionSpy.count(), 1);
+ textEdit->select(0,1); //No change to selection start/end
+ QCOMPARE(selectionSpy.count(), 1);
+ textEdit->select(0,2); //Change selection end
+ QCOMPARE(selectionSpy.count(), 2);
+ textEdit->select(1,2); //Change selection start
+ QCOMPARE(selectionSpy.count(), 3);
+}
+
void tst_qquicktextedit::padding()
{
QScopedPointer<QQuickView> window(new QQuickView);
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 079f73ae34..85123c6f92 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -3092,14 +3092,16 @@ void tst_qquicktextinput::cursorRectangle()
} else {
QCOMPARE(r.left(), input.width());
}
- QVERIFY(r.top() >= line.height() - 1);
+ // we can't be exact here, as the space character can have a different ascent/descent from the arabic chars
+ // this then leads to different line heights between the wrapped and non wrapped texts
+ QVERIFY(r.top() >= line.height() - 5);
COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(11), r);
for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.top() >= line.height() - 1);
+ QVERIFY(r.top() >= line.height() - 5);
COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r);
QCOMPARE(input.positionToRectangle(i), r);
}
diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp
index 7235246fc0..6c466293b6 100644
--- a/tests/auto/shared/testhttpserver.cpp
+++ b/tests/auto/shared/testhttpserver.cpp
@@ -81,15 +81,14 @@ The following request urls will then result in the appropriate action:
\endtable
*/
TestHTTPServer::TestHTTPServer()
-: m_state(AwaitingHeader)
+ : m_state(AwaitingHeader)
{
- QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
-
+ QObject::connect(&m_server, &QTcpServer::newConnection, this, &TestHTTPServer::newConnection);
}
bool TestHTTPServer::listen()
{
- return server.listen(QHostAddress::LocalHost, 0);
+ return m_server.listen(QHostAddress::LocalHost, 0);
}
QUrl TestHTTPServer::baseUrl() const
@@ -97,7 +96,7 @@ QUrl TestHTTPServer::baseUrl() const
QUrl url;
url.setScheme(QStringLiteral("http"));
url.setHost(QStringLiteral("127.0.0.1"));
- url.setPort(server.serverPort());
+ url.setPort(m_server.serverPort());
return url;
}
@@ -113,12 +112,12 @@ QString TestHTTPServer::urlString(const QString &documentPath) const
QString TestHTTPServer::errorString() const
{
- return server.errorString();
+ return m_server.errorString();
}
bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
{
- dirs.append(qMakePair(dir, mode));
+ m_directories.append(qMakePair(dir, mode));
return true;
}
@@ -128,17 +127,17 @@ bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
*/
void TestHTTPServer::addAlias(const QString &filename, const QString &alias)
{
- aliases.insert(filename, alias);
+ m_aliases.insert(filename, alias);
}
void TestHTTPServer::addRedirect(const QString &filename, const QString &redirectName)
{
- redirects.insert(filename, redirectName);
+ m_redirects.insert(filename, redirectName);
}
void TestHTTPServer::registerFileNameForContentSubstitution(const QString &fileName)
{
- contentSubstitutedFileNames.insert(fileName);
+ m_contentSubstitutedFileNames.insert(fileName);
}
bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body)
@@ -147,19 +146,23 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod
m_data.clear();
QFile expectFile(expect.toLocalFile());
- if (!expectFile.open(QIODevice::ReadOnly)) return false;
+ if (!expectFile.open(QIODevice::ReadOnly))
+ return false;
QFile replyFile(reply.toLocalFile());
- if (!replyFile.open(QIODevice::ReadOnly)) return false;
+ if (!replyFile.open(QIODevice::ReadOnly))
+ return false;
- bodyData = QByteArray();
+ m_bodyData = QByteArray();
if (body.isValid()) {
QFile bodyFile(body.toLocalFile());
- if (!bodyFile.open(QIODevice::ReadOnly)) return false;
- bodyData = bodyFile.readAll();
+ if (!bodyFile.open(QIODevice::ReadOnly))
+ return false;
+ m_bodyData = bodyFile.readAll();
}
- const QByteArray serverHostUrl = QByteArrayLiteral("127.0.0.1:") + QByteArray::number(server.serverPort());
+ const QByteArray serverHostUrl
+ = QByteArrayLiteral("127.0.0.1:")+ QByteArray::number(m_server.serverPort());
QByteArray line;
bool headers_done = false;
@@ -170,10 +173,10 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod
continue;
}
if (headers_done) {
- waitData.body.append(line);
+ m_waitData.body.append(line);
} else {
line.replace("{{ServerHostUrl}}", serverHostUrl);
- waitData.headers.append(line);
+ m_waitData.headers.append(line);
}
}
/*
@@ -181,20 +184,21 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod
waitData = waitData.left(waitData.count() - 1);
*/
- replyData = replyFile.readAll();
+ m_replyData = replyFile.readAll();
- if (!replyData.endsWith('\n'))
- replyData.append("\n");
- replyData.append("Content-length: " + QByteArray::number(bodyData.length()));
- replyData .append("\n\n");
+ if (!m_replyData.endsWith('\n'))
+ m_replyData.append('\n');
+ m_replyData.append("Content-length: ");
+ m_replyData.append(QByteArray::number(m_bodyData.length()));
+ m_replyData.append("\n\n");
- for (int ii = 0; ii < replyData.count(); ++ii) {
- if (replyData.at(ii) == '\n' && (!ii || replyData.at(ii - 1) != '\r')) {
- replyData.insert(ii, '\r');
+ for (int ii = 0; ii < m_replyData.count(); ++ii) {
+ if (m_replyData.at(ii) == '\n' && (!ii || m_replyData.at(ii - 1) != '\r')) {
+ m_replyData.insert(ii, '\r');
++ii;
}
}
- replyData.append(bodyData);
+ m_replyData.append(m_bodyData);
return true;
}
@@ -206,25 +210,27 @@ bool TestHTTPServer::hasFailed() const
void TestHTTPServer::newConnection()
{
- QTcpSocket *socket = server.nextPendingConnection();
- if (!socket) return;
+ QTcpSocket *socket = m_server.nextPendingConnection();
+ if (!socket)
+ return;
- if (!dirs.isEmpty())
- dataCache.insert(socket, QByteArray());
+ if (!m_directories.isEmpty())
+ m_dataCache.insert(socket, QByteArray());
- QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
- QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ QObject::connect(socket, &QAbstractSocket::disconnected, this, &TestHTTPServer::disconnected);
+ QObject::connect(socket, &QIODevice::readyRead, this, &TestHTTPServer::readyRead);
}
void TestHTTPServer::disconnected()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
- if (!socket) return;
+ if (!socket)
+ return;
- dataCache.remove(socket);
- for (int ii = 0; ii < toSend.count(); ++ii) {
- if (toSend.at(ii).first == socket) {
- toSend.removeAt(ii);
+ m_dataCache.remove(socket);
+ for (int ii = 0; ii < m_toSend.count(); ++ii) {
+ if (m_toSend.at(ii).first == socket) {
+ m_toSend.removeAt(ii);
--ii;
}
}
@@ -235,14 +241,15 @@ void TestHTTPServer::disconnected()
void TestHTTPServer::readyRead()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
- if (!socket || socket->state() == QTcpSocket::ClosingState) return;
+ if (!socket || socket->state() == QTcpSocket::ClosingState)
+ return;
- if (!dirs.isEmpty()) {
+ if (!m_directories.isEmpty()) {
serveGET(socket, socket->readAll());
return;
}
- if (m_state == Failed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) {
+ if (m_state == Failed || (m_waitData.body.isEmpty() && m_waitData.headers.count() == 0)) {
qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll();
return;
}
@@ -256,8 +263,9 @@ void TestHTTPServer::readyRead()
m_data += socket->readAll();
break;
} else {
- if (!waitData.headers.contains(line)) {
- qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers;
+ if (!m_waitData.headers.contains(line)) {
+ qWarning() << "TestHTTPServer: Unexpected header:" << line
+ << "\nExpected headers: " << m_waitData.headers;
m_state = Failed;
socket->disconnectFromHost();
return;
@@ -268,34 +276,38 @@ void TestHTTPServer::readyRead()
m_data += socket->readAll();
}
- if (!m_data.isEmpty() || waitData.body.isEmpty()) {
- if (waitData.body != m_data) {
- qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << waitData.body;
+ if (!m_data.isEmpty() || m_waitData.body.isEmpty()) {
+ if (m_waitData.body != m_data) {
+ qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << m_waitData.body;
m_state = Failed;
} else {
- socket->write(replyData);
+ socket->write(m_replyData);
}
socket->disconnectFromHost();
}
}
-bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName)
+bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileNameIn)
{
- if (redirects.contains(fileName)) {
- QByteArray response = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + redirects[fileName].toUtf8() + "\r\n\r\n";
+ const QString fileName = QLatin1String(fileNameIn);
+ if (m_redirects.contains(fileName)) {
+ const QByteArray response
+ = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: "
+ + m_redirects.value(fileName).toUtf8() + "\r\n\r\n";
socket->write(response);
return true;
}
- for (int ii = 0; ii < dirs.count(); ++ii) {
- QString dir = dirs.at(ii).first;
- Mode mode = dirs.at(ii).second;
+ for (int ii = 0; ii < m_directories.count(); ++ii) {
+ const QString &dir = m_directories.at(ii).first;
+ const Mode mode = m_directories.at(ii).second;
- QString dirFile = dir + QLatin1String("/") + QLatin1String(fileName);
+ QString dirFile = dir + QLatin1Char('/') + fileName;
if (!QFile::exists(dirFile)) {
- if (aliases.contains(fileName))
- dirFile = dir + QLatin1String("/") + aliases.value(fileName);
+ const QHash<QString, QString>::const_iterator it = m_aliases.constFind(fileName);
+ if (it != m_aliases.constEnd())
+ dirFile = dir + QLatin1Char('/') + it.value();
}
QFile file(dirFile);
@@ -305,18 +317,18 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName)
return true;
QByteArray data = file.readAll();
- if (contentSubstitutedFileNames.contains("/" + fileName)) {
+ if (m_contentSubstitutedFileNames.contains(QLatin1Char('/') + fileName))
data.replace(QByteArrayLiteral("{{ServerBaseUrl}}"), baseUrl().toString().toUtf8());
- }
- QByteArray response = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: ";
+ QByteArray response
+ = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: ";
response += QByteArray::number(data.count());
response += "\r\n\r\n";
response += data;
if (mode == Delay) {
- toSend.append(qMakePair(socket, response));
- QTimer::singleShot(500, this, SLOT(sendOne()));
+ m_toSend.append(qMakePair(socket, response));
+ QTimer::singleShot(500, this, &TestHTTPServer::sendOne);
return false;
} else {
socket->write(response);
@@ -325,9 +337,7 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName)
}
}
-
- QByteArray response = "HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n";
- socket->write(response);
+ socket->write("HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n");
return true;
}
@@ -339,39 +349,31 @@ void TestHTTPServer::sendDelayedItem()
void TestHTTPServer::sendOne()
{
- if (!toSend.isEmpty()) {
- toSend.first().first->write(toSend.first().second);
- toSend.first().first->close();
- toSend.removeFirst();
+ if (!m_toSend.isEmpty()) {
+ m_toSend.first().first->write(m_toSend.first().second);
+ m_toSend.first().first->close();
+ m_toSend.removeFirst();
}
}
void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data)
{
- if (!dataCache.contains(socket))
+ const QHash<QTcpSocket *, QByteArray>::iterator it = m_dataCache.find(socket);
+ if (it == m_dataCache.end())
return;
- QByteArray total = dataCache[socket] + data;
- dataCache[socket] = total;
+ QByteArray &total = it.value();
+ total.append(data);
if (total.contains("\n\r\n")) {
-
bool close = true;
-
if (total.startsWith("GET /")) {
-
- int space = total.indexOf(' ', 4);
- if (space != -1) {
-
- QByteArray req = total.mid(5, space - 5);
- close = reply(socket, req);
-
- }
+ const int space = total.indexOf(' ', 4);
+ if (space != -1)
+ close = reply(socket, total.mid(5, space - 5));
}
- dataCache.remove(socket);
-
+ m_dataCache.erase(it);
if (close)
socket->disconnectFromHost();
}
}
-
diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h
index 0c0e799d8e..0fc8e4a79c 100644
--- a/tests/auto/shared/testhttpserver.h
+++ b/tests/auto/shared/testhttpserver.h
@@ -34,7 +34,6 @@
#ifndef TESTHTTPSERVER_H
#define TESTHTTPSERVER_H
-#include <QObject>
#include <QTcpServer>
#include <QUrl>
#include <QPair>
@@ -81,24 +80,24 @@ private:
void serveGET(QTcpSocket *, const QByteArray &);
bool reply(QTcpSocket *, const QByteArray &);
- QList<QPair<QString, Mode> > dirs;
- QHash<QTcpSocket *, QByteArray> dataCache;
- QList<QPair<QTcpSocket *, QByteArray> > toSend;
- QSet<QString> contentSubstitutedFileNames;
+ QList<QPair<QString, Mode> > m_directories;
+ QHash<QTcpSocket *, QByteArray> m_dataCache;
+ QList<QPair<QTcpSocket *, QByteArray> > m_toSend;
+ QSet<QString> m_contentSubstitutedFileNames;
struct WaitData {
QList <QByteArray>headers;
QByteArray body;
- } waitData;
- QByteArray replyData;
- QByteArray bodyData;
+ } m_waitData;
+ QByteArray m_replyData;
+ QByteArray m_bodyData;
QByteArray m_data;
State m_state;
- QHash<QString,QString> aliases;
- QHash<QString,QString> redirects;
+ QHash<QString, QString> m_aliases;
+ QHash<QString, QString> m_redirects;
- QTcpServer server;
+ QTcpServer m_server;
};
#endif // TESTHTTPSERVER_H
diff --git a/tests/manual/v4/crypto.js b/tests/manual/v4/crypto.js
index cd48bdb019..7c24b08439 100644
--- a/tests/manual/v4/crypto.js
+++ b/tests/manual/v4/crypto.js
@@ -1710,3 +1710,4 @@ if (typeof(print) === "undefined")
print = console.log;
print("done in", new Date - d1)
+gc()
diff --git a/tests/manual/v4/typedarrays.js b/tests/manual/v4/typedarrays.js
index d52fd6bab0..8cf2b8c75a 100644
--- a/tests/manual/v4/typedarrays.js
+++ b/tests/manual/v4/typedarrays.js
@@ -51,11 +51,13 @@ function assertTrue(b) {
throw "assertTrue failed:" + b
}
-function assertEquals(a, b) {
+function assertEquals(a, b, delta) {
if (isNaN(a) && isNaN(b))
return
- if (a !== b)
+ if (!delta && a !== b)
throw "assertEquals failed:" + a + "!==" + b
+ else if (Math.abs(a - b) > delta)
+ throw "assertEquals failed: Math.abs(" + a + " - " + b + ") > " + delta
}
function assertArrayEquals(a, b)
@@ -700,9 +702,36 @@ function TestDataViewPropertyTypeChecks() {
CheckProperty("byteLength");
}
-
TestDataViewPropertyTypeChecks();
+function TestDataGetterSetters() {
+ var a = new DataView(new ArrayBuffer(16));
+ function TestGetterSetter(size, name, value0, value1, delta1, delta2) {
+ var getter = 'get' + name;
+ var setter = 'set' + name;
+ a[setter](0, value0);
+ a[setter](size, value1);
+ assertEquals(value0, a[getter](0), delta1);
+ assertEquals(value1, a[getter](size), delta2);
+ }
+
+ TestGetterSetter(1, 'Int8', 111, -100);
+ TestGetterSetter(2, 'Int16', 31111, -30000);
+ TestGetterSetter(4, 'Int32', 2111111111, -2000000000);
+ TestGetterSetter(1, 'Uint8', 111, 200);
+ TestGetterSetter(2, 'Uint16', 31111, 60000);
+ TestGetterSetter(4, 'Uint32', 2111111111, 4000000000);
+ TestGetterSetter(4, 'Float32', Math.pow(10, 38), Math.pow(10, -38), Math.pow(10, 31), Math.pow(10, -45));
+ TestGetterSetter(8, 'Float64', Math.pow(10, 308), Math.pow(10, -293), Math.pow(10, 293), Math.pow(10, -308));
+
+ // Backword compatibility
+ TestGetterSetter(1, 'UInt8', 111, 200);
+ TestGetterSetter(2, 'UInt16', 31111, 60000);
+ TestGetterSetter(4, 'UInt32', 2111111111, 4000000000);
+}
+
+TestDataGetterSetters();
+
// General tests for properties
// Test property attribute [[Enumerable]]
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 90d2a940a3..0f16c62320 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -332,6 +332,7 @@ void printUsage()
printf("\t-desktop.......................Force use of desktop GL (AA_UseDesktopOpenGL)\n");
printf("\t-gles..........................Force use of GLES (AA_UseOpenGLES)\n");
printf("\t-software......................Force use of software rendering (AA_UseOpenGLES)\n");
+ printf("\t-no-scaling....................Disable High DPI scaling (AA_NoHighDpiScaling)\n");
printf("\tDebugging options:\n");
printf("\t-verbose ..................... Print information about what qml is doing, like specific file urls being loaded.\n");
printf("\t-translation [file] .......... Load the given file as the translations file.\n");
@@ -503,6 +504,8 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
} else if (arg == QLatin1String("-desktop")) {
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+ } else if (arg == QLatin1String("-no-scaling")) {
+ QCoreApplication::setAttribute(Qt::AA_NoHighDpiScaling);
} else {
files << arg;
}
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index 53e520cd1f..132817ff8c 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -188,9 +188,9 @@ int main(int argc, char *argv[])
QV4::Scope scope(&vm);
QV4::ScopedContext ctx(scope, vm.rootContext());
- QV4::ScopedObject print(scope, vm.memoryManager->alloc<builtins::Print>(ctx));
+ QV4::ScopedObject print(scope, vm.memoryManager->allocObject<builtins::Print>(vm.rootContext()));
vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("print"))).getPointer(), print);
- QV4::ScopedObject gc(scope, vm.memoryManager->alloc<builtins::GC>(ctx));
+ QV4::ScopedObject gc(scope, vm.memoryManager->allocObject<builtins::GC>(ctx));
vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("gc"))).getPointer(), gc);
foreach (const QString &fn, args) {
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 911328c12a..0238a4aaae 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -1157,7 +1157,7 @@ int main(int argc, char *argv[])
"//\n"
"// This file was auto-generated by:\n"
"// '%1 %2'\n"
- "\n").arg(QFileInfo(args.at(0)).fileName()).arg(QStringList(args.mid(1)).join(QLatin1String(" "))));
+ "\n").arg(QFileInfo(args.at(0)).baseName(), args.mid(1).join(QLatin1Char(' '))));
qml.writeStartObject("Module");
QStringList quotedDependencies;
foreach (const QString &dep, dependencies)
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index fe01b92244..14845ed433 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -156,7 +156,7 @@ struct Options
applicationAttributes.append(Qt::AA_ShareOpenGLContexts);
}
- QUrl file;
+ QUrl url;
bool originalQml;
bool originalQmlRaster;
bool maximized;
@@ -252,12 +252,10 @@ static bool checkVersion(const QUrl &url)
if (!qgetenv("QMLSCENE_IMPORT_NAME").isEmpty())
fprintf(stderr, "QMLSCENE_IMPORT_NAME is no longer supported.\n");
- QString fileName = url.toLocalFile();
- if (fileName.isEmpty()) {
- fprintf(stderr, "qmlscene: filename required.\n");
- return false;
- }
+ if (!url.isLocalFile())
+ return true;
+ const QString fileName = url.toLocalFile();
QFile f(fileName);
if (!f.open(QFile::ReadOnly | QFile::Text)) {
fprintf(stderr, "qmlscene: failed to check version of file '%s', could not open...\n",
@@ -300,7 +298,7 @@ static void displayFileDialog(Options *options)
QString fileName = QFileDialog::getOpenFileName(0, "Open QML file", QString(), "QML Files (*.qml)");
if (!fileName.isEmpty()) {
QFileInfo fi(fileName);
- options->file = QUrl::fromLocalFile(fi.canonicalFilePath());
+ options->url = QUrl::fromLocalFile(fi.canonicalFilePath());
}
#else
Q_UNUSED(options);
@@ -358,6 +356,7 @@ static void usage()
puts(" --desktop..........................Force use of desktop GL (AA_UseDesktopOpenGL)");
puts(" --gles.............................Force use of GLES (AA_UseOpenGLES)");
puts(" --software.........................Force use of software rendering (AA_UseOpenGLES)");
+ puts(" --no-scaling.......................Disable High DPI scaling (AA_NoHighDpiScaling)");
puts(" --verbose..........................Print version and graphical diagnostics for the run-time");
puts(" -I <path> ........................ Add <path> to the list of import paths");
puts(" -P <path> ........................ Add <path> to the list of plugin paths");
@@ -416,6 +415,24 @@ static void setWindowTitle(bool verbose, const QObject *topLevel, QWindow *windo
window->setTitle(newTitle);
}
+static QUrl parseUrlArgument(const char *arg)
+{
+ const QUrl url = QUrl::fromUserInput(QFile::decodeName(arg), QDir::currentPath(), QUrl::AssumeLocalFile);
+ if (!url.isValid()) {
+ fprintf(stderr, "Invalid URL: \"%s\"\n", arg);
+ return QUrl();
+ }
+ if (url.isLocalFile()) {
+ const QFileInfo fi(url.toLocalFile());
+ if (!fi.exists()) {
+ fprintf(stderr, "\"%s\" does not exist.\n",
+ qPrintable(QDir::toNativeSeparators(fi.absoluteFilePath())));
+ return QUrl();
+ }
+ }
+ return url;
+}
+
int main(int argc, char ** argv)
{
Options options;
@@ -423,8 +440,8 @@ int main(int argc, char ** argv)
QStringList imports;
QStringList pluginPaths;
for (int i = 1; i < argc; ++i) {
- if (*argv[i] != '-' && QFileInfo(QFile::decodeName(argv[i])).exists()) {
- options.file = QUrl::fromLocalFile(argv[i]);
+ if (*argv[i] != '-') {
+ options.url = parseUrlArgument(argv[i]);
} else {
const QString lowerArgument = QString::fromLatin1(argv[i]).toLower();
if (lowerArgument == QLatin1String("--maximized"))
@@ -455,6 +472,8 @@ int main(int argc, char ** argv)
options.applicationAttributes.append(Qt::AA_UseSoftwareOpenGL);
else if (lowerArgument == QLatin1String("--desktop"))
options.applicationAttributes.append(Qt::AA_UseDesktopOpenGL);
+ else if (lowerArgument == QLatin1String("--no-scaling"))
+ options.applicationAttributes.append(Qt::AA_NoHighDpiScaling);
else if (lowerArgument == QLatin1String("--verbose"))
options.verbose = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < argc)
@@ -502,7 +521,7 @@ int main(int argc, char ** argv)
QUnifiedTimer::instance()->setSlowModeEnabled(options.slowAnimations);
- if (options.file.isEmpty())
+ if (options.url.isEmpty())
#if defined(QMLSCENE_BUNDLE)
displayOptionsDialog(&options);
#else
@@ -514,8 +533,8 @@ int main(int argc, char ** argv)
if (options.verbose)
puts(QLibraryInfo::build());
- if (!options.file.isEmpty()) {
- if (!options.versionDetection || checkVersion(options.file)) {
+ if (!options.url.isEmpty()) {
+ if (!options.versionDetection || checkVersion(options.url)) {
#ifndef QT_NO_TRANSLATION
QTranslator translator;
#endif
@@ -528,15 +547,17 @@ int main(int argc, char ** argv)
engine.addImportPath(imports.at(i));
for (int i = 0; i < pluginPaths.size(); ++i)
engine.addPluginPath(pluginPaths.at(i));
- if (options.file.isLocalFile()) {
- QFileInfo fi(options.file.toLocalFile());
+ if (options.url.isLocalFile()) {
+ QFileInfo fi(options.url.toLocalFile());
#ifndef QT_NO_TRANSLATION
loadTranslationFile(translator, fi.path());
#endif
loadDummyDataFiles(engine, fi.path());
}
QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
- component->loadUrl(options.file);
+ component->loadUrl(options.url);
+ while (component->isLoading())
+ QCoreApplication::processEvents();
if ( !component->isReady() ) {
fprintf(stderr, "%s\n", qPrintable(component->errorString()));
return -1;
@@ -560,7 +581,7 @@ int main(int argc, char ** argv)
qxView->setResizeMode(QQuickView::SizeViewToRootObject);
else
qxView->setResizeMode(QQuickView::SizeRootObjectToView);
- qxView->setContent(options.file, component, contentItem);
+ qxView->setContent(options.url, component, contentItem);
}
}