aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp28
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h5
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp18
-rw-r--r--src/qml/compiler/qv4codegen.cpp3
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compiler.cpp7
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h78
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp89
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h7
-rw-r--r--src/qml/compiler/qv4isel_p.cpp42
-rw-r--r--src/qml/compiler/qv4isel_p.h7
-rw-r--r--src/qml/compiler/qv4jsir.cpp18
-rw-r--r--src/qml/compiler/qv4jsir_p.h25
-rw-r--r--src/qml/compiler/qv4ssa.cpp6
-rw-r--r--src/qml/debugger/debugger.pri31
-rw-r--r--src/qml/debugger/qdebugmessageservice.cpp122
-rw-r--r--src/qml/debugger/qdebugmessageservice_p.h77
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice.cpp88
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice_p.h79
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice_p_p.h70
-rw-r--r--src/qml/debugger/qqmldebug.cpp120
-rw-r--r--src/qml/debugger/qqmldebug.h2
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp151
-rw-r--r--src/qml/debugger/qqmldebugconnector_p.h (renamed from src/qml/debugger/qqmlinspectorservice_p.h)67
-rw-r--r--src/qml/debugger/qqmldebugpluginmanager_p.h (renamed from src/qml/debugger/qqmlenginecontrolservice_p.h)75
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp787
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h104
-rw-r--r--src/qml/debugger/qqmldebugserverconnection_p.h76
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp252
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h42
-rw-r--r--src/qml/debugger/qqmldebugservicefactory_p.h (renamed from src/qml/debugger/qqmldebugservice_p_p.h)24
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces.cpp (renamed from src/qml/jsruntime/qv4qmlextensions_p.h)25
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h133
-rw-r--r--src/qml/debugger/qqmlenginecontrolservice.cpp137
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp820
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h132
-rw-r--r--src/qml/debugger/qqmlinspectorinterface_p.h74
-rw-r--r--src/qml/debugger/qqmlinspectorservice.cpp181
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp85
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h26
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp379
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h112
-rw-r--r--src/qml/debugger/qv4debugservice.cpp1265
-rw-r--r--src/qml/debugger/qv4debugservice_p.h83
-rw-r--r--src/qml/debugger/qv4profileradapter.cpp125
-rw-r--r--src/qml/debugger/qv4profileradapter_p.h78
-rw-r--r--src/qml/jit/qv4assembler.cpp20
-rw-r--r--src/qml/jit/qv4assembler_p.h36
-rw-r--r--src/qml/jit/qv4binop.cpp63
-rw-r--r--src/qml/jit/qv4isel_masm.cpp95
-rw-r--r--src/qml/jit/qv4isel_masm_p.h7
-rw-r--r--src/qml/jit/qv4regalloc.cpp42
-rw-r--r--src/qml/jit/qv4targetplatform_p.h65
-rw-r--r--src/qml/jsapi/qjsengine.cpp11
-rw-r--r--src/qml/jsapi/qjsvalue.cpp33
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp39
-rw-r--r--src/qml/jsapi/qjsvalueiterator_p.h10
-rw-r--r--src/qml/jsruntime/jsruntime.pri6
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp19
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h4
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp126
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h16
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp337
-rw-r--r--src/qml/jsruntime/qv4context_p.h50
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp15
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h6
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp174
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h23
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp588
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h112
-rw-r--r--src/qml/jsruntime/qv4engine.cpp599
-rw-r--r--src/qml/jsruntime/qv4engine_p.h304
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp73
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4function.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp149
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h59
-rw-r--r--src/qml/jsruntime/qv4global_p.h7
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp76
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h4
-rw-r--r--src/qml/jsruntime/qv4include.cpp12
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h2
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp152
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h52
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp69
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h20
-rw-r--r--src/qml/jsruntime/qv4managed.cpp6
-rw-r--r--src/qml/jsruntime/qv4managed_p.h121
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp3
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp149
-rw-r--r--src/qml/jsruntime/qv4object_p.h99
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp41
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h6
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp74
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h4
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp32
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h20
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp18
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h10
-rw-r--r--src/qml/jsruntime/qv4property_p.h13
-rw-r--r--src/qml/jsruntime/qv4qmlextensions.cpp43
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp223
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h30
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp25
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h3
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp190
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h34
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h105
-rw-r--r--src/qml/jsruntime/qv4script.cpp87
-rw-r--r--src/qml/jsruntime/qv4script_p.h24
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp32
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h5
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp22
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h2
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h12
-rw-r--r--src/qml/jsruntime/qv4string.cpp4
-rw-r--r--src/qml/jsruntime/qv4string_p.h14
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp88
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h20
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp33
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h8
-rw-r--r--src/qml/jsruntime/qv4value.cpp78
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h293
-rw-r--r--src/qml/jsruntime/qv4value_p.h441
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp61
-rw-r--r--src/qml/memory/memory.pri14
-rw-r--r--src/qml/memory/qv4heap_p.h129
-rw-r--r--src/qml/memory/qv4mm.cpp (renamed from src/qml/jsruntime/qv4mm.cpp)64
-rw-r--r--src/qml/memory/qv4mm_p.h (renamed from src/qml/jsruntime/qv4mm_p.h)10
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h22
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/ftw/ftw.pri2
-rw-r--r--src/qml/qml/ftw/qqmlpool.cpp89
-rw-r--r--src/qml/qml/ftw/qqmlpool_p.h270
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h25
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp27
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/qml.pri4
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp170
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h140
-rw-r--r--src/qml/qml/qqmlabstractexpression.cpp93
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h116
-rw-r--r--src/qml/qml/qqmlbinding.cpp434
-rw-r--r--src/qml/qml/qqmlbinding_p.h65
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp316
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h78
-rw-r--r--src/qml/qml/qqmlcomponent.cpp115
-rw-r--r--src/qml/qml/qqmlcomponent.h5
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-rw-r--r--src/qml/qml/qqmlcontext.cpp11
-rw-r--r--src/qml/qml/qqmlcontext.h1
-rw-r--r--src/qml/qml/qqmlcontext_p.h6
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp114
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h29
-rw-r--r--src/qml/qml/qqmldata_p.h17
-rw-r--r--src/qml/qml/qqmldirparser.cpp30
-rw-r--r--src/qml/qml/qqmlengine.cpp146
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlengine_p.h34
-rw-r--r--src/qml/qml/qqmlexpression.cpp34
-rw-r--r--src/qml/qml/qqmlexpression_p.h12
-rw-r--r--src/qml/qml/qqmlglobal.cpp4
-rw-r--r--src/qml/qml/qqmlimport.cpp29
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp120
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h99
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp14
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h8
-rw-r--r--src/qml/qml/qqmllocale.cpp32
-rw-r--r--src/qml/qml/qqmllocale_p.h10
-rw-r--r--src/qml/qml/qqmlmemoryprofiler.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp17
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlnotifier_p.h12
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp57
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp12
-rw-r--r--src/qml/qml/qqmlproperty.cpp456
-rw-r--r--src/qml/qml/qqmlproperty_p.h38
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp5
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp23
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp10
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp4
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp97
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h20
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp79
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp57
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlwatcher.cpp181
-rw-r--r--src/qml/qml/qqmlwatcher_p.h86
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp105
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp59
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h6
-rw-r--r--src/qml/qml/v8/qv4domerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv4sqlerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp23
-rw-r--r--src/qml/qml/v8/qv8engine_p.h16
-rw-r--r--src/qml/types/qqmlbind.cpp90
-rw-r--r--src/qml/types/qqmlconnections.cpp2
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp39
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h2
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h2
-rw-r--r--src/qml/types/qqmllistmodel.cpp36
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp1
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp204
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h15
-rw-r--r--src/qml/types/qquickworkerscript.cpp2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp6
229 files changed, 5486 insertions, 11601 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 63833504f1..4b1e3601dc 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -33,7 +33,7 @@
#include "qqmlirbuilder_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljslexer_p.h>
@@ -1456,10 +1456,8 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR
, _disableAcceleratedLookups(false)
, _contextObject(0)
, _scopeObject(0)
- , _contextObjectTemp(-1)
- , _scopeObjectTemp(-1)
+ , _qmlContextTemp(-1)
, _importedScriptsTemp(-1)
- , _idArrayTemp(-1)
{
_module = jsModule;
_module->setFileName(fileName);
@@ -1764,24 +1762,14 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver,
void JSCodeGen::beginFunctionBodyHook()
{
- _contextObjectTemp = _block->newTemp();
- _scopeObjectTemp = _block->newTemp();
+ _qmlContextTemp = _block->newTemp();
_importedScriptsTemp = _block->newTemp();
- _idArrayTemp = _block->newTemp();
#ifndef V4_BOOTSTRAP
- QV4::IR::Temp *temp = _block->TEMP(_contextObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _contextObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0));
-
- temp = _block->TEMP(_scopeObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _scopeObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0));
+ QV4::IR::Temp *temp = _block->TEMP(_qmlContextTemp);
+ move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context, 0, 0));
move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
- move(_block->TEMP(_idArrayTemp), _block->NAME(QV4::IR::Name::builtin_qml_id_array, 0, 0));
#endif
}
@@ -1807,7 +1795,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
_function->idObjectDependencies.insert(mapping.idIndex);
- QV4::IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(QV4::IR::SInt32Type, mapping.idIndex));
+ QV4::IR::Expr *s = _block->MEMBER(_block->TEMP(_qmlContextTemp), _function->newString(name), 0, QV4::IR::Member::MemberOfIdObjectsArray, mapping.idIndex);
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
_block->MOVE(result, s);
result = _block->TEMP(result->index);
@@ -1857,7 +1845,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
@@ -1870,7 +1858,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_contextObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 120de91321..5617912081 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -34,7 +34,6 @@
#define QQMLIRBUILDER_P_H
#include <private/qqmljsast_p.h>
-#include <private/qqmlpool_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compileddata_p.h>
@@ -496,10 +495,8 @@ private:
ObjectIdMapping _idObjects;
QQmlPropertyCache *_contextObject;
QQmlPropertyCache *_scopeObject;
- int _contextObjectTemp;
- int _scopeObjectTemp;
+ int _qmlContextTemp;
int _importedScriptsTemp;
- int _idArrayTemp;
};
} // namespace QmlIR
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 4e9817aa0d..307f945d20 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -104,11 +104,10 @@ bool QQmlTypeCompiler::compile()
}
if (ref->type->containsRevisionedAttributes()) {
- QQmlError cacheError;
ref->typePropertyCache = engine->cache(ref->type,
- resolvedType->minorVersion,
- cacheError);
+ resolvedType->minorVersion);
if (!ref->typePropertyCache) {
+ QQmlError cacheError;
cacheError.setColumn(resolvedType->location.column);
cacheError.setLine(resolvedType->location.line);
recordError(cacheError);
@@ -696,6 +695,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
const int paramCount = s->parameters->count;
QList<QByteArray> names;
+ names.reserve(paramCount);
QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
if (paramCount) {
@@ -1022,10 +1022,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
}
- QHash<QString, QStringList>::ConstIterator entry = customSignals.find(propertyName);
+ QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName);
if (entry == customSignals.constEnd() && propertyName.endsWith(QStringLiteral("Changed"))) {
QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed")));
- entry = customSignals.find(alternateName);
+ entry = customSignals.constFind(alternateName);
}
if (entry == customSignals.constEnd()) {
@@ -2017,7 +2017,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
- foreach (QQmlError error, parserErrors)
+ foreach (const QQmlError &error, parserErrors)
compiler->recordError(error);
return false;
}
@@ -2623,10 +2623,8 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move
}
if (QV4::IR::Name *n = move->source->asName()) {
- if (n->builtin == QV4::IR::Name::builtin_qml_id_array
- || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object
- || n->builtin == QV4::IR::Name::builtin_qml_context_object
- || n->builtin == QV4::IR::Name::builtin_qml_scope_object) {
+ if (n->builtin == QV4::IR::Name::builtin_qml_context
+ || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object) {
// these are free of side-effects
return;
}
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 9168889c8c..ea82d07e69 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -33,6 +33,7 @@
#include "qv4codegen_p.h"
#include "qv4util_p.h"
+#include "qv4engine_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
@@ -43,7 +44,7 @@
#include <QtCore/QStack>
#include <private/qqmljsast_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4context_p.h>
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 5d954eb4fc..20db5edaa3 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -33,7 +33,7 @@
#include "qv4compileddata_p.h"
#include "qv4jsir_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qv4engine_p.h>
#include <private/qv4function_p.h>
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 450889c275..ba4bde7a31 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -35,7 +35,7 @@
#include <qv4compileddata_p.h>
#include <qv4isel_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
@@ -44,8 +44,8 @@ QV4::Compiler::StringTableGenerator::StringTableGenerator()
int QV4::Compiler::StringTableGenerator::registerString(const QString &str)
{
- QHash<QString, int>::ConstIterator it = stringToId.find(str);
- if (it != stringToId.end())
+ QHash<QString, int>::ConstIterator it = stringToId.constFind(str);
+ if (it != stringToId.cend())
return *it;
stringToId.insert(str, strings.size());
strings.append(str);
@@ -169,6 +169,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg
// ### re-use existing class definitions.
QList<CompiledData::JSClassMember> members;
+ members.reserve(count);
IR::ExprList *it = args;
for (int i = 0; i < count; ++i, it = it->next) {
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 5c2ad45da2..6839c7f609 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -64,12 +64,19 @@ QT_BEGIN_NAMESPACE
F(SetLookup, setLookup) \
F(StoreQObjectProperty, storeQObjectProperty) \
F(LoadQObjectProperty, loadQObjectProperty) \
+ F(StoreScopeObjectProperty, storeScopeObjectProperty) \
+ F(StoreContextObjectProperty, storeContextObjectProperty) \
+ F(LoadScopeObjectProperty, loadScopeObjectProperty) \
+ F(LoadContextObjectProperty, loadContextObjectProperty) \
+ F(LoadIdObject, loadIdObject) \
F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \
F(LoadSingletonQObjectProperty, loadQObjectProperty) \
F(Push, push) \
F(CallValue, callValue) \
F(CallProperty, callProperty) \
F(CallPropertyLookup, callPropertyLookup) \
+ F(CallScopeObjectProperty, callScopeObjectProperty) \
+ F(CallContextObjectProperty, callContextObjectProperty) \
F(CallElement, callElement) \
F(CallActivationProperty, callActivationProperty) \
F(CallGlobalLookup, callGlobalLookup) \
@@ -125,10 +132,8 @@ QT_BEGIN_NAMESPACE
F(Sub, sub) \
F(BinopContext, binopContext) \
F(LoadThis, loadThis) \
- F(LoadQmlIdArray, loadQmlIdArray) \
+ F(LoadQmlContext, loadQmlContext) \
F(LoadQmlImportedScripts, loadQmlImportedScripts) \
- F(LoadQmlContextObject, loadQmlContextObject) \
- F(LoadQmlScopeObject, loadQmlScopeObject) \
F(LoadQmlSingleton, loadQmlSingleton)
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
@@ -293,6 +298,24 @@ union Instr
Param base;
Param result;
};
+ struct instr_loadScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadIdObject {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
struct instr_loadQObjectProperty {
MOTH_INSTR_HEADER
int propertyIndex;
@@ -318,6 +341,18 @@ union Instr
Param base;
Param source;
};
+ struct instr_storeScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
+ struct instr_storeContextObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
struct instr_storeQObjectProperty {
MOTH_INSTR_HEADER
Param base;
@@ -377,6 +412,22 @@ union Instr
Param base;
Param result;
};
+ struct instr_callScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
+ struct instr_callContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
struct instr_callElement {
MOTH_INSTR_HEADER
Param base;
@@ -684,7 +735,7 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlIdArray {
+ struct instr_loadQmlContext {
MOTH_INSTR_HEADER
Param result;
};
@@ -692,14 +743,6 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlContextObject {
- MOTH_INSTR_HEADER
- Param result;
- };
- struct instr_loadQmlScopeObject {
- MOTH_INSTR_HEADER
- Param result;
- };
struct instr_loadQmlSingleton {
MOTH_INSTR_HEADER
Param result;
@@ -725,15 +768,22 @@ union Instr
instr_storeElementLookup storeElementLookup;
instr_loadProperty loadProperty;
instr_getLookup getLookup;
+ instr_loadScopeObjectProperty loadScopeObjectProperty;
+ instr_loadContextObjectProperty loadContextObjectProperty;
+ instr_loadIdObject loadIdObject;
instr_loadQObjectProperty loadQObjectProperty;
instr_loadAttachedQObjectProperty loadAttachedQObjectProperty;
instr_storeProperty storeProperty;
instr_setLookup setLookup;
+ instr_storeScopeObjectProperty storeScopeObjectProperty;
+ instr_storeContextObjectProperty storeContextObjectProperty;
instr_storeQObjectProperty storeQObjectProperty;
instr_push push;
instr_callValue callValue;
instr_callProperty callProperty;
instr_callPropertyLookup callPropertyLookup;
+ instr_callScopeObjectProperty callScopeObjectProperty;
+ instr_callContextObjectProperty callContextObjectProperty;
instr_callElement callElement;
instr_callActivationProperty callActivationProperty;
instr_callGlobalLookup callGlobalLookup;
@@ -789,10 +839,8 @@ union Instr
instr_sub sub;
instr_binopContext binopContext;
instr_loadThis loadThis;
- instr_loadQmlIdArray loadQmlIdArray;
+ instr_loadQmlContext loadQmlContext;
instr_loadQmlImportedScripts loadQmlImportedScripts;
- instr_loadQmlContextObject loadQmlContextObject;
- instr_loadQmlScopeObject loadQmlScopeObject;
instr_loadQmlSingleton loadQmlSingleton;
static int size(Type type);
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index eb78a0c054..ede1e6938f 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -447,7 +447,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backend
foreach (IR::Function *irFunction, irModule->functions)
compilationUnit->codeRefs[i++] = codeRefs[irFunction];
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -461,6 +461,29 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex
addInstruction(call);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::CallScopeObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::CallContextObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -565,9 +588,9 @@ void InstructionSelection::loadThisObject(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *e)
+void InstructionSelection::loadQmlContext(IR::Expr *e)
{
- Instruction::LoadQmlIdArray load;
+ Instruction::LoadQmlContext load;
load.result = getResultParam(e);
addInstruction(load);
}
@@ -579,20 +602,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *e)
-{
- Instruction::LoadQmlContextObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *e)
-{
- Instruction::LoadQmlScopeObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e)
{
Instruction::LoadQmlSingleton load;
@@ -694,6 +703,25 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
addInstruction(store);
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::StoreScopeObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::StoreContextObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
Instruction::StoreQObjectProperty store;
@@ -703,6 +731,31 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
addInstruction(store);
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::LoadScopeObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::LoadContextObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfIdObjectsArray) {
+ Instruction::LoadIdObject load;
+ load.base = getParam(source);
+ load.index = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0) {
@@ -1444,7 +1497,7 @@ ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &in
void InstructionSelection::patchJumpAddresses()
{
typedef QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt;
- for (PatchIt i = _patches.begin(), ei = _patches.end(); i != ei; ++i) {
+ for (PatchIt i = _patches.cbegin(), ei = _patches.cend(); i != ei; ++i) {
Q_ASSERT(_addrs.contains(i.key()));
ptrdiff_t target = _addrs.value(i.key());
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 4ea0f1d07f..ac1eaba740 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -95,6 +95,7 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
@@ -102,10 +103,8 @@ protected:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
virtual void loadThisObject(IR::Expr *e);
- virtual void loadQmlIdArray(IR::Expr *e);
+ virtual void loadQmlContext(IR::Expr *e);
virtual void loadQmlImportedScripts(IR::Expr *e);
- virtual void loadQmlContextObject(IR::Expr *e);
- virtual void loadQmlScopeObject(IR::Expr *e);
virtual void loadQmlSingleton(const QString &name, IR::Expr *e);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *e);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -115,7 +114,9 @@ protected:
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 54b184b4eb..9d172b1223 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -36,7 +36,7 @@
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qqmlpropertycache_p.h>
#endif
@@ -91,12 +91,8 @@ void IRDecoder::visitMove(IR::Move *s)
if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
loadThisObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_id_array)
- loadQmlIdArray(s->target);
- else if (n->builtin == IR::Name::builtin_qml_context_object)
- loadQmlContextObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_scope_object)
- loadQmlScopeObject(s->target);
+ else if (n->builtin == IR::Name::builtin_qml_context)
+ loadQmlContext(s->target);
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
loadQmlImportedScripts(s->target);
else if (n->qmlSingleton)
@@ -140,8 +136,8 @@ void IRDecoder::visitMove(IR::Move *s)
#else
bool captureRequired = true;
- Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfEnum && m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject;
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
@@ -153,9 +149,16 @@ void IRDecoder::visitMove(IR::Move *s)
captureRequired = false;
}
}
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target);
+ return;
+ }
getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
+ } else if (m->kind == IR::Member::MemberOfIdObjectsArray) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target);
+ return;
} else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
getProperty(m->base, *m->name, s->target);
return;
@@ -174,6 +177,13 @@ void IRDecoder::visitMove(IR::Move *s)
callBuiltin(c, s->target);
return;
} else if (Member *member = c->base->asMember()) {
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, s->target);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, s->target);
return;
} else if (Subscript *ss = c->base->asSubscript()) {
@@ -192,11 +202,16 @@ void IRDecoder::visitMove(IR::Move *s)
if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
if (m->property && attachedPropertiesId == 0) {
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
#else
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex);
+ return;
+ }
setQObjectProperty(s->source, m->base, m->property->coreIndex);
#endif
return;
@@ -238,6 +253,13 @@ void IRDecoder::visitExp(IR::Exp *s)
callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) {
Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, 0);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, 0);
} else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 1e273df93e..2b8aa7eb33 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -129,6 +129,7 @@ public: // to implement by subclasses:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0;
virtual void convertType(IR::Expr *source, IR::Expr *target) = 0;
@@ -136,10 +137,8 @@ public: // to implement by subclasses:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
virtual void loadThisObject(IR::Expr *target) = 0;
- virtual void loadQmlIdArray(IR::Expr *target) = 0;
+ virtual void loadQmlContext(IR::Expr *target) = 0;
virtual void loadQmlImportedScripts(IR::Expr *target) = 0;
- virtual void loadQmlContextObject(IR::Expr *target) = 0;
- virtual void loadQmlScopeObject(IR::Expr *target) = 0;
virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0;
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0;
virtual void loadString(const QString &str, IR::Expr *target) = 0;
@@ -149,7 +148,9 @@ public: // to implement by subclasses:
virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0;
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0;
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0;
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0;
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0;
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0;
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5c9cc98ade..98b53c6b3b 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -341,14 +341,10 @@ const char *builtin_to_string(Name::Builtin b)
return "builtin_setup_argument_object";
case IR::Name::builtin_convert_this_to_object:
return "builtin_convert_this_to_object";
- case IR::Name::builtin_qml_id_array:
- return "builtin_qml_id_array";
+ case IR::Name::builtin_qml_context:
+ return "builtin_qml_context";
case IR::Name::builtin_qml_imported_scripts_object:
return "builtin_qml_imported_scripts_object";
- case IR::Name::builtin_qml_scope_object:
- return "builtin_qml_scope_object";
- case IR::Name::builtin_qml_context_object:
- return "builtin_qml_context_object";
}
return "builtin_(###FIXME)";
};
@@ -935,7 +931,7 @@ void CloneExpr::visitSubscript(Subscript *e)
void CloneExpr::visitMember(Member *e)
{
Expr *clonedBase = clone(e->base);
- cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->attachedPropertiesIdOrEnumValue);
+ cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->idIndex);
}
IRPrinter::IRPrinter(QTextStream *out)
@@ -1239,9 +1235,9 @@ void IRPrinter::visitSubscript(Subscript *e)
void IRPrinter::visitMember(Member *e)
{
- if (e->kind != Member::MemberOfEnum
- && e->attachedPropertiesIdOrEnumValue != 0 && !e->base->asTemp())
- *out << "[[attached property from " << e->attachedPropertiesIdOrEnumValue << "]]";
+ if (e->kind != Member::MemberOfEnum && e->kind != Member::MemberOfIdObjectsArray
+ && e->attachedPropertiesId != 0 && !e->base->asTemp())
+ *out << "[[attached property from " << e->attachedPropertiesId << "]]";
else
e->base->accept(this);
*out << '.' << *e->name;
@@ -1250,6 +1246,8 @@ void IRPrinter::visitMember(Member *e)
*out << " (meta-property " << e->property->coreIndex
<< " <" << QMetaType::typeName(e->property->propType)
<< ">)";
+ else if (e->kind == Member::MemberOfIdObjectsArray)
+ *out << "(id object " << e->idIndex << ")";
#endif
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 8daad97e8b..568ded5337 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -337,10 +337,8 @@ struct Name: Expr {
builtin_define_object_literal,
builtin_setup_argument_object,
builtin_convert_this_to_object,
- builtin_qml_id_array,
- builtin_qml_imported_scripts_object,
- builtin_qml_context_object,
- builtin_qml_scope_object
+ builtin_qml_context,
+ builtin_qml_imported_scripts_object
};
const QString *id;
@@ -558,13 +556,18 @@ struct Member: Expr {
MemberOfEnum,
MemberOfQmlScopeObject,
MemberOfQmlContextObject,
- MemberOfSingletonObject
+ MemberOfIdObjectsArray,
+ MemberOfSingletonObject,
};
Expr *base;
const QString *name;
QQmlPropertyData *property;
- int attachedPropertiesIdOrEnumValue; // depending on kind
+ union { // depending on kind
+ int attachedPropertiesId;
+ int enumValue;
+ int idIndex;
+ };
uchar freeOfSideEffects : 1;
// This is set for example for for QObject properties. All sorts of extra behavior
@@ -577,20 +580,20 @@ struct Member: Expr {
void setEnumValue(int value) {
kind = MemberOfEnum;
- attachedPropertiesIdOrEnumValue = value;
+ enumValue = value;
}
void setAttachedPropertiesId(int id) {
- Q_ASSERT(kind != MemberOfEnum);
- attachedPropertiesIdOrEnumValue = id;
+ Q_ASSERT(kind != MemberOfEnum && kind != MemberOfIdObjectsArray);
+ attachedPropertiesId = id;
}
- void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int attachedPropertiesIdOrEnumValue = 0)
+ void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int index = 0)
{
this->base = base;
this->name = name;
this->property = property;
- this->attachedPropertiesIdOrEnumValue = attachedPropertiesIdOrEnumValue;
+ this->idIndex = index;
this->freeOfSideEffects = false;
this->inhibitTypeConversionOnWrite = property != 0;
this->kind = kind;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c0669d3e47..c150666a11 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3912,7 +3912,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
QString name;
if (f->name) name = *f->name;
- else name = QString::fromLatin1("%1").arg((unsigned long long)f);
+ else name = QStringLiteral("%1").arg((unsigned long long)f);
qout << "digraph \"" << name << "\" { ordering=out;\n";
foreach (LoopDetection::LoopInfo *l, loops) {
@@ -4020,14 +4020,14 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
if (Member *member = m->source->asMember()) {
if (member->kind == Member::MemberOfEnum) {
Const *c = function->New<Const>();
- const int enumValue = member->attachedPropertiesIdOrEnumValue;
+ const int enumValue = member->enumValue;
c->init(SInt32Type, enumValue);
replaceUses(targetTemp, c, W);
defUses.removeDef(*targetTemp);
W.remove(s);
defUses.removeUse(s, *member->base->asTemp());
continue;
- } else if (member->attachedPropertiesIdOrEnumValue != 0 && member->property && member->base->asTemp()) {
+ } else if (member->kind != IR::Member::MemberOfIdObjectsArray && member->attachedPropertiesId != 0 && member->property && member->base->asTemp()) {
// Attached properties have no dependency on their base. Isel doesn't
// need it and we can eliminate the temp used to initialize it.
defUses.removeUse(s, *member->base->asTemp());
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 77a3ba6490..30a44eedd1 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -1,36 +1,23 @@
+contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER
+
SOURCES += \
+ $$PWD/qqmldebug.cpp \
+ $$PWD/qqmldebugconnector.cpp \
$$PWD/qqmldebugservice.cpp \
- $$PWD/qqmlprofilerservice.cpp \
- $$PWD/qqmldebugserver.cpp \
- $$PWD/qqmlinspectorservice.cpp \
- $$PWD/qqmlenginedebugservice.cpp \
- $$PWD/qdebugmessageservice.cpp \
- $$PWD/qv4debugservice.cpp \
- $$PWD/qqmlconfigurabledebugservice.cpp \
- $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmldebugserviceinterfaces.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qv4profileradapter.cpp \
$$PWD/qqmlprofiler.cpp
HEADERS += \
+ $$PWD/qqmldebugconnector_p.h \
+ $$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservice_p.h \
- $$PWD/qqmldebugservice_p_p.h \
- $$PWD/qqmlprofilerservice_p.h \
- $$PWD/qqmldebugserver_p.h \
- $$PWD/qqmldebugserverconnection_p.h \
+ $$PWD/qqmldebugservicefactory_p.h \
+ $$PWD/qqmldebugserviceinterfaces_p.h \
$$PWD/qqmldebugstatesdelegate_p.h \
- $$PWD/qqmlinspectorservice_p.h \
- $$PWD/qqmlinspectorinterface_p.h \
- $$PWD/qqmlenginedebugservice_p.h \
$$PWD/qqmldebug.h \
- $$PWD/qdebugmessageservice_p.h \
- $$PWD/qv4debugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p_p.h \
- $$PWD/qqmlenginecontrolservice_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
- $$PWD/qv4profileradapter_p.h \
$$PWD/qqmlprofiler_p.h
INCLUDEPATH += $$PWD
diff --git a/src/qml/debugger/qdebugmessageservice.cpp b/src/qml/debugger/qdebugmessageservice.cpp
deleted file mode 100644
index deaa472ce0..0000000000
--- a/src/qml/debugger/qdebugmessageservice.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdebugmessageservice_p.h"
-#include "qqmldebugservice_p_p.h"
-
-#include <QDataStream>
-#include <QMutex>
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QDebugMessageService, qmlDebugMessageService)
-
-void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
- const QString &buf)
-{
- QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf);
-}
-
-class QDebugMessageServicePrivate : public QQmlDebugServicePrivate
-{
-public:
- QDebugMessageServicePrivate()
- : oldMsgHandler(0)
- , prevState(QQmlDebugService::NotConnected)
- {
- }
-
- QtMessageHandler oldMsgHandler;
- QQmlDebugService::State prevState;
- QMutex initMutex;
-};
-
-QDebugMessageService::QDebugMessageService(QObject *parent) :
- QQmlDebugService(*(new QDebugMessageServicePrivate()),
- QStringLiteral("DebugMessages"), 2, parent)
-{
- Q_D(QDebugMessageService);
-
- // don't execute stateChanged() in parallel
- QMutexLocker lock(&d->initMutex);
- registerService();
- if (state() == Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- d->prevState = Enabled;
- }
-}
-
-QDebugMessageService *QDebugMessageService::instance()
-{
- return qmlDebugMessageService();
-}
-
-void QDebugMessageService::sendDebugMessage(QtMsgType type,
- const QMessageLogContext &ctxt,
- const QString &buf)
-{
- Q_D(QDebugMessageService);
-
- //We do not want to alter the message handling mechanism
- //We just eavesdrop and forward the messages to a port
- //only if a client is connected to it.
- QByteArray message;
- QQmlDebugStream ws(&message, QIODevice::WriteOnly);
- ws << QByteArray("MESSAGE") << type << buf.toUtf8();
- ws << QString::fromLatin1(ctxt.file).toUtf8();
- ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
-
- sendMessage(message);
- if (d->oldMsgHandler)
- (*d->oldMsgHandler)(type, ctxt, buf);
-}
-
-void QDebugMessageService::stateChanged(State state)
-{
- Q_D(QDebugMessageService);
- QMutexLocker lock(&d->initMutex);
-
- if (state != Enabled && d->prevState == Enabled) {
- QtMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler);
- // has our handler been overwritten in between?
- if (handler != DebugMessageHandler)
- qInstallMessageHandler(handler);
-
- } else if (state == Enabled && d->prevState != Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- }
-
- d->prevState = state;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qdebugmessageservice_p.h b/src/qml/debugger/qdebugmessageservice_p.h
deleted file mode 100644
index 694cd0e64c..0000000000
--- a/src/qml/debugger/qdebugmessageservice_p.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDEBUGMESSAGESERVICE_P_H
-#define QDEBUGMESSAGESERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmldebugservice_p.h"
-
-#include <QtCore/qlogging.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDebugMessageServicePrivate;
-
-class QDebugMessageService : public QQmlDebugService
-{
- Q_OBJECT
-public:
- QDebugMessageService(QObject *parent = 0);
-
- static QDebugMessageService *instance();
-
- void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt,
- const QString &buf);
-
-protected:
- void stateChanged(State);
-
-private:
- Q_DISABLE_COPY(QDebugMessageService)
- Q_DECLARE_PRIVATE(QDebugMessageService)
-};
-
-QT_END_NAMESPACE
-
-#endif // QDEBUGMESSAGESERVICE_P_H
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice.cpp b/src/qml/debugger/qqmlconfigurabledebugservice.cpp
deleted file mode 100644
index e3693e00a4..0000000000
--- a/src/qml/debugger/qqmlconfigurabledebugservice.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(const QString &name, float version,
- QObject *parent) :
- QQmlDebugService((*new QQmlConfigurableDebugServicePrivate), name, version, parent) { init(); }
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version,
- QObject *parent) :
- QQmlDebugService(dd, name, version, parent) { init(); }
-
-QMutex *QQmlConfigurableDebugService::configMutex()
-{
- Q_D(QQmlConfigurableDebugService);
- return &d->configMutex;
-}
-
-void QQmlConfigurableDebugService::init()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- // If we're not enabled or not blocking, don't wait for configuration
- d->waitingForConfiguration = (registerService() == Enabled && blockingMode());
-}
-
-void QQmlConfigurableDebugService::stopWaiting()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- d->waitingForConfiguration = false;
- foreach (QQmlEngine *engine, d->waitingEngines)
- emit attachedToEngine(engine);
- d->waitingEngines.clear();
-}
-
-void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState)
-{
- if (newState != Enabled)
- stopWaiting();
-}
-
-void QQmlConfigurableDebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- if (d->waitingForConfiguration)
- d->waitingEngines.append(engine);
- else
- emit attachedToEngine(engine);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p.h
deleted file mode 100644
index cf69c3a1f6..0000000000
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QQMLCONFIGURABLEDEBUGSEVICE_H
-#define QQMLCONFIGURABLEDEBUGSEVICE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmldebugservice_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QMutex;
-class QQmlConfigurableDebugServicePrivate;
-class QQmlConfigurableDebugService : public QQmlDebugService
-{
- Q_OBJECT
-public:
- QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0);
-
-protected:
- QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- QMutex *configMutex();
- void stopWaiting();
- void init();
-
- void stateChanged(State);
- void engineAboutToBeAdded(QQmlEngine *);
-
- virtual ~QQmlConfigurableDebugService() {}
-private:
- Q_DISABLE_COPY(QQmlConfigurableDebugService)
- Q_DECLARE_PRIVATE(QQmlConfigurableDebugService)
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
deleted file mode 100644
index 6d693b6352..0000000000
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLCONFIGURABLEDEBUGSERVICE_P_H
-#define QQMLCONFIGURABLEDEBUGSERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-
-#include <QMutex>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlEngine;
-
-class QQmlConfigurableDebugServicePrivate : public QQmlDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QQmlConfigurableDebugService)
-public:
- QQmlConfigurableDebugServicePrivate() : configMutex(QMutex::Recursive) {}
-
- QMutex configMutex;
- QList<QQmlEngine *> waitingEngines;
- bool waitingForConfiguration;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCONFIGURABLEDEBUGSERVICE_P_H
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
new file mode 100644
index 0000000000..83718921f1
--- /dev/null
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebug.h"
+#include "qqmldebugconnector_p.h"
+
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ if (!QQmlEnginePrivate::qml_debugging_enabled
+ && printWarning) {
+ qDebug("QML debugging is enabled. Only use this in a safe environment.");
+ }
+ QQmlEnginePrivate::qml_debugging_enabled = true;
+#else
+ Q_UNUSED(printWarning);
+#endif
+}
+
+/*!
+ * \enum QQmlDebuggingEnabler::StartMode
+ *
+ * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
+ * client is connecting, in order to set breakpoints in or profile startup code.
+ *
+ * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
+ * \value WaitForClient If a QML engine starts while the debug services are connecting,
+ * interrupt it until they are done.
+ */
+
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * listen on \a port at \a hostName and block the QML engine until it receives a connection if
+ * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
+ * specified it will listen on all available interfaces. You can only start one debug server at a
+ * time. A debug server may have already been started if the -qmljsdebugger= command line argument
+ * was given. This method returns \c true if a new debug server was successfully started, or
+ * \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ configuration[QLatin1String("hostAddress")] = hostName;
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+ Q_UNUSED(hostName);
+#endif
+ return false;
+}
+
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server 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
+ * specified it will not block. You can only start one debug server at a time. A debug server may
+ * have already been started if the -qmljsdebugger= command line argument was given. This method
+ * returns \c true if a new debug server was successfully started, or \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, StartMode mode)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("fileName")] = socketFileName;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+#endif
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 559c492dfd..5d65982a49 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -50,6 +50,8 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
QQmlDebuggingEnabler(bool printWarning = true);
static bool startTcpDebugServer(int port, StartMode mode = DoNotWaitForClient,
const QString &hostName = QString());
+ static bool connectToLocalDebugger(const QString &socketFileName,
+ StartMode mode = DoNotWaitForClient);
};
// Execute code in constructor before first QQmlEngine is instantiated
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
new file mode 100644
index 0000000000..8de734fa68
--- /dev/null
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugpluginmanager_p.h"
+#include "qqmldebugconnector_p.h"
+#include "qqmldebugservicefactory_p.h"
+#include <QtCore/QPluginLoader>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QJsonArray>
+
+#include <private/qcoreapplication_p.h>
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// We could add more plugins here, and distinguish by arguments to instance()
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugConnector)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebugServerFactory)
+
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebuggerServiceFactory)
+
+struct QQmlDebugConnectorParams {
+ QString pluginKey;
+ QStringList services;
+ QString arguments;
+ QQmlDebugConnector *instance;
+
+ QQmlDebugConnectorParams() : instance(0)
+ {
+ if (qApp) {
+ QCoreApplicationPrivate *appD =
+ static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
+ if (appD)
+ arguments = appD->qmljsDebugArgumentsString();
+ }
+ }
+};
+
+Q_GLOBAL_STATIC(QQmlDebugConnectorParams, qmlDebugConnectorParams)
+
+void QQmlDebugConnector::setPluginKey(const QString &key)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params) {
+ if (params->instance)
+ qWarning() << "QML debugger: Cannot set plugin key after loading the plugin.";
+ else
+ params->pluginKey = key;
+ }
+}
+
+void QQmlDebugConnector::setServices(const QStringList &services)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params)
+ params->services = services;
+}
+
+QString QQmlDebugConnector::commandLineArguments()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return QString();
+ return params->arguments;
+}
+
+QQmlDebugConnector *QQmlDebugConnector::instance()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return 0;
+
+ 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);
+ params->arguments.clear();
+ }
+ return 0;
+ }
+
+ if (!params->instance) {
+ if (!params->pluginKey.isEmpty()) {
+ if (params->pluginKey != QLatin1String("QQmlDebugServer"))
+ return 0; // We cannot load anything else, yet
+ } else if (params->arguments.isEmpty()) {
+ return 0; // no explicit class name given and no command line arguments
+ }
+ params->instance = loadQQmlDebugConnector(QLatin1String("QQmlDebugServer"));
+ if (params->instance) {
+ foreach (const QJsonObject &object, metaDataForQQmlDebugService()) {
+ foreach (const QJsonValue &key, object.value(QLatin1String("MetaData")).toObject()
+ .value(QLatin1String("Keys")).toArray()) {
+ QString keyString = key.toString();
+ if (params->services.isEmpty() || params->services.contains(keyString))
+ loadQQmlDebugService(keyString);
+ }
+ }
+ }
+ }
+
+ return params->instance;
+}
+
+QQmlDebugConnectorFactory::~QQmlDebugConnectorFactory()
+{
+ // This is triggered when the plugin is unloaded.
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params && params->instance) {
+ delete params->instance;
+ params->instance = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlinspectorservice_p.h b/src/qml/debugger/qqmldebugconnector_p.h
index f49c36aacb..f5f5a87b56 100644
--- a/src/qml/debugger/qqmlinspectorservice_p.h
+++ b/src/qml/debugger/qqmldebugconnector_p.h
@@ -31,8 +31,13 @@
**
****************************************************************************/
-#ifndef QQMLINSPECTORSERVICE_H
-#define QQMLINSPECTORSERVICE_H
+#ifndef QQMLDEBUGCONNECTOR_H
+#define QQMLDEBUGCONNECTOR_H
+
+#include <QtQml/qtqmlglobal.h>
+#include <QtCore/QVariantList>
+
+#include <private/qqmldebugservice_p.h>
//
// W A R N I N G
@@ -45,45 +50,49 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
-
-#include <QtQml/qtqmlglobal.h>
-#include <QtCore/QList>
-
QT_BEGIN_NAMESPACE
-
-class QQmlInspectorInterface;
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService
+class QQmlDebugService;
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject
{
Q_OBJECT
-
public:
- QQmlInspectorService();
- static QQmlInspectorService *instance();
+ static void setPluginKey(const QString &key);
+ static void setServices(const QStringList &services);
+ static QQmlDebugConnector *instance();
- void addView(QObject *);
- void removeView(QObject *);
+ virtual bool blockingMode() const = 0;
- void sendMessage(const QByteArray &message);
+ virtual QQmlDebugService *service(const QString &name) const = 0;
-protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
+ virtual void addEngine(QQmlEngine *engine) = 0;
+ virtual void removeEngine(QQmlEngine *engine) = 0;
+
+ virtual bool addService(const QString &name, QQmlDebugService *service) = 0;
+ virtual bool removeService(const QString &name) = 0;
-private Q_SLOTS:
- void processMessage(const QByteArray &message);
- void updateState();
+ virtual bool open(const QVariantHash &configuration = QVariantHash()) = 0;
-private:
- void loadInspectorPlugins();
+ template<class Service>
+ static Service *service()
+ {
+ QQmlDebugConnector *inst = instance();
+ return inst ? static_cast<Service *>(inst->service(Service::s_key)) : 0;
+ }
+
+protected:
+ static QString commandLineArguments();
+};
- QList<QObject*> m_views;
- QQmlInspectorInterface *m_currentInspectorPlugin;
- QList<QQmlInspectorInterface*> m_inspectorPlugins;
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnectorFactory : public QObject {
+ Q_OBJECT
+public:
+ virtual QQmlDebugConnector *create(const QString &key) = 0;
+ ~QQmlDebugConnectorFactory();
};
+#define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory"
+
QT_END_NAMESPACE
-#endif // QQMLINSPECTORSERVICE_H
+#endif // QQMLDEBUGCONNECTOR_H
diff --git a/src/qml/debugger/qqmlenginecontrolservice_p.h b/src/qml/debugger/qqmldebugpluginmanager_p.h
index 2171937efe..cef463b8b3 100644
--- a/src/qml/debugger/qqmlenginecontrolservice_p.h
+++ b/src/qml/debugger/qqmldebugpluginmanager_p.h
@@ -31,11 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLENGINECONTROLSERVICE_H
-#define QQMLENGINECONTROLSERVICE_H
-
-#include <QMutex>
-#include "qqmldebugservice_p.h"
+#ifndef QQMLDEBUGPLUGINMANAGER_P_H
+#define QQMLDEBUGPLUGINMANAGER_P_H
//
// W A R N I N G
@@ -48,43 +45,49 @@
// We mean it.
//
-QT_BEGIN_NAMESPACE
-
-class QQmlEngineControlService : public QQmlDebugService
-{
-public:
- enum MessageType {
- EngineAboutToBeAdded,
- EngineAdded,
- EngineAboutToBeRemoved,
- EngineRemoved
- };
+#include <QDebug>
+#include <private/qtqmlglobal_p.h>
+#include <private/qfactoryloader_p.h>
- enum CommandType {
- StartWaitingEngine,
- StopWaitingEngine
- };
+QT_BEGIN_NAMESPACE
- QQmlEngineControlService();
+#if defined(QT_NO_QML_DEBUGGER)
- static QQmlEngineControlService *instance();
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ qWarning() << "Qml Debugger: QtQml is not configured for debugging. Ignoring request for"\
+ << "debug plugin" << key;\
+ return 0;\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return QList<QJsonObject();\
+ }
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
-protected:
- QMutex dataMutex;
- QList<QQmlEngine *> startingEngines;
- QList<QQmlEngine *> stoppingEngines;
+#else // QT_NO_QML_DEBUGGER
- void messageReceived(const QByteArray &);
- void engineAboutToBeAdded(QQmlEngine *);
- void engineAboutToBeRemoved(QQmlEngine *);
- void engineAdded(QQmlEngine *);
- void engineRemoved(QQmlEngine *);
+#ifdef QT_STATIC
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)\
+ Q_IMPORT_PLUGIN(className)
+#else
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
+#endif // QT_STATIC
- void sendMessage(MessageType type, QQmlEngine *engine);
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, interfaceName##Loader,\
+ (interfaceName##Factory_iid, QLatin1String("/qmltooling")))\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ return qLoadPlugin<interfaceName, interfaceName##Factory>(interfaceName##Loader(), key);\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return interfaceName##Loader()->metaData();\
+ }
- void stateChanged(State);
-};
+#endif // QT_NO_QML_DEBUGGER
QT_END_NAMESPACE
-
-#endif // QQMLENGINECONTROLSERVICE_H
+#endif // QQMLDEBUGPLUGINMANAGER_P_H
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
deleted file mode 100644
index b0302181ee..0000000000
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ /dev/null
@@ -1,787 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmldebugserver_p.h"
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmlenginedebugservice_p.h"
-#include "qv4debugservice_p.h"
-#include "qdebugmessageservice_p.h"
-#include "qqmlprofilerservice_p.h"
-
-#include <private/qqmlengine_p.h>
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QAtomicInt>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-#include <QtCore/QStringList>
-#include <QtCore/qwaitcondition.h>
-
-#include <private/qobject_p.h>
-#include <private/qcoreapplication_p.h>
-
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
-#include "../../plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h"
-#endif
-
-QT_BEGIN_NAMESPACE
-
-// We can't friend the Q_GLOBAL_STATIC to have the constructor available so we need a little
-// workaround here. Using this wrapper we can also make QQmlEnginePrivate's cleanup() available to
-// qAddPostRoutine(). We can't do the cleanup in the destructor because we need a QApplication to
-// be available when stopping the plugins.
-struct QQmlDebugServerInstanceWrapper {
- QQmlDebugServer m_instance;
- void cleanup();
-};
-
-Q_GLOBAL_STATIC(QQmlDebugServerInstanceWrapper, debugServerInstance)
-
-/*
- QQmlDebug Protocol (Version 1):
-
- handshake:
- 1. Client sends
- "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
- version: an int representing the highest protocol version the client knows
- pluginNames: plugins available on client side
- 2. Server sends
- "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
- version: an int representing the highest protocol version the client & server know
- pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
- client plugin advertisement
- 1. Client sends
- "QDeclarativeDebugServer" 1 pluginNames
- server plugin advertisement
- 1. Server sends
- "QDeclarativeDebugClient" 1 pluginNames pluginVersions
- plugin communication:
- Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
- */
-
-const int protocolVersion = 1;
-int QQmlDebugServer::s_dataStreamVersion = QDataStream::Qt_4_7;
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-class QQmlDebugServerThread;
-
-class QQmlDebugServerPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlDebugServer)
-public:
- QQmlDebugServerPrivate();
-
- bool start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName);
- void advertisePlugins();
- void cleanup();
- QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
-
- QQmlDebugServerConnection *connection;
- QHash<QString, QQmlDebugService *> plugins;
- mutable QReadWriteLock pluginsLock;
- QStringList clientPlugins;
- bool gotHello;
- bool blockingMode;
-
- class EngineCondition {
- public:
- EngineCondition() : numServices(0), condition(new QWaitCondition) {}
-
- bool waitForServices(QReadWriteLock *locked, int numEngines);
-
- void wake();
- private:
- int numServices;
-
- // shared pointer to allow for QHash-inflicted copying.
- QSharedPointer<QWaitCondition> condition;
- };
-
- QHash<QQmlEngine *, EngineCondition> engineConditions;
-
- QMutex helloMutex;
- QWaitCondition helloCondition;
- QQmlDebugServerThread *thread;
- QPluginLoader loader;
- QAtomicInt changeServiceStateCalls;
-
-private:
- // private slots
- void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState);
- void _q_sendMessages(const QList<QByteArray> &messages);
- void _q_removeThread();
-};
-
-void QQmlDebugServerInstanceWrapper::cleanup()
-{ m_instance.d_func()->cleanup(); }
-
-class QQmlDebugServerThread : public QThread
-{
-public:
- void setPluginName(const QString &pluginName) {
- m_pluginName = pluginName;
- }
-
- void setPortRange(int portFrom, int portTo, bool block, const QString &hostAddress) {
- m_portFrom = portFrom;
- m_portTo = portTo;
- m_block = block;
- m_hostAddress = hostAddress;
- }
-
- void run();
-
-private:
- QString m_pluginName;
- int m_portFrom;
- int m_portTo;
- bool m_block;
- QString m_hostAddress;
-};
-
-QQmlDebugServerPrivate::QQmlDebugServerPrivate() :
- connection(0),
- pluginsLock(QReadWriteLock::Recursive),
- gotHello(false),
- blockingMode(false),
- thread(0)
-{
- // used in _q_sendMessages
- qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
- // used in _q_changeServiceState
- qRegisterMetaType<QQmlDebugService::State>("QQmlDebugService::State");
-}
-
-void QQmlDebugServerPrivate::advertisePlugins()
-{
- Q_Q(QQmlDebugServer);
-
- if (!gotHello)
- return;
-
- QByteArray message;
- {
- QQmlDebugStream out(&message, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 1 << pluginNames << pluginVersions;
- }
-
- QMetaObject::invokeMethod(q, "_q_sendMessages", Qt::QueuedConnection, Q_ARG(QList<QByteArray>, QList<QByteArray>() << message));
-}
-
-void QQmlDebugServerPrivate::cleanup()
-{
- Q_Q(QQmlDebugServer);
- {
- QReadLocker lock(&pluginsLock);
- foreach (QQmlDebugService *service, plugins.values()) {
- changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(q, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, QQmlDebugService::NotConnected));
- }
- }
-
- // Wait for changeServiceState calls to finish
- // (while running an event loop because some services
- // might again use slots to execute stuff in the GUI thread)
- QEventLoop loop;
- while (!changeServiceStateCalls.testAndSetOrdered(0, 0))
- loop.processEvents();
-
- // Stop the thread while the application is still there. Copy here as the thread will set itself
- // to 0 when it stops. It will also do deleteLater, but as long as we don't allow the GUI
- // thread's event loop to run we're safe from that.
- QThread *threadCopy = thread;
- if (threadCopy) {
- threadCopy->exit();
- threadCopy->wait();
- }
-}
-
-QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
- const QString &pluginName)
-{
-#ifndef QT_NO_LIBRARY
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists()) {
- QStringList plugins(dir.entryList(QDir::Files));
- foreach (const QString &pluginPath, plugins) {
- if (QFileInfo(pluginPath).fileName().contains(pluginName))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
- }
- }
-
- QQmlDebugServerConnection *loadedConnection = 0;
- foreach (const QString &pluginPath, pluginCandidates) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Trying to load plugin " << pluginPath << "...";
-
- loader.setFileName(pluginPath);
- if (!loader.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Error while loading: " << loader.errorString();
- continue;
- }
- if (QObject *instance = loader.instance())
- loadedConnection = qobject_cast<QQmlDebugServerConnection*>(instance);
-
- if (loadedConnection) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin successfully loaded.";
-
- return loadedConnection;
- }
-
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin does not implement interface QQmlDebugServerConnection.";
-
- loader.unload();
- }
-#endif
- return 0;
-}
-
-void QQmlDebugServerThread::run()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- Q_ASSERT_X(wrapper != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
- QQmlDebugServer *server = &wrapper->m_instance;
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
- QQmlDebugServerConnection *connection
- = new QTcpServerConnection;
-#else
- QQmlDebugServerConnection *connection
- = server->d_func()->loadConnectionPlugin(m_pluginName);
-#endif
- if (connection) {
- connection->setServer(server);
- if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
- delete connection;
- return;
- }
- server->d_func()->connection = connection;
- if (m_block)
- connection->waitForConnection();
- } else {
- qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
- return;
- }
-
- exec();
-
- // make sure events still waiting are processed
- QEventLoop eventLoop;
- eventLoop.processEvents(QEventLoop::AllEvents);
-}
-
-bool QQmlDebugServer::hasDebuggingClient() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection
- && d->connection->isConnected()
- && d->gotHello;
-}
-
-bool QQmlDebugServer::hasThread() const
-{
- Q_D(const QQmlDebugServer);
- return d->thread != 0;
-}
-
-bool QQmlDebugServer::hasConnection() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection != 0;
-}
-
-bool QQmlDebugServer::blockingMode() const
-{
- Q_D(const QQmlDebugServer);
- return d->blockingMode;
-}
-
-QQmlDebugServer *QQmlDebugServer::instance()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper && wrapper->m_instance.d_func()->thread) {
- QQmlDebugServer *ret = &(wrapper->m_instance);
- QQmlDebugServerPrivate *d = ret->d_func();
- QMutexLocker locker(&d->helloMutex);
- if (d->blockingMode && !d->gotHello)
- d->helloCondition.wait(&d->helloMutex);
- return ret;
- } else {
- return 0;
- }
-}
-
-static void cleanupOnShutdown()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper)
- wrapper->cleanup();
-}
-
-bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName)
-{
- if (!QQmlEnginePrivate::qml_debugging_enabled)
- return false;
- if (thread)
- return false;
- static bool postRoutineAdded = false;
- if (!postRoutineAdded) {
- qAddPostRoutine(cleanupOnShutdown);
- postRoutineAdded = true;
- }
- Q_Q(QQmlDebugServer);
- thread = new QQmlDebugServerThread;
- q->moveToThread(thread);
-
- // Remove the thread immmediately when it finishes, so that we don't have to wait for the event
- // loop to signal that.
- QObject::connect(thread, SIGNAL(finished()), q, SLOT(_q_removeThread()), Qt::DirectConnection);
-
- thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
- thread->setPluginName(pluginName);
- thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
- blockingMode = block;
- thread->start();
- return true;
-}
-
-QQmlDebugServer::QQmlDebugServer()
- : QObject(*(new QQmlDebugServerPrivate))
-{
- if (qApp == 0)
- return;
- QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QT_NO_QML_DEBUGGER
- // ### remove port definition when protocol is changed
- int portFrom = 0;
- int portTo = 0;
- bool block = false;
- bool ok = false;
- QString hostAddress;
-
- // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- if (!QQmlEnginePrivate::qml_debugging_enabled) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Debugging has not been enabled.")).arg(
- appD->qmljsDebugArgumentsString());
- return;
- }
-
- QString pluginName;
- QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
- .split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
- QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
- if (strArgument.startsWith(QLatin1String("port:"))) {
- pluginName = QLatin1String("qmldbg_tcp");
- portFrom = strArgument.mid(5).toInt(&ok);
- portTo = portFrom;
- QStringList::const_iterator argsNext = argsIt + 1;
- if (argsNext == argsItEnd)
- break;
- const QString nextArgument = *argsNext;
- if (ok && nextArgument.contains(QRegExp(QStringLiteral("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
- ++argsIt;
- }
- } else if (strArgument.startsWith(QLatin1String("host:"))) {
- hostAddress = strArgument.mid(5);
- } else if (strArgument == QLatin1String("block")) {
- block = true;
- } else {
- qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
- "detected. Ignoring the same.")
- .arg(strArgument);
- }
- }
-
- if (ok) {
- Q_D(QQmlDebugServer);
- d->start(portFrom, portTo, block, hostAddress, pluginName);
- } else {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
- "<ip address>][,block]")).arg(appD->qmljsDebugArgumentsString());
- }
- }
-#else
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "QtQml is not configured for debugging.")).arg(
- appD->qmljsDebugArgumentsString());
- }
-#endif
-}
-
-void QQmlDebugServer::receiveMessage(const QByteArray &message)
-{
- typedef QHash<QString, QQmlDebugService*>::const_iterator DebugServiceConstIt;
-
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
-
- QQmlDebugStream in(message);
-
- QString name;
-
- in >> name;
- if (name == QLatin1String("QDeclarativeDebugServer")) {
- int op = -1;
- in >> op;
- if (op == 0) {
- QWriteLocker lock(&d->pluginsLock);
- int version;
- in >> version >> d->clientPlugins;
-
- //Get the supported QDataStream version
- if (!in.atEnd()) {
- in >> s_dataStreamVersion;
- if (s_dataStreamVersion > QDataStream().version())
- s_dataStreamVersion = QDataStream().version();
- }
-
- // Send the hello answer immediately, since it needs to arrive before
- // the plugins below start sending messages.
-
- QByteArray helloAnswer;
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, d->plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
-
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << s_dataStreamVersion;
-
- d->connection->send(QList<QByteArray>() << helloAnswer);
-
- QMutexLocker helloLock(&d->helloMutex);
- d->gotHello = true;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(iter.key()))
- newState = QQmlDebugService::Enabled;
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
-
- d->helloCondition.wakeAll();
-
- } else if (op == 1) {
- QWriteLocker lock(&d->pluginsLock);
-
- // Service Discovery
- QStringList oldClientPlugins = d->clientPlugins;
- in >> d->clientPlugins;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- const QString pluginName = iter.key();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(pluginName))
- newState = QQmlDebugService::Enabled;
-
- if (oldClientPlugins.contains(pluginName)
- != d->clientPlugins.contains(pluginName)) {
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
- }
-
- } else {
- qWarning("QML Debugger: Invalid control message %d.", op);
- d->connection->disconnect();
- return;
- }
-
- } else {
- if (d->gotHello) {
- QByteArray message;
- in >> message;
-
- QReadLocker lock(&d->pluginsLock);
- QHash<QString, QQmlDebugService *>::Iterator iter = d->plugins.find(name);
- if (iter == d->plugins.end()) {
- qWarning() << "QML Debugger: Message received for missing plugin" << name << '.';
- } else {
- (*iter)->messageReceived(message);
- }
- } else {
- qWarning("QML Debugger: Invalid hello message.");
- }
-
- }
-}
-
-void QQmlDebugServerPrivate::_q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- QQmlDebugService *service = 0;
- {
- // Write lock here, because this can be called from receiveMessage which already has a write
- // lock. We cannot downgrade it. We also don't want to give up the write lock and later get
- // a read lock as that technique has great potential for deadlocks.
- QWriteLocker lock(&pluginsLock);
- service = plugins.value(serviceName);
- }
-
- if (service && (service->d_func()->state != newState)) {
- service->stateAboutToBeChanged(newState);
- service->d_func()->state = newState;
- service->stateChanged(newState);
- }
-
- changeServiceStateCalls.deref();
-}
-
-void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- if (connection)
- connection->send(messages);
-}
-
-void QQmlDebugServerPrivate::_q_removeThread()
-{
- Q_ASSERT(thread->isFinished());
- Q_ASSERT(QThread::currentThread() == thread);
-
- QThread *parentThread = thread->thread();
-
- // We cannot delete it right away as it will access its data after the finished() signal.
- thread->deleteLater();
- thread = 0;
-
- delete connection;
- connection = 0;
-
- // Move it back to the parent thread so that we can potentially restart it on a new thread.
- q_func()->moveToThread(parentThread);
-}
-
-QList<QQmlDebugService*> QQmlDebugServer::services() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.values();
-}
-
-QStringList QQmlDebugServer::serviceNames() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.keys();
-}
-
-void QQmlDebugServer::addEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeAdded(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAdded(engine);
-}
-
-void QQmlDebugServer::removeEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeRemoved(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineRemoved(engine);
-}
-
-bool QQmlDebugServer::addService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
- connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
-
-
- QWriteLocker lock(&d->pluginsLock);
- if (!service || d->plugins.contains(service->name()))
- return false;
- d->plugins.insert(service->name(), service);
- d->advertisePlugins();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(service->name()))
- newState = QQmlDebugService::Enabled;
- service->d_func()->state = newState;
- return true;
-}
-
-bool QQmlDebugServer::removeService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- QWriteLocker lock(&d->pluginsLock);
- QQmlDebugService::State newState = QQmlDebugService::NotConnected;
-
- d->changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, newState));
-
- if (!service || !d->plugins.contains(service->name()))
- return false;
- d->plugins.remove(service->name());
-
- d->advertisePlugins();
-
- return true;
-}
-
-void QQmlDebugServer::sendMessages(QQmlDebugService *service,
- const QList<QByteArray> &messages)
-{
- QList<QByteArray> prefixedMessages;
- foreach (const QByteArray &message, messages) {
- QByteArray prefixed;
- QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
- out << service->name() << message;
- prefixedMessages << prefixed;
- }
-
- QMetaObject::invokeMethod(this, "_q_sendMessages", Qt::QueuedConnection,
- Q_ARG(QList<QByteArray>, prefixedMessages));
-}
-
-bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString &hostAddress)
-{
-#ifndef QT_NO_QML_DEBUGGER
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (!wrapper)
- return false;
- QQmlDebugServerPrivate *d = wrapper->m_instance.d_func();
- if (d->thread)
- return false;
- if (!d->start(portFrom, portTo, block, hostAddress, QLatin1String("qmldbg_tcp")))
- return false;
- while (!wrapper->m_instance.hasConnection()) {
- if (!wrapper->m_instance.hasThread())
- return false;
- }
- return true;
-#else
- Q_UNUSED(portFrom);
- Q_UNUSED(portTo);
- Q_UNUSED(block);
- Q_UNUSED(hostAddress);
- return false;
-#endif
-}
-
-void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
- d->engineConditions[engine].wake();
-}
-
-bool QQmlDebugServerPrivate::EngineCondition::waitForServices(QReadWriteLock *locked, int num)
-{
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != QQmlDebugServer::instance()->thread());
-
- Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
- numServices = num;
- return condition->wait(locked);
-}
-
-void QQmlDebugServerPrivate::EngineCondition::wake()
-{
- if (--numServices == 0)
- condition->wakeAll();
- Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmldebugserver_p.cpp"
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
deleted file mode 100644
index b2bd0b2463..0000000000
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDEBUGSERVER_H
-#define QQMLDEBUGSERVER_H
-
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmldebugserverconnection_p.h>
-#include <private/qqmldebugservice_p.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlDebugServerPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServer : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDebugServer)
- Q_DISABLE_COPY(QQmlDebugServer)
-public:
-
- static QQmlDebugServer *instance();
-
- bool hasThread() const;
- bool hasConnection() const;
- bool hasDebuggingClient() const;
- bool blockingMode() const;
-
- QList<QQmlDebugService*> services() const;
- QStringList serviceNames() const;
-
- void addEngine(QQmlEngine *engine);
- void removeEngine(QQmlEngine *engine);
-
- bool addService(QQmlDebugService *service);
- bool removeService(QQmlDebugService *service);
-
- void receiveMessage(const QByteArray &message);
-
- void sendMessages(QQmlDebugService *service, const QList<QByteArray> &messages);
- static bool enable(int portFrom, int portTo, bool block, const QString &hostAddress);
-
-private slots:
- void wakeEngine(QQmlEngine *engine);
-
-private:
- friend class QQmlDebugService;
- friend class QQmlDebugServicePrivate;
- friend class QQmlDebugServerThread;
- friend struct QQmlDebugServerInstanceWrapper;
- QQmlDebugServer();
- Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State state))
- Q_PRIVATE_SLOT(d_func(), void _q_sendMessages(QList<QByteArray>))
- Q_PRIVATE_SLOT(d_func(), void _q_removeThread())
-
-public:
- static int s_dataStreamVersion;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLDEBUGSERVICE_H
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/qml/debugger/qqmldebugserverconnection_p.h
deleted file mode 100644
index 9170238b46..0000000000
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDEBUGSERVERCONNECTION_H
-#define QQMLDEBUGSERVERCONNECTION_H
-
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlDebugServer;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServerConnection
-{
-public:
- QQmlDebugServerConnection() {}
- virtual ~QQmlDebugServerConnection() {}
-
- virtual void setServer(QQmlDebugServer *server) = 0;
- virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
- virtual bool isConnected() const = 0;
- virtual void send(const QList<QByteArray> &messages) = 0;
- virtual void disconnect() = 0;
- virtual void waitForConnection() = 0;
- virtual bool waitForMessage() = 0;
-};
-
-#define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection"
-
-Q_DECLARE_INTERFACE(QQmlDebugServerConnection, QQmlDebugServerConnection_iid)
-
-QT_END_NAMESPACE
-
-#endif // QQMLDEBUGSERVERCONNECTION_H
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index b37a7335a0..0b07f320ec 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -32,8 +32,7 @@
****************************************************************************/
#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmldebugserver_p.h"
+#include "qqmldebugconnector_p.h"
#include <private/qqmldata_p.h>
#include <private/qqmlcontext_p.h>
@@ -43,58 +42,55 @@
QT_BEGIN_NAMESPACE
-QQmlDebugServicePrivate::QQmlDebugServicePrivate()
-{
-}
+class QQmlDebugServer;
-QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
- : QObject(*(new QQmlDebugServicePrivate), parent)
+class QQmlDebugServicePrivate : public QObjectPrivate
{
- QQmlDebugServer::instance(); // create it when it isn't there yet.
+ Q_DECLARE_PUBLIC(QQmlDebugService)
+public:
+ QQmlDebugServicePrivate(const QString &name, float version);
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
-}
+ const QString name;
+ const float version;
+ QQmlDebugService::State state;
+};
-QQmlDebugService::QQmlDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version, QObject *parent)
- : QObject(dd, parent)
+QQmlDebugServicePrivate::QQmlDebugServicePrivate(const QString &name, float version) :
+ name(name), version(version), state(QQmlDebugService::NotConnected)
{
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
}
-/**
- Registers the service. This should be called in the constructor of the inherited class. From
- then on the service might get asynchronous calls to messageReceived().
- */
-QQmlDebugService::State QQmlDebugService::registerService()
+QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
+ : QObject(*(new QQmlDebugServicePrivate(name, version)), parent)
{
Q_D(QQmlDebugService);
- QQmlDebugServer *server = QQmlDebugServer::instance();
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
if (!server)
- return NotConnected;
+ return;
- if (server->serviceNames().contains(d->name)) {
+ if (server->service(d->name)) {
qWarning() << "QQmlDebugService: Conflicting plugin name" << d->name;
} else {
- server->addService(this);
+ server->addService(d->name, this);
}
- return state();
}
QQmlDebugService::~QQmlDebugService()
{
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->removeService(this);
+ Q_D(QQmlDebugService);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+
+ if (!server)
+ return;
+
+ if (server->service(d->name) != this)
+ qWarning() << "QQmlDebugService: Plugin" << d->name << "is not registered.";
+ else
+ server->removeService(d->name);
}
-QString QQmlDebugService::name() const
+const QString &QQmlDebugService::name() const
{
Q_D(const QQmlDebugService);
return d->name;
@@ -112,27 +108,38 @@ QQmlDebugService::State QQmlDebugService::state() const
return d->state;
}
-namespace {
-
-struct ObjectReference
+void QQmlDebugService::setState(QQmlDebugService::State newState)
{
- QPointer<QObject> object;
- int id;
-};
+ Q_D(QQmlDebugService);
+ d->state = newState;
+}
-struct ObjectReferenceHash
+namespace {
+class ObjectReferenceHash : public QObject
{
+ Q_OBJECT
+public:
ObjectReferenceHash() : nextId(0) {}
- QHash<QObject *, ObjectReference> objects;
+ QHash<QObject *, int> objects;
QHash<int, QObject *> ids;
int nextId;
-};
+private slots:
+ void remove(QObject *obj);
+};
}
Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash)
+void ObjectReferenceHash::remove(QObject *obj)
+{
+ QHash<QObject *, int>::Iterator iter = objects.find(obj);
+ if (iter != objects.end()) {
+ ids.remove(iter.value());
+ objects.erase(iter);
+ }
+}
/*!
Returns a unique id for \a object. Calling this method multiple times
@@ -144,158 +151,23 @@ int QQmlDebugService::idForObject(QObject *object)
return -1;
ObjectReferenceHash *hash = objectReferenceHash();
- QHash<QObject *, ObjectReference>::Iterator iter =
- hash->objects.find(object);
+ QHash<QObject *, int>::Iterator iter = hash->objects.find(object);
if (iter == hash->objects.end()) {
int id = hash->nextId++;
-
- hash->ids.insert(id, object);
- iter = hash->objects.insert(object, ObjectReference());
- iter->object = object;
- iter->id = id;
- } else if (iter->object != object) {
- int id = hash->nextId++;
-
- hash->ids.remove(iter->id);
-
hash->ids.insert(id, object);
- iter->object = object;
- iter->id = id;
- }
- return iter->id;
-}
-
-/*!
- Returns the object for unique \a id. If the object has not previously been
- assigned an id, through idForObject(), then 0 is returned. If the object
- has been destroyed, 0 is returned.
-*/
-QObject *QQmlDebugService::objectForId(int id)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
-
- QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
- if (iter == hash->ids.end())
- return 0;
-
-
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- hash->ids.erase(iter);
- hash->objects.erase(objIter);
- // run a loop to remove other invalid objects
- removeInvalidObjectsFromHash();
- return 0;
- } else {
- return *iter;
+ iter = hash->objects.insert(object, id);
+ connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*)));
}
+ return iter.value();
}
/*!
- Returns a list of objects matching the given filename, line and column.
+ Returns the mapping of objects to unique \a ids, created through calls to idForObject().
*/
-QList<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QList<QObject*> objects;
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- QQmlData *ddata = QQmlData::get(iter.value());
- if (ddata && ddata->outerContext) {
- if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
- ddata->lineNumber == lineNumber &&
- ddata->columnNumber >= columnNumber) {
- objects << *iter;
- }
- }
- ++iter;
- }
- }
- return objects;
-}
-
-void QQmlDebugService::removeInvalidObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- ++iter;
- }
- }
-}
-
-void QQmlDebugService::clearObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- hash->ids.clear();
- hash->objects.clear();
-}
-
-bool QQmlDebugService::isDebuggingEnabled()
-{
- return QQmlDebugServer::instance() != 0;
-}
-
-bool QQmlDebugService::hasDebuggingClient()
+const QHash<int, QObject *> &QQmlDebugService::objectsForIds()
{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->hasDebuggingClient();
-}
-
-bool QQmlDebugService::blockingMode()
-{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->blockingMode();
-}
-
-QString QQmlDebugService::objectToString(QObject *obj)
-{
- if(!obj)
- return QStringLiteral("NULL");
-
- QString objectName = obj->objectName();
- if(objectName.isEmpty())
- objectName = QStringLiteral("<unnamed>");
-
- QString rv = QString::fromUtf8(obj->metaObject()->className()) +
- QLatin1String(": ") + objectName;
-
- return rv;
-}
-
-void QQmlDebugService::sendMessage(const QByteArray &message)
-{
- sendMessages(QList<QByteArray>() << message);
-}
-
-void QQmlDebugService::sendMessages(const QList<QByteArray> &messages)
-{
- if (state() != Enabled)
- return;
-
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->sendMessages(this, messages);
+ return objectReferenceHash()->ids;
}
void QQmlDebugService::stateAboutToBeChanged(State)
@@ -328,28 +200,32 @@ void QQmlDebugService::engineRemoved(QQmlEngine *)
{
}
+int QQmlDebugStream::s_dataStreamVersion = QDataStream::Qt_4_7;
+
QQmlDebugStream::QQmlDebugStream()
: QDataStream()
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QIODevice *d)
: QDataStream(d)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
: QDataStream(ba, flags)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
: QDataStream(ba)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QT_END_NAMESPACE
+
+#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 9cdfc34ff1..3d692133cc 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -35,7 +35,8 @@
#define QQMLDEBUGSERVICE_H
#include <QtCore/qobject.h>
-#include <QtCore/QDataStream>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qhash.h>
#include <private/qtqmlglobal_p.h>
@@ -62,35 +63,14 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
Q_DISABLE_COPY(QQmlDebugService)
public:
- explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
~QQmlDebugService();
- QString name() const;
+ const QString &name() const;
float version() const;
enum State { NotConnected, Unavailable, Enabled };
State state() const;
-
- void sendMessage(const QByteArray &);
- void sendMessages(const QList<QByteArray> &);
-
- static int idForObject(QObject *);
- static QObject *objectForId(int);
- static QList<QObject*> objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber);
- static void removeInvalidObjectsFromHash();
- static void clearObjectsFromHash();
-
- static QString objectToString(QObject *obj);
-
- static bool isDebuggingEnabled();
- static bool hasDebuggingClient();
- static bool blockingMode();
-
-protected:
- QQmlDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- State registerService();
+ void setState(State newState);
virtual void stateAboutToBeChanged(State);
virtual void stateChanged(State);
@@ -101,18 +81,26 @@ protected:
virtual void engineAdded(QQmlEngine *);
virtual void engineRemoved(QQmlEngine *);
+ static const QHash<int, QObject *> &objectsForIds();
+ static int idForObject(QObject *);
+ static QObject *objectForId(int id) { return objectsForIds().value(id); }
+
+protected:
+ explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
+
signals:
void attachedToEngine(QQmlEngine *);
void detachedFromEngine(QQmlEngine *);
-private:
- friend class QQmlDebugServer;
- friend class QQmlDebugServerPrivate;
+ void messageToClient(const QString &name, const QByteArray &message);
+ void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
{
public:
+ static int s_dataStreamVersion;
+
QQmlDebugStream();
explicit QQmlDebugStream(QIODevice *d);
QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
diff --git a/src/qml/debugger/qqmldebugservice_p_p.h b/src/qml/debugger/qqmldebugservicefactory_p.h
index 7d60739f3a..af50cd4635 100644
--- a/src/qml/debugger/qqmldebugservice_p_p.h
+++ b/src/qml/debugger/qqmldebugservicefactory_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLDEBUGSERVICE_P_H
-#define QQMLDEBUGSERVICE_P_H
+#ifndef QQMLDEBUGSERVICEFACTORY_P_H
+#define QQMLDEBUGSERVICEFACTORY_P_H
//
// W A R N I N G
@@ -45,25 +45,19 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
-#include <private/qobject_p.h>
+#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-
-class QQmlDebugServer;
-
-class QQmlDebugServicePrivate : public QObjectPrivate
+class Q_QML_PRIVATE_EXPORT QQmlDebugServiceFactory : public QObject
{
- Q_DECLARE_PUBLIC(QQmlDebugService)
+ Q_OBJECT
public:
- QQmlDebugServicePrivate();
-
- QString name;
- float version;
- QQmlDebugService::State state;
+ virtual QQmlDebugService *create(const QString &key) = 0;
};
+#define QQmlDebugServiceFactory_iid "org.qt-project.Qt.QQmlDebugServiceFactory"
+
QT_END_NAMESPACE
-#endif // QQMLDEBUGSERVICE_P_H
+#endif // QQMLDEBUGSERVICEFACTORY_P_H
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
index e4b9f75298..2bf9f2785c 100644
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
@@ -30,29 +30,14 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4QMLEXTENSIONS_P_H
-#define QV4QMLEXTENSIONS_P_H
-#include <qtqmlglobal.h>
-#include <qv4global_p.h>
+#include "qqmldebugserviceinterfaces_p.h"
QT_BEGIN_NAMESPACE
-namespace QV4 {
-
-struct Q_QML_EXPORT QmlExtensions
-{
- QmlExtensions()
- : valueTypeWrapperPrototype(0)
- {}
-
- Heap::Object *valueTypeWrapperPrototype;
-
- void markObjects(ExecutionEngine *e);
-};
-
-} // namespace QV4
+const QString QV4DebugService::s_key = QStringLiteral("V8Debugger");
+const QString QQmlEngineDebugService::s_key = QStringLiteral("QmlDebugger");
+const QString QQmlInspectorService::s_key = QStringLiteral("QmlInspector");
+const QString QQmlProfilerService::s_key = QStringLiteral("CanvasFrameRate");
QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
new file mode 100644
index 0000000000..a2ba670608
--- /dev/null
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGSERVICEINTERFACES_P_H
+#define QQMLDEBUGSERVICEINTERFACES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstring.h>
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugstatesdelegate_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
+#include <private/qqmlboundsignal_p.h>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void signalEmitted(const QString &signal) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QV4DebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+ virtual void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+ virtual void startProfiling(QQmlEngine *engine,
+ quint64 features = std::numeric_limits<quint64>::max()) = 0;
+ virtual void stopProfiling(QQmlEngine *engine) = 0;
+
+ virtual void dataReady(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlProfilerService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void objectCreated(QQmlEngine *engine, QObject *object) = 0;
+ virtual void setStatesDelegate(QQmlDebugStatesDelegate *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlEngineDebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addView(QObject *) = 0;
+ virtual void removeView(QObject *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlInspectorService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVICEINTERFACES_P_H
+
diff --git a/src/qml/debugger/qqmlenginecontrolservice.cpp b/src/qml/debugger/qqmlenginecontrolservice.cpp
deleted file mode 100644
index 07c6715524..0000000000
--- a/src/qml/debugger/qqmlenginecontrolservice.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QQmlEngine>
-#include "qqmldebug.h"
-#include "qqmlenginecontrolservice_p.h"
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlEngineControlService, qmlEngineControlService)
-
-QQmlEngineControlService::QQmlEngineControlService() :
- QQmlDebugService(QStringLiteral("EngineControl"), 1)
-{
- QMutexLocker lock(&dataMutex);
- registerService();
-}
-
-QQmlEngineControlService *QQmlEngineControlService::instance()
-{
- return qmlEngineControlService();
-}
-
-void QQmlEngineControlService::messageReceived(const QByteArray &message)
-{
- QMutexLocker lock(&dataMutex);
- QQmlDebugStream d(message);
- int command;
- int engineId;
- d >> command >> engineId;
- QQmlEngine *engine = qobject_cast<QQmlEngine *>(objectForId(engineId));
- if (command == StartWaitingEngine && startingEngines.contains(engine)) {
- startingEngines.removeOne(engine);
- emit attachedToEngine(engine);
- } else if (command == StopWaitingEngine && stoppingEngines.contains(engine)) {
- stoppingEngines.removeOne(engine);
- emit detachedFromEngine(engine);
- }
-}
-
-void QQmlEngineControlService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- QMutexLocker lock(&dataMutex);
- if (state() == Enabled) {
- Q_ASSERT(!stoppingEngines.contains(engine));
- Q_ASSERT(!startingEngines.contains(engine));
- startingEngines.append(engine);
- sendMessage(EngineAboutToBeAdded, engine);
- } else {
- emit attachedToEngine(engine);
- }
-}
-
-void QQmlEngineControlService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- QMutexLocker lock(&dataMutex);
- if (state() == Enabled) {
- Q_ASSERT(!stoppingEngines.contains(engine));
- Q_ASSERT(!startingEngines.contains(engine));
- stoppingEngines.append(engine);
- sendMessage(EngineAboutToBeRemoved, engine);
- } else {
- emit detachedFromEngine(engine);
- }
-}
-
-void QQmlEngineControlService::engineAdded(QQmlEngine *engine)
-{
- if (state() == Enabled) {
- QMutexLocker lock(&dataMutex);
- Q_ASSERT(!startingEngines.contains(engine));
- Q_ASSERT(!stoppingEngines.contains(engine));
- sendMessage(EngineAdded, engine);
- }
-}
-
-void QQmlEngineControlService::engineRemoved(QQmlEngine *engine)
-{
- if (state() == Enabled) {
- QMutexLocker lock(&dataMutex);
- Q_ASSERT(!startingEngines.contains(engine));
- Q_ASSERT(!stoppingEngines.contains(engine));
- sendMessage(EngineRemoved, engine);
- }
-}
-
-void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType type, QQmlEngine *engine)
-{
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- d << type << idForObject(engine);
- QQmlDebugService::sendMessage(message);
-}
-
-void QQmlEngineControlService::stateChanged(State)
-{
- // We flush everything for any kind of state change, to avoid complicated timing issues.
- QMutexLocker lock(&dataMutex);
- foreach (QQmlEngine *engine, startingEngines)
- emit attachedToEngine(engine);
- startingEngines.clear();
- foreach (QQmlEngine *engine, stoppingEngines)
- emit detachedFromEngine(engine);
- stoppingEngines.clear();
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
deleted file mode 100644
index da01d00f17..0000000000
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ /dev/null
@@ -1,820 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlenginedebugservice_p.h"
-
-#include "qqmldebugstatesdelegate_p.h"
-#include <private/qqmlboundsignal_p.h>
-#include <qqmlengine.h>
-#include <private/qqmlmetatype_p.h>
-#include <qqmlproperty.h>
-#include <private/qqmlproperty_p.h>
-#include <private/qqmlbinding_p.h>
-#include <private/qqmlcontext_p.h>
-#include <private/qqmlwatcher_p.h>
-#include <private/qqmlvaluetype_p.h>
-#include <private/qqmlvmemetaobject_p.h>
-#include <private/qqmlexpression_p.h>
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qmetaobject.h>
-#include <private/qmetaobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlEngineDebugService, qmlEngineDebugService)
-
-QQmlEngineDebugService *QQmlEngineDebugService::instance()
-{
- return qmlEngineDebugService();
-}
-
-QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QmlDebugger"), 2, parent),
- m_watch(new QQmlWatcher(this)),
- m_statesDelegate(0)
-{
- QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
- this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
-
- registerService();
-}
-
-QQmlEngineDebugService::~QQmlEngineDebugService()
-{
- delete m_statesDelegate;
-}
-
-QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectData &data)
-{
- ds << data.url << data.lineNumber << data.columnNumber << data.idString
- << data.objectName << data.objectType << data.objectId << data.contextId
- << data.parentId;
- return ds;
-}
-
-QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectData &data)
-{
- ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
- >> data.objectName >> data.objectType >> data.objectId >> data.contextId
- >> data.parentId;
- return ds;
-}
-
-QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectProperty &data)
-{
- ds << (int)data.type << data.name;
- // check first whether the data can be saved
- // (otherwise we assert in QVariant::operator<<)
- QByteArray buffer;
- QDataStream fakeStream(&buffer, QIODevice::WriteOnly);
- if (QMetaType::save(fakeStream, data.value.type(), data.value.constData()))
- ds << data.value;
- else
- ds << QVariant();
- ds << data.valueTypeName << data.binding << data.hasNotifySignal;
- return ds;
-}
-
-QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectProperty &data)
-{
- int type;
- ds >> type >> data.name >> data.value >> data.valueTypeName
- >> data.binding >> data.hasNotifySignal;
- data.type = (QQmlEngineDebugService::QQmlObjectProperty::Type)type;
- return ds;
-}
-
-static inline bool isSignalPropertyName(const QString &signalName)
-{
- // see QmlCompiler::isSignalPropertyName
- return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
- signalName.at(2).isLetter() && signalName.at(2).isUpper();
-}
-
-static bool hasValidSignal(QObject *object, const QString &propertyName)
-{
- if (!isSignalPropertyName(propertyName))
- return false;
-
- QString signalName = propertyName.mid(2);
- signalName[0] = signalName.at(0).toLower();
-
- int sigIdx = QQmlPropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex();
-
- if (sigIdx == -1)
- return false;
-
- return true;
-}
-
-QQmlEngineDebugService::QQmlObjectProperty
-QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
-{
- QQmlObjectProperty rv;
-
- QMetaProperty prop = obj->metaObject()->property(propIdx);
-
- rv.type = QQmlObjectProperty::Unknown;
- rv.valueTypeName = QString::fromUtf8(prop.typeName());
- rv.name = QString::fromUtf8(prop.name());
- rv.hasNotifySignal = prop.hasNotifySignal();
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(QQmlProperty(obj, rv.name));
- if (binding)
- rv.binding = binding->expression();
-
- if (QQmlValueTypeFactory::isValueType(prop.userType())) {
- rv.type = QQmlObjectProperty::Basic;
- } else if (QQmlMetaType::isQObject(prop.userType())) {
- rv.type = QQmlObjectProperty::Object;
- } else if (QQmlMetaType::isList(prop.userType())) {
- rv.type = QQmlObjectProperty::List;
- } else if (prop.userType() == QMetaType::QVariant) {
- rv.type = QQmlObjectProperty::Variant;
- }
-
- QVariant value;
- if (rv.type != QQmlObjectProperty::Unknown && prop.userType() != 0) {
- value = prop.read(obj);
- }
- rv.value = valueContents(value);
-
- return rv;
-}
-
-QVariant QQmlEngineDebugService::valueContents(QVariant value) const
-{
- // We can't send JS objects across the wire, so transform them to variant
- // maps for serialization.
- if (value.userType() == qMetaTypeId<QJSValue>())
- value = value.value<QJSValue>().toVariant();
- const int userType = value.userType();
-
- //QObject * is not streamable.
- //Convert all such instances to a String value
-
- if (value.type() == QVariant::List) {
- QVariantList contents;
- QVariantList list = value.toList();
- int count = list.size();
- for (int i = 0; i < count; i++)
- contents << valueContents(list.at(i));
- return contents;
- }
-
- if (value.type() == QVariant::Map) {
- QVariantMap contents;
- QMapIterator<QString, QVariant> i(value.toMap());
- while (i.hasNext()) {
- i.next();
- contents.insert(i.key(), valueContents(i.value()));
- }
- return contents;
- }
-
- if (QQmlValueTypeFactory::isValueType(userType)) {
- const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
- if (mo) {
- int toStringIndex = mo->indexOfMethod("toString");
- if (toStringIndex != -1) {
- QMetaMethod mm = mo->method(toStringIndex);
- QMetaType info(userType);
- QString s;
- if (info.flags() & QMetaType::IsGadget
- && mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
- return s;
- }
- }
-
- return value;
- }
-
- if (QQmlMetaType::isQObject(userType)) {
- QObject *o = QQmlMetaType::toQObject(value);
- if (o) {
- QString name = o->objectName();
- if (name.isEmpty())
- name = QStringLiteral("<unnamed object>");
- return name;
- }
- }
-
- return QString(QStringLiteral("<unknown value>"));
-}
-
-void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
- QObject *object, bool recur, bool dumpProperties)
-{
- message << objectData(object);
-
- QObjectList children = object->children();
-
- int childrenCount = children.count();
- for (int ii = 0; ii < children.count(); ++ii) {
- if (qobject_cast<QQmlContext*>(children[ii]))
- --childrenCount;
- }
-
- message << childrenCount << recur;
-
- QList<QQmlObjectProperty> fakeProperties;
-
- for (int ii = 0; ii < children.count(); ++ii) {
- QObject *child = children.at(ii);
- if (qobject_cast<QQmlContext*>(child))
- continue;
- if (recur)
- buildObjectDump(message, child, recur, dumpProperties);
- else
- message << objectData(child);
- }
-
- if (!dumpProperties) {
- message << 0;
- return;
- }
-
- QList<int> propertyIndexes;
- for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
- if (object->metaObject()->property(ii).isScriptable())
- propertyIndexes << ii;
- }
-
- QQmlData *ddata = QQmlData::get(object);
- if (ddata && ddata->signalHandlers) {
- QQmlAbstractBoundSignal *signalHandler = ddata->signalHandlers;
-
- while (signalHandler) {
- if (!dumpProperties) {
- signalHandler = signalHandler->m_nextSignal;
- continue;
- }
- QQmlObjectProperty prop;
- prop.type = QQmlObjectProperty::SignalProperty;
- prop.hasNotifySignal = false;
- QQmlBoundSignalExpression *expr = signalHandler->expression();
- if (expr) {
- prop.value = expr->expression();
- QObject *scope = expr->scopeObject();
- if (scope) {
- QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->index()).name());
- if (!methodName.isEmpty()) {
- prop.name = QLatin1String("on") + methodName[0].toUpper()
- + methodName.mid(1);
- }
- }
- }
- fakeProperties << prop;
-
- signalHandler = signalHandler->m_nextSignal;
- }
- }
-
- message << propertyIndexes.size() + fakeProperties.count();
-
- for (int ii = 0; ii < propertyIndexes.size(); ++ii)
- message << propertyData(object, propertyIndexes.at(ii));
-
- for (int ii = 0; ii < fakeProperties.count(); ++ii)
- message << fakeProperties[ii];
-}
-
-void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj)
-{
- qmlExecuteDeferred(obj);
-
- QObjectList children = obj->children();
- for (int ii = 0; ii < children.count(); ++ii) {
- QObject *child = children.at(ii);
- prepareDeferredObjects(child);
- }
-
-}
-
-void QQmlEngineDebugService::storeObjectIds(QObject *co)
-{
- QQmlDebugService::idForObject(co);
- QObjectList children = co->children();
- for (int ii = 0; ii < children.count(); ++ii)
- storeObjectIds(children.at(ii));
-}
-
-void QQmlEngineDebugService::buildObjectList(QDataStream &message,
- QQmlContext *ctxt,
- const QList<QPointer<QObject> > &instances)
-{
- QQmlContextData *p = QQmlContextData::get(ctxt);
-
- QString ctxtName = ctxt->objectName();
- int ctxtId = QQmlDebugService::idForObject(ctxt);
- if (ctxt->contextObject())
- storeObjectIds(ctxt->contextObject());
-
- message << ctxtName << ctxtId;
-
- int count = 0;
-
- QQmlContextData *child = p->childContexts;
- while (child) {
- ++count;
- child = child->nextChild;
- }
-
- message << count;
-
- child = p->childContexts;
- while (child) {
- buildObjectList(message, child->asQQmlContext(), instances);
- child = child->nextChild;
- }
-
- count = 0;
- for (int ii = 0; ii < instances.count(); ++ii) {
- QQmlData *data = QQmlData::get(instances.at(ii));
- if (data->context == p)
- count ++;
- }
- message << count;
-
- for (int ii = 0; ii < instances.count(); ++ii) {
- QQmlData *data = QQmlData::get(instances.at(ii));
- if (data->context == p)
- message << objectData(instances.at(ii));
- }
-}
-
-void QQmlEngineDebugService::buildStatesList(bool cleanList,
- const QList<QPointer<QObject> > &instances)
-{
- if (m_statesDelegate)
- m_statesDelegate->buildStatesList(cleanList, instances);
-}
-
-QQmlEngineDebugService::QQmlObjectData
-QQmlEngineDebugService::objectData(QObject *object)
-{
- QQmlData *ddata = QQmlData::get(object);
- QQmlObjectData rv;
- if (ddata && ddata->outerContext) {
- rv.url = ddata->outerContext->url();
- rv.lineNumber = ddata->lineNumber;
- rv.columnNumber = ddata->columnNumber;
- } else {
- rv.lineNumber = -1;
- rv.columnNumber = -1;
- }
-
- QQmlContext *context = qmlContext(object);
- if (context) {
- QQmlContextData *cdata = QQmlContextData::get(context);
- if (cdata)
- rv.idString = cdata->findObjectId(object);
- }
-
- rv.objectName = object->objectName();
- rv.objectId = QQmlDebugService::idForObject(object);
- rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
- rv.parentId = QQmlDebugService::idForObject(object->parent());
- QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
- if (type) {
- QString typeName = type->qmlTypeName();
- int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
- rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
- } else {
- rv.objectType = QString::fromUtf8(object->metaObject()->className());
- int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
- if (marker != -1)
- rv.objectType = rv.objectType.left(marker);
- }
-
- return rv;
-}
-
-void QQmlEngineDebugService::messageReceived(const QByteArray &message)
-{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
-}
-
-void QQmlEngineDebugService::processMessage(const QByteArray &message)
-{
- QQmlDebugStream ds(message);
-
- QByteArray type;
- int queryId;
- ds >> type >> queryId;
-
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
-
- if (type == "LIST_ENGINES") {
- rs << QByteArray("LIST_ENGINES_R");
- rs << queryId << m_engines.count();
-
- for (int ii = 0; ii < m_engines.count(); ++ii) {
- QQmlEngine *engine = m_engines.at(ii);
-
- QString engineName = engine->objectName();
- int engineId = QQmlDebugService::idForObject(engine);
-
- rs << engineName << engineId;
- }
-
- } else if (type == "LIST_OBJECTS") {
- int engineId = -1;
- ds >> engineId;
-
- QQmlEngine *engine =
- qobject_cast<QQmlEngine *>(QQmlDebugService::objectForId(engineId));
-
- rs << QByteArray("LIST_OBJECTS_R") << queryId;
-
- if (engine) {
- QQmlContext *rootContext = engine->rootContext();
- // Clean deleted objects
- QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext);
- for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
- if (!ctxtPriv->instances.at(ii)) {
- ctxtPriv->instances.removeAt(ii);
- --ii;
- }
- }
- buildObjectList(rs, rootContext, ctxtPriv->instances);
- buildStatesList(true, ctxtPriv->instances);
- }
-
- } else if (type == "FETCH_OBJECT") {
- int objectId;
- bool recurse;
- bool dumpProperties = true;
-
- ds >> objectId >> recurse >> dumpProperties;
-
- QObject *object = QQmlDebugService::objectForId(objectId);
-
- rs << QByteArray("FETCH_OBJECT_R") << queryId;
-
- if (object) {
- if (recurse)
- prepareDeferredObjects(object);
- buildObjectDump(rs, object, recurse, dumpProperties);
- }
-
- } else if (type == "FETCH_OBJECTS_FOR_LOCATION") {
- QString file;
- int lineNumber;
- int columnNumber;
- bool recurse;
- bool dumpProperties = true;
-
- ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
-
- QList<QObject*> objects = QQmlDebugService::objectForLocationInfo(
- file, lineNumber, columnNumber);
-
- rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
- << objects.count();
-
- foreach (QObject *object, objects) {
- if (recurse)
- prepareDeferredObjects(object);
- buildObjectDump(rs, object, recurse, dumpProperties);
- }
-
- } else if (type == "WATCH_OBJECT") {
- int objectId;
-
- ds >> objectId;
- bool ok = m_watch->addWatch(queryId, objectId);
-
- rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
-
- } else if (type == "WATCH_PROPERTY") {
- int objectId;
- QByteArray property;
-
- ds >> objectId >> property;
- bool ok = m_watch->addWatch(queryId, objectId, property);
-
- rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
-
- } else if (type == "WATCH_EXPR_OBJECT") {
- int debugId;
- QString expr;
-
- ds >> debugId >> expr;
- bool ok = m_watch->addWatch(queryId, debugId, expr);
-
- rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
-
- } else if (type == "NO_WATCH") {
- bool ok = m_watch->removeWatch(queryId);
-
- rs << QByteArray("NO_WATCH_R") << queryId << ok;
-
- } else if (type == "EVAL_EXPRESSION") {
- int objectId;
- QString expr;
-
- ds >> objectId >> expr;
- int engineId = -1;
- if (!ds.atEnd())
- ds >> engineId;
-
- QObject *object = QQmlDebugService::objectForId(objectId);
- QQmlContext *context = qmlContext(object);
- if (!context) {
- QQmlEngine *engine = qobject_cast<QQmlEngine *>(
- QQmlDebugService::objectForId(engineId));
- if (engine && m_engines.contains(engine))
- context = engine->rootContext();
- }
- QVariant result;
- if (context) {
- QQmlExpression exprObj(context, object, expr);
- bool undefined = false;
- QVariant value = exprObj.evaluate(&undefined);
- if (undefined)
- result = QString(QStringLiteral("<undefined>"));
- else
- result = valueContents(value);
- } else {
- result = QString(QStringLiteral("<unknown context>"));
- }
-
- rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
-
- } else if (type == "SET_BINDING") {
- int objectId;
- QString propertyName;
- QVariant expr;
- bool isLiteralValue;
- QString filename;
- int line;
- ds >> objectId >> propertyName >> expr >> isLiteralValue >>
- filename >> line;
- bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
- filename, line);
-
- rs << QByteArray("SET_BINDING_R") << queryId << ok;
-
- } else if (type == "RESET_BINDING") {
- int objectId;
- QString propertyName;
- ds >> objectId >> propertyName;
- bool ok = resetBinding(objectId, propertyName);
-
- rs << QByteArray("RESET_BINDING_R") << queryId << ok;
-
- } else if (type == "SET_METHOD_BODY") {
- int objectId;
- QString methodName;
- QString methodBody;
- ds >> objectId >> methodName >> methodBody;
- bool ok = setMethodBody(objectId, methodName, methodBody);
-
- rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
-
- }
- sendMessage(reply);
-}
-
-bool QQmlEngineDebugService::setBinding(int objectId,
- const QString &propertyName,
- const QVariant &expression,
- bool isLiteralValue,
- QString filename,
- int line,
- int column)
-{
- bool ok = true;
- QObject *object = objectForId(objectId);
- QQmlContext *context = qmlContext(object);
-
- if (object && context) {
- QQmlProperty property(object, propertyName, context);
- if (property.isValid()) {
-
- bool inBaseState = true;
- if (m_statesDelegate) {
- m_statesDelegate->updateBinding(context, property, expression, isLiteralValue,
- filename, line, column, &inBaseState);
- }
-
- if (inBaseState) {
- if (isLiteralValue) {
- property.write(expression);
- } else if (hasValidSignal(object, propertyName)) {
- QQmlBoundSignalExpression *qmlExpression = new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(property)->signalIndex(),
- QQmlContextData::get(context), object, expression.toString(),
- filename, line, column);
- QQmlPropertyPrivate::takeSignalExpression(property, qmlExpression);
- } else if (property.isProperty()) {
- QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);;
- binding->setTarget(property);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, binding);
- if (oldBinding)
- oldBinding->destroy();
- binding->update();
- } else {
- ok = false;
- qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
- }
- }
-
- } else {
- // not a valid property
- if (m_statesDelegate)
- ok = m_statesDelegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue);
- if (!ok)
- qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
- }
- }
- return ok;
-}
-
-bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyName)
-{
- QObject *object = objectForId(objectId);
- QQmlContext *context = qmlContext(object);
-
- if (object && context) {
- QString parentProperty = propertyName;
- if (propertyName.indexOf(QLatin1Char('.')) != -1)
- parentProperty = propertyName.left(propertyName.indexOf(QLatin1Char('.')));
-
- if (object->property(parentProperty.toLatin1()).isValid()) {
- QQmlProperty property(object, propertyName);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(property);
- if (oldBinding) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, 0);
- if (oldBinding)
- oldBinding->destroy();
- }
- if (property.isResettable()) {
- // Note: this will reset the property in any case, without regard to states
- // Right now almost no QQuickItem has reset methods for its properties (with the
- // notable exception of QQuickAnchors), so this is not a big issue
- // later on, setBinding does take states into account
- property.reset();
- } else {
- // overwrite with default value
- if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) {
- if (QObject *emptyObject = objType->create()) {
- if (emptyObject->property(parentProperty.toLatin1()).isValid()) {
- QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
- if (defaultValue.isValid()) {
- setBinding(objectId, propertyName, defaultValue, true);
- }
- }
- delete emptyObject;
- }
- }
- }
- return true;
- }
-
- if (hasValidSignal(object, propertyName)) {
- QQmlProperty property(object, propertyName, context);
- QQmlPropertyPrivate::setSignalExpression(property, 0);
- return true;
- }
-
- if (m_statesDelegate) {
- m_statesDelegate->resetBindingForInvalidProperty(object, propertyName);
- return true;
- }
-
- return false;
- }
- // object or context null.
- return false;
-}
-
-bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
-{
- QObject *object = objectForId(objectId);
- QQmlContext *context = qmlContext(object);
- if (!object || !context || !context->engine())
- return false;
- QQmlContextData *contextData = QQmlContextData::get(context);
- if (!contextData)
- return false;
-
- QQmlPropertyData dummy;
- QQmlPropertyData *prop =
- QQmlPropertyCache::property(context->engine(), object, method, contextData, dummy);
-
- if (!prop || !prop->isVMEFunction())
- return false;
-
- QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
- QList<QByteArray> paramNames = metaMethod.parameterNames();
-
- QString paramStr;
- for (int ii = 0; ii < paramNames.count(); ++ii) {
- if (ii != 0) paramStr.append(QLatin1Char(','));
- paramStr.append(QString::fromUtf8(paramNames.at(ii)));
- }
-
- QString jsfunction = QLatin1String("(function ") + method + QLatin1Char('(') + paramStr +
- QLatin1String(") {");
- jsfunction += body;
- jsfunction += QLatin1String("\n})");
-
- QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
-
- int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
- QV4::Scope scope(v4);
- QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
- vmeMetaObject->setVmeMethod(prop->coreIndex, v);
- return true;
-}
-
-void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
-{
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
-
- rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
-
- sendMessage(reply);
-}
-
-void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_ASSERT(engine);
- Q_ASSERT(!m_engines.contains(engine));
-
- m_engines.append(engine);
- emit attachedToEngine(engine);
-}
-
-void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- Q_ASSERT(engine);
- Q_ASSERT(m_engines.contains(engine));
-
- m_engines.removeAll(engine);
- emit detachedFromEngine(engine);
-}
-
-void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
-{
- Q_ASSERT(engine);
- Q_ASSERT(m_engines.contains(engine));
-
- int engineId = QQmlDebugService::idForObject(engine);
- int objectId = QQmlDebugService::idForObject(object);
- int parentId = QQmlDebugService::idForObject(object->parent());
-
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
-
- //unique queryId -1
- rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
- sendMessage(reply);
-}
-
-void QQmlEngineDebugService::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
-{
- m_statesDelegate = delegate;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
deleted file mode 100644
index 0a824b132f..0000000000
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLENGINEDEBUGSERVICE_P_H
-#define QQMLENGINEDEBUGSERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qqmldebugservice_p.h>
-
-#include <QtCore/qurl.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/QPointer>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlEngine;
-class QQmlContext;
-class QQmlWatcher;
-class QDataStream;
-class QQmlDebugStatesDelegate;
-
-class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService
-{
- Q_OBJECT
-public:
- QQmlEngineDebugService(QObject * = 0);
- ~QQmlEngineDebugService();
-
- struct QQmlObjectData {
- QUrl url;
- int lineNumber;
- int columnNumber;
- QString idString;
- QString objectName;
- QString objectType;
- int objectId;
- int contextId;
- int parentId;
- };
-
- struct QQmlObjectProperty {
- enum Type { Unknown, Basic, Object, List, SignalProperty, Variant };
- Type type;
- QString name;
- QVariant value;
- QString valueTypeName;
- QString binding;
- bool hasNotifySignal;
- };
-
- void engineAboutToBeAdded(QQmlEngine *);
- void engineAboutToBeRemoved(QQmlEngine *);
- void objectCreated(QQmlEngine *, QObject *);
-
- void setStatesDelegate(QQmlDebugStatesDelegate *);
-
- static QQmlEngineDebugService *instance();
-
-protected:
- virtual void messageReceived(const QByteArray &);
-
-private Q_SLOTS:
- void processMessage(const QByteArray &msg);
- void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
-
-private:
- void prepareDeferredObjects(QObject *);
- void buildObjectList(QDataStream &, QQmlContext *,
- const QList<QPointer<QObject> > &instances);
- void buildObjectDump(QDataStream &, QObject *, bool, bool);
- void buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances);
- QQmlObjectData objectData(QObject *);
- QQmlObjectProperty propertyData(QObject *, int);
- QVariant valueContents(QVariant defaultValue) const;
- bool setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1, int column = 0);
- bool resetBinding(int objectId, const QString &propertyName);
- bool setMethodBody(int objectId, const QString &method, const QString &body);
- void storeObjectIds(QObject *co);
-
- QList<QQmlEngine *> m_engines;
- QQmlWatcher *m_watch;
- QQmlDebugStatesDelegate *m_statesDelegate;
-};
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectProperty &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectProperty &);
-
-QT_END_NAMESPACE
-
-#endif // QQMLENGINEDEBUGSERVICE_P_H
-
diff --git a/src/qml/debugger/qqmlinspectorinterface_p.h b/src/qml/debugger/qqmlinspectorinterface_p.h
deleted file mode 100644
index 9b29d383c7..0000000000
--- a/src/qml/debugger/qqmlinspectorinterface_p.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLINSPECTORINTERFACE_H
-#define QQMLINSPECTORINTERFACE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorInterface
-{
-public:
- QQmlInspectorInterface() {}
- virtual ~QQmlInspectorInterface() {}
-
- virtual bool canHandleView(QObject *view) = 0;
-
- virtual void activate(QObject *view) = 0;
- virtual void deactivate() = 0;
-
- virtual void clientMessage(const QByteArray &message) = 0;
-};
-
-#define QQmlInspectorInterface_iid "org.qt-project.Qt.QQmlInspectorInterface"
-
-Q_DECLARE_INTERFACE(QQmlInspectorInterface, QQmlInspectorInterface_iid)
-
-QT_END_NAMESPACE
-
-#endif // QQMLINSPECTORINTERFACE_H
diff --git a/src/qml/debugger/qqmlinspectorservice.cpp b/src/qml/debugger/qqmlinspectorservice.cpp
deleted file mode 100644
index 5a8c4487d9..0000000000
--- a/src/qml/debugger/qqmlinspectorservice.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlinspectorservice_p.h"
-#include "qqmlinspectorinterface_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlInspectorService, serviceInstance)
-
-QQmlInspectorService::QQmlInspectorService()
- : QQmlDebugService(QStringLiteral("QmlInspector"), 1)
- , m_currentInspectorPlugin(0)
-{
- registerService();
-}
-
-QQmlInspectorService *QQmlInspectorService::instance()
-{
- return serviceInstance();
-}
-
-void QQmlInspectorService::addView(QObject *view)
-{
- m_views.append(view);
- updateState();
-}
-
-void QQmlInspectorService::removeView(QObject *view)
-{
- m_views.removeAll(view);
- updateState();
-}
-
-void QQmlInspectorService::sendMessage(const QByteArray &message)
-{
- if (state() != Enabled)
- return;
-
- QQmlDebugService::sendMessage(message);
-}
-
-void QQmlInspectorService::stateChanged(State /*state*/)
-{
- QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
-}
-
-void QQmlInspectorService::updateState()
-{
- if (m_views.isEmpty()) {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- return;
- }
-
- if (state() == Enabled) {
- if (m_inspectorPlugins.isEmpty())
- loadInspectorPlugins();
-
- if (m_inspectorPlugins.isEmpty()) {
- qWarning() << "QQmlInspector: No plugins found.";
- QQmlDebugServer::instance()->removeService(this);
- return;
- }
-
- m_currentInspectorPlugin = 0;
- foreach (QQmlInspectorInterface *inspector, m_inspectorPlugins) {
- if (inspector->canHandleView(m_views.first())) {
- m_currentInspectorPlugin = inspector;
- break;
- }
- }
-
- if (!m_currentInspectorPlugin) {
- qWarning() << "QQmlInspector: No plugin available for view '" << m_views.first()->metaObject()->className() << "'.";
- return;
- }
- m_currentInspectorPlugin->activate(m_views.first());
- } else {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- }
-}
-
-void QQmlInspectorService::messageReceived(const QByteArray &message)
-{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
-}
-
-void QQmlInspectorService::processMessage(const QByteArray &message)
-{
- if (m_currentInspectorPlugin)
- m_currentInspectorPlugin->clientMessage(message);
-}
-
-void QQmlInspectorService::loadInspectorPlugins()
-{
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists())
- foreach (const QString &pluginPath, dir.entryList(QDir::Files))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
-
- foreach (const QString &pluginPath, pluginCandidates) {
- if (pluginPath.contains(QLatin1String("qmldbg_tcp")))
- continue;
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Trying to load plugin " << pluginPath << "...";
-
- QPluginLoader loader(pluginPath);
- if (!loader.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Error while loading: " << loader.errorString();
-
- continue;
- }
-
- QQmlInspectorInterface *inspector =
- qobject_cast<QQmlInspectorInterface*>(loader.instance());
- if (inspector) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin successfully loaded.";
- m_inspectorPlugins << inspector;
- } else {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin does not implement interface QQmlInspectorInterface.";
-
- loader.unload();
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index b35da8a714..a6423d769a 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -32,88 +32,13 @@
****************************************************************************/
#include "qqmlprofiler_p.h"
-#include "qqmlprofilerservice_p.h"
#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-// convert to QByteArrays that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
-{
- QByteArray data;
- Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
- if ((messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
- if ((detailType & (1 << decodedDetailType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << decodedMessageType << decodedDetailType;
-
- switch (decodedMessageType) {
- case QQmlProfilerDefinitions::RangeStart:
- if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
- ds << QQmlProfilerDefinitions::QmlBinding;
- break;
- case QQmlProfilerDefinitions::RangeData:
- ds << detailString;
- break;
- case QQmlProfilerDefinitions::RangeLocation:
- ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
- break;
- case QQmlProfilerDefinitions::RangeEnd: break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
- }
- messages << data;
- data.clear();
- }
- }
-}
-
-QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
- QQmlAbstractProfilerAdapter(service)
-{
- engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()),
- engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QQmlProfilerData>)),
- this, SLOT(receiveData(QList<QQmlProfilerData>)));
-}
-
-qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- while (!data.empty() && data.front().time <= until) {
- data.front().toByteArrays(messages);
- data.pop_front();
- }
- return data.empty() ? -1 : data.front().time;
-}
-
-void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
-{
- data = new_data;
- service->dataReady(this);
-}
-
-
QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
{
- static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
+ static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >();
Q_UNUSED(metatype);
m_timer.start();
}
@@ -127,16 +52,12 @@ void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
reportData();
- m_data.clear();
}
void QQmlProfiler::reportData()
{
- QList<QQmlProfilerData> result;
- result.reserve(m_data.size());
- for (int i = 0; i < m_data.size(); ++i)
- result.append(m_data[i]);
- emit dataReady(result);
+ emit dataReady(m_data);
+ m_data.clear();
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 5c994b112f..3c8337c969 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -68,8 +68,9 @@ QT_BEGIN_NAMESPACE
// This struct is somewhat dangerous to use:
// The messageType is a bit field. You can pack multiple messages into
// one object, e.g. RangeStart and RangeLocation. Each one will be read
-// independently by toByteArrays. Thus you can only pack messages if their data
-// doesn't overlap. It's up to you to figure that out.
+// independently when converting to QByteArrays. Thus you can only pack
+// messages if their data doesn't overlap. It's up to you to figure that
+// out.
struct Q_AUTOTEST_EXPORT QQmlProfilerData
{
QQmlProfilerData() {}
@@ -103,8 +104,6 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData
int x; //used by RangeLocation
int y; //used by RangeLocation
-
- void toByteArrays(QList<QByteArray> &messages) const;
};
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
@@ -171,24 +170,11 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QQmlProfilerData> &);
+ void dataReady(const QVector<QQmlProfilerData> &);
protected:
QElapsedTimer m_timer;
- QVarLengthArray<QQmlProfilerData> m_data;
-};
-
-class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
- Q_OBJECT
-public:
- QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-
-public slots:
- void receiveData(const QList<QQmlProfilerData> &new_data);
-
-private:
- QList<QQmlProfilerData> data;
+ QVector<QQmlProfilerData> m_data;
};
//
@@ -332,6 +318,6 @@ private:
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QQmlProfilerData>)
+Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
#endif // QQMLPROFILER_P_H
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
deleted file mode 100644
index 85556836e6..0000000000
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugserver_p.h"
-#include "qv4profileradapter_p.h"
-#include "qqmlprofiler_p.h"
-#include <private/qqmlengine_p.h>
-
-#include <QtCore/qdatastream.h>
-#include <QtCore/qurl.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qthread.h>
-#include <QtCore/qcoreapplication.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
-
-QQmlProfilerService::QQmlProfilerService()
- : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
-{
- m_timer.start();
-
- QMutexLocker lock(configMutex());
- // If there is no debug server it doesn't matter as we'll never get enabled anyway.
- if (QQmlDebugServer::instance() != 0)
- moveToThread(QQmlDebugServer::instance()->thread());
-}
-
-QQmlProfilerService::~QQmlProfilerService()
-{
- // No need to lock here. If any engine or global profiler is still trying to register at this
- // point we have a nasty bug anyway.
- qDeleteAll(m_engineProfilers.values());
- qDeleteAll(m_globalProfilers);
-}
-
-void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
-{
- QMutexLocker lock(configMutex());
- bool dataComplete = true;
- for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) {
- if (i.value() == profiler) {
- m_startTimes.erase(i++);
- } else {
- if (i.key() == -1)
- dataComplete = false;
- ++i;
- }
- }
- m_startTimes.insert(0, profiler);
- if (dataComplete) {
- QList<QQmlEngine *> enginesToRelease;
- foreach (QQmlEngine *engine, m_stoppingEngines) {
- foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers.values(engine)) {
- if (m_startTimes.values().contains(engineProfiler)) {
- enginesToRelease.append(engine);
- break;
- }
- }
- }
- sendMessages();
- foreach (QQmlEngine *engine, enginesToRelease) {
- m_stoppingEngines.removeOne(engine);
- emit detachedFromEngine(engine);
- }
- }
-}
-
-QQmlProfilerService *QQmlProfilerService::instance()
-{
- // just make sure that the service is properly registered
- return profilerInstance();
-}
-
-void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
-
- QMutexLocker lock(configMutex());
- QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
- QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
- addEngineProfiler(qmlAdapter, engine);
- addEngineProfiler(v4Adapter, engine);
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
-}
-
-void QQmlProfilerService::engineAdded(QQmlEngine *engine)
-{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
-
- QMutexLocker lock(configMutex());
- foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine))
- profiler->stopWaiting();
-}
-
-void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
-
- QMutexLocker lock(configMutex());
- bool isRunning = false;
- foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
- if (profiler->isRunning())
- isRunning = true;
- profiler->startWaiting();
- }
- if (isRunning) {
- m_stoppingEngines.append(engine);
- stopProfiling(engine);
- } else {
- emit detachedFromEngine(engine);
- }
-}
-
-void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
-{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
-
- QMutexLocker lock(configMutex());
- foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
- removeProfilerFromStartTimes(profiler);
- delete profiler;
- }
- m_engineProfilers.remove(engine);
-}
-
-void QQmlProfilerService::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
-{
- profiler->moveToThread(thread());
- profiler->synchronize(m_timer);
- m_engineProfilers.insert(engine, profiler);
-}
-
-void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
-{
- QMutexLocker lock(configMutex());
- profiler->synchronize(m_timer);
- m_globalProfilers.append(profiler);
- // Global profiler, not connected to a specific engine.
- // Global profilers are started whenever any engine profiler is started and stopped when
- // all engine profilers are stopped.
- quint64 features = 0;
- foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers)
- features |= engineProfiler->features();
-
- if (features != 0)
- profiler->startProfiling(features);
-}
-
-void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
-{
- QMutexLocker lock(configMutex());
- removeProfilerFromStartTimes(profiler);
- m_globalProfilers.removeOne(profiler);
- delete profiler;
-}
-
-void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
-{
- for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin());
- i != m_startTimes.end();) {
- if (i.value() == profiler) {
- m_startTimes.erase(i++);
- break;
- } else {
- ++i;
- }
- }
-}
-
-/*!
- * Start profiling the given \a engine. If \a engine is 0, start all engine profilers that aren't
- * currently running.
- *
- * If any engine profiler is started like that also start all global profilers.
- */
-void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
-{
- QMutexLocker lock(configMutex());
-
- QByteArray message;
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
-
- d << m_timer.nsecsElapsed() << (int)Event << (int)StartTrace;
- bool startedAny = false;
- if (engine != 0) {
- foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
- if (!profiler->isRunning()) {
- profiler->startProfiling(features);
- startedAny = true;
- }
- }
- if (startedAny)
- d << idForObject(engine);
- } else {
- QSet<QQmlEngine *> engines;
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
- i != m_engineProfilers.end(); ++i) {
- if (!i.value()->isRunning()) {
- engines << i.key();
- i.value()->startProfiling(features);
- startedAny = true;
- }
- }
- foreach (QQmlEngine *profiledEngine, engines)
- d << idForObject(profiledEngine);
- }
-
- if (startedAny) {
- foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
- if (!profiler->isRunning())
- profiler->startProfiling(features);
- }
- }
-
- QQmlDebugService::sendMessage(message);
-}
-
-/*!
- * Stop profiling the given \a engine. If \a engine is 0, stop all currently running engine
- * profilers.
- *
- * If afterwards no more engine profilers are running, also stop all global profilers. Otherwise
- * only make them report their data.
- */
-void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
-{
- QMutexLocker lock(configMutex());
- QList<QQmlAbstractProfilerAdapter *> stopping;
- QList<QQmlAbstractProfilerAdapter *> reporting;
-
- bool stillRunning = false;
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
- i != m_engineProfilers.end(); ++i) {
- if (i.value()->isRunning()) {
- if (engine == 0 || i.key() == engine) {
- m_startTimes.insert(-1, i.value());
- stopping << i.value();
- } else {
- stillRunning = true;
- }
- }
- }
-
- foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
- if (!profiler->isRunning())
- continue;
- m_startTimes.insert(-1, profiler);
- if (stillRunning) {
- reporting << profiler;
- } else {
- stopping << profiler;
- }
- }
-
- foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
- profiler->reportData();
-
- foreach (QQmlAbstractProfilerAdapter *profiler, stopping)
- profiler->stopProfiling();
-}
-
-/*
- Send the queued up messages.
-*/
-void QQmlProfilerService::sendMessages()
-{
- QList<QByteArray> messages;
-
- QByteArray data;
- QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
- traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
-
- QSet<QQmlEngine *> seen;
- foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
- i != m_engineProfilers.end(); ++i) {
- if (i.value() == profiler && !seen.contains(i.key())) {
- seen << i.key();
- traceEnd << idForObject(i.key());
- }
- }
- }
-
- while (!m_startTimes.empty()) {
- QQmlAbstractProfilerAdapter *first = m_startTimes.begin().value();
- m_startTimes.erase(m_startTimes.begin());
- if (!m_startTimes.empty()) {
- qint64 next = first->sendMessages(m_startTimes.begin().key(), messages);
- if (next != -1)
- m_startTimes.insert(next, first);
- } else {
- first->sendMessages(std::numeric_limits<qint64>::max(), messages);
- }
- }
-
- //indicate completion
- messages << data;
- data.clear();
-
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (qint64)-1 << (int)Complete;
- messages << data;
-
- QQmlDebugService::sendMessages(messages);
-}
-
-void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
-{
- QMutexLocker lock(configMutex());
-
- if (state() == newState)
- return;
-
- // Stop all profiling and send the data before we get disabled.
- if (newState != Enabled) {
- foreach (QQmlEngine *engine, m_engineProfilers.keys())
- stopProfiling(engine);
- }
-}
-
-void QQmlProfilerService::messageReceived(const QByteArray &message)
-{
- QMutexLocker lock(configMutex());
-
- QByteArray rwData = message;
- QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
-
- int engineId = -1;
- quint64 features = std::numeric_limits<quint64>::max();
- bool enabled;
- stream >> enabled;
- if (!stream.atEnd())
- stream >> engineId;
- if (!stream.atEnd())
- stream >> features;
-
- // If engineId == -1 objectForId() and then the cast will return 0.
- if (enabled)
- startProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)), features);
- else
- stopProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
-
- stopWaiting();
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
deleted file mode 100644
index 978d8413a7..0000000000
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLPROFILERSERVICE_P_H
-#define QQMLPROFILERSERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlprofilerdefinitions_p.h"
-#include "qqmlabstractprofileradapter_p.h"
-
-#include <private/qqmlboundsignal_p.h>
-
-#include <QtCore/qelapsedtimer.h>
-#include <QtCore/qmetaobject.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qstringbuilder.h>
-#include <QtCore/qwaitcondition.h>
-
-#include <limits>
-
-QT_BEGIN_NAMESPACE
-
-class QUrl;
-class QQmlEngine;
-
-
-class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlConfigurableDebugService, public QQmlProfilerDefinitions
-{
- Q_OBJECT
-public:
-
- static QQmlProfilerService *instance();
- void engineAboutToBeAdded(QQmlEngine *engine);
- void engineAboutToBeRemoved(QQmlEngine *engine);
- void engineAdded(QQmlEngine *engine);
- void engineRemoved(QQmlEngine *engine);
-
- void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
- void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
-
- void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits<quint64>::max());
- void stopProfiling(QQmlEngine *engine);
-
- QQmlProfilerService();
- ~QQmlProfilerService();
-
- void dataReady(QQmlAbstractProfilerAdapter *profiler);
-
-protected:
- virtual void stateAboutToBeChanged(State state);
- virtual void messageReceived(const QByteArray &);
-
-private:
-
- void sendMessages();
- void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
- void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
-
- QElapsedTimer m_timer;
-
- QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
- QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
- QList<QQmlEngine *> m_stoppingEngines;
- QMultiMap<qint64, QQmlAbstractProfilerAdapter *> m_startTimes;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLPROFILERSERVICE_P_H
-
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
deleted file mode 100644
index cefb29e031..0000000000
--- a/src/qml/debugger/qv4debugservice.cpp
+++ /dev/null
@@ -1,1265 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4debugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-#include "qqmlengine.h"
-#include "qv4debugging_p.h"
-#include "qv4engine_p.h"
-#include "qv4function_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qv8engine_p.h>
-
-#include <QtCore/QJsonArray>
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonValue>
-
-const char *V4_CONNECT = "connect";
-const char *V4_DISCONNECT = "disconnect";
-const char *V4_BREAK_ON_SIGNAL = "breakonsignal";
-const char *V4_ADD_BREAKPOINT = "addBreakpoint";
-const char *V4_REMOVE_BREAKPOINT = "removeBreakpoint";
-const char *V4_PAUSE = "interrupt";
-const char *V4_ALL = "all";
-const char *V4_BREAK = "break";
-
-const char *V4_FILENAME = "filename";
-const char *V4_LINENUMBER = "linenumber";
-
-#define NO_PROTOCOL_TRACING
-#ifdef NO_PROTOCOL_TRACING
-# define TRACE_PROTOCOL(x)
-#else
-#include <QtCore/QDebug>
-# define TRACE_PROTOCOL(x) x
-#endif
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QV4DebugService, v4ServiceInstance)
-
-class QV4DebugServicePrivate;
-
-class QV4DebuggerAgent : public QV4::Debugging::DebuggerAgent
-{
-public:
- QV4DebuggerAgent(QV4DebugServicePrivate *debugServicePrivate)
- : debugServicePrivate(debugServicePrivate)
- {}
-
- QV4::Debugging::Debugger *firstDebugger() const
- {
- // Currently only 1 single engine is supported, so:
- if (m_debuggers.isEmpty())
- return 0;
- else
- return m_debuggers.first();
- }
-
- bool isRunning() const
- {
- // Currently only 1 single engine is supported, so:
- if (QV4::Debugging::Debugger *debugger = firstDebugger())
- return debugger->state() == QV4::Debugging::Debugger::Running;
- else
- return false;
- }
-
-public slots:
- virtual void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason);
- virtual void sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr);
-
-private:
- QV4DebugServicePrivate *debugServicePrivate;
-};
-
-class V8CommandHandler;
-class UnknownV8CommandHandler;
-
-class VariableCollector: public QV4::Debugging::Debugger::Collector
-{
-public:
- VariableCollector(QV4::ExecutionEngine *engine)
- : Collector(engine)
- , destination(0)
- {}
-
- virtual ~VariableCollector() {}
-
- void collectScope(QJsonArray *dest, QV4::Debugging::Debugger *debugger, int frameNr, int scopeNr)
- {
- qSwap(destination, dest);
- bool oldIsProp = isProperty();
- setIsProperty(true);
- debugger->collectArgumentsInContext(this, frameNr, scopeNr);
- debugger->collectLocalsInContext(this, frameNr, scopeNr);
- setIsProperty(oldIsProp);
- qSwap(destination, dest);
- }
-
- void setDestination(QJsonArray *dest)
- { destination = dest; }
-
- QJsonArray retrieveRefsToInclude()
- {
- QJsonArray result;
- qSwap(refsToInclude, result);
- return result;
- }
-
- QJsonValue lookup(int handle, bool addRefs = true)
- {
- if (handle < 0)
- handle = -handle;
-
- if (addRefs)
- foreach (int ref, refsByHandle[handle])
- refsToInclude.append(lookup(ref, false));
- return refs[handle];
- }
-
- QJsonObject makeRef(int refId)
- {
- QJsonObject ref;
- ref[QLatin1String("ref")] = refId;
- return ref;
- }
-
- QJsonObject addFunctionRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("function");
- func[QLatin1String("className")] = QStringLiteral("Function");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addScriptRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("script");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addObjectRef(QJsonObject obj, bool anonymous)
- {
- int ref = newRefId();
-
- if (anonymous)
- ref = -ref;
- obj[QLatin1String("handle")] = ref;
- obj[QLatin1String("type")] = QStringLiteral("object");
- insertRef(obj, ref);
- QSet<int> used;
- qSwap(usedRefs, used);
- refsByHandle.insert(ref, used);
-
- return makeRef(ref);
- }
-
-protected:
- virtual void addUndefined(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("undefined"));
- }
-
- virtual void addNull(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("null"));
- }
-
- virtual void addBoolean(const QString &name, bool value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("boolean"));
- }
-
- virtual void addString(const QString &name, const QString &value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("string"));
- }
-
- virtual void addObject(const QString &name, const QV4::Value &value)
- {
- QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
-
- int ref = cachedObjectRef(obj);
- if (ref != -1) {
- addNameRefPair(name, ref);
- } else {
- int ref = newRefId();
- cacheObjectRef(obj, ref);
-
- QJsonArray properties, *prev = &properties;
- QSet<int> used;
- qSwap(usedRefs, used);
- qSwap(destination, prev);
- collect(obj);
- qSwap(destination, prev);
- qSwap(usedRefs, used);
-
- QJsonObject o;
- o[QLatin1String("properties")] = properties;
- addHandle(name, o, QStringLiteral("object"), ref);
- refsByHandle.insert(ref, used);
- }
- }
-
- virtual void addInteger(const QString &name, int value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
- virtual void addDouble(const QString &name, double value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
-private:
- int addHandle(const QString &name, QJsonObject object, const QString &type, int suppliedRef = -1)
- {
- Q_ASSERT(destination);
-
- object[QLatin1String("type")] = type;
-
- QJsonDocument tmp;
- tmp.setObject(object);
- QByteArray key = tmp.toJson(QJsonDocument::Compact);
-
- int ref;
- if (suppliedRef == -1) {
- ref = refCache.value(key, -1);
- if (ref == -1) {
- ref = newRefId();
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
- } else {
- ref = suppliedRef;
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
-
- addNameRefPair(name, ref);
- return ref;
- }
-
- void addNameRefPair(const QString &name, int ref)
- {
- QJsonObject nameValuePair;
- nameValuePair[QLatin1String("name")] = name;
- if (isProperty()) {
- nameValuePair[QLatin1String("ref")] = ref;
- } else {
- QJsonObject refObj;
- refObj[QLatin1String("ref")] = ref;
- nameValuePair[QLatin1String("value")] = refObj;
- }
- destination->append(nameValuePair);
- usedRefs.insert(ref);
- }
-
- int newRefId()
- {
- int ref = refs.count();
- refs.insert(ref, QJsonValue());
- return ref;
- }
-
- void insertRef(const QJsonValue &value, int refId)
- {
- if (refId < 0)
- refId = -refId;
-
- refs.insert(refId, value);
- refsToInclude.append(value);
- }
-
- void cacheObjectRef(QV4::Value obj, int ref)
- {
- objectRefs.insert(obj.val, ref);
- }
-
- int cachedObjectRef(QV4::Value obj) const
- {
- return objectRefs.value(obj.val, -1);
- }
-
-private:
- QJsonArray refsToInclude;
- QHash<int, QJsonValue> refs;
- QHash<QByteArray, int> refCache;
- QJsonArray *destination;
- QSet<int> usedRefs;
- QHash<int, QSet<int> > refsByHandle;
- QHash<quint64, int> objectRefs;
-};
-
-class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QV4DebugService)
-
-public:
- QV4DebugServicePrivate();
- ~QV4DebugServicePrivate() { qDeleteAll(handlers.values()); }
-
- static QByteArray packMessage(const QByteArray &command, const QByteArray &message = QByteArray())
- {
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
- static const QByteArray cmd("V8DEBUG");
- rs << cmd << command << message;
- return reply;
- }
-
- void send(QJsonObject v8Payload)
- {
- v8Payload[QLatin1String("seq")] = sequence++;
- QJsonDocument doc;
- doc.setObject(v8Payload);
-#ifdef NO_PROTOCOL_TRACING
- QByteArray responseData = doc.toJson(QJsonDocument::Compact);
-#else
- QByteArray responseData = doc.toJson(QJsonDocument::Indented);
-#endif
-
- TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData << endl);
-
- q_func()->sendMessage(packMessage("v8message", responseData));
- }
-
- void processCommand(const QByteArray &command, const QByteArray &data);
-
- QV4DebuggerAgent debuggerAgent;
-
- QStringList breakOnSignals;
- QMap<int, QV4::Debugging::Debugger *> debuggerMap;
- static int debuggerIndex;
- static int sequence;
- const int version;
-
- V8CommandHandler *v8CommandHandler(const QString &command) const;
-
- void clearHandles(QV4::ExecutionEngine *engine)
- {
- theCollector.reset(new VariableCollector(engine));
- }
-
- QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::Debugger *debugger)
- {
- QJsonObject frame;
- frame[QLatin1String("index")] = frameNr;
- frame[QLatin1String("debuggerFrame")] = false;
- frame[QLatin1String("func")] = theCollector->addFunctionRef(stackFrame.function);
- frame[QLatin1String("script")] = theCollector->addScriptRef(stackFrame.source);
- frame[QLatin1String("line")] = stackFrame.line - 1;
- if (stackFrame.column >= 0)
- frame[QLatin1String("column")] = stackFrame.column;
-
- QJsonArray properties;
- theCollector->setDestination(&properties);
- if (debugger->collectThisInContext(theCollector.data(), frameNr)) {
- QJsonObject obj;
- obj[QLatin1String("properties")] = properties;
- frame[QLatin1String("receiver")] = theCollector->addObjectRef(obj, false);
- }
-
- QJsonArray scopes;
- // Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
- int type = encodeScopeType(scopeTypes[i]);
- if (type == -1)
- continue;
-
- QJsonObject scope;
- scope[QLatin1String("index")] = i;
- scope[QLatin1String("type")] = type;
- scopes.push_back(scope);
- }
- frame[QLatin1String("scopes")] = scopes;
-
- return frame;
- }
-
- int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
- {
- switch (scopeType) {
- case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- break;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
- break;
- case QV4::Heap::ExecutionContext::Type_WithContext:
- return 2;
- break;
- case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
- case QV4::Heap::ExecutionContext::Type_CallContext:
- return 1;
- break;
- case QV4::Heap::ExecutionContext::Type_QmlContext:
- default:
- return -1;
- }
- }
-
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger)
- {
- QJsonObject scope;
-
- QJsonArray properties;
- theCollector->collectScope(&properties, debugger, frameNr, scopeNr);
-
- QJsonObject anonymous;
- anonymous[QLatin1String("properties")] = properties;
-
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
- scope[QLatin1String("index")] = scopeNr;
- scope[QLatin1String("frameIndex")] = frameNr;
- scope[QLatin1String("object")] = theCollector->addObjectRef(anonymous, true);
-
- return scope;
- }
-
- QJsonValue lookup(int refId) const { return theCollector->lookup(refId); }
-
- QJsonArray buildRefs()
- {
- return theCollector->retrieveRefsToInclude();
- }
-
- VariableCollector *collector() const
- {
- return theCollector.data();
- }
-
- void selectFrame(int frameNr)
- { theSelectedFrame = frameNr; }
-
- int selectedFrame() const
- { return theSelectedFrame; }
-
-private:
- QScopedPointer<VariableCollector> theCollector;
- int theSelectedFrame;
-
- void addHandler(V8CommandHandler* handler);
- QHash<QString, V8CommandHandler*> handlers;
- QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
-};
-
-int QV4DebugServicePrivate::debuggerIndex = 0;
-int QV4DebugServicePrivate::sequence = 0;
-
-class V8CommandHandler
-{
-public:
- V8CommandHandler(const QString &command)
- : cmd(command)
- {}
-
- virtual ~V8CommandHandler()
- {}
-
- QString command() const { return cmd; }
-
- void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
- {
- TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
-
- req = request;
- seq = req.value(QStringLiteral("seq"));
- debugService = s;
- debugServicePrivate = p;
-
- handleRequest();
- if (!response.isEmpty()) {
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
- }
-
- debugServicePrivate = 0;
- debugService = 0;
- seq = QJsonValue();
- req = QJsonObject();
- response = QJsonObject();
- }
-
- virtual void handleRequest() = 0;
-
-protected:
- void addCommand() { response.insert(QStringLiteral("command"), cmd); }
- void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
- void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
- void addBody(const QJsonObject &body)
- {
- response.insert(QStringLiteral("body"), body);
- }
-
- void addRunning()
- {
- response.insert(QStringLiteral("running"), debugServicePrivate->debuggerAgent.isRunning());
- }
-
- void addRefs()
- {
- response.insert(QStringLiteral("refs"), debugServicePrivate->buildRefs());
- }
-
- void createErrorResponse(const QString &msg)
- {
- QJsonValue command = req.value(QStringLiteral("command"));
- response.insert(QStringLiteral("command"), command);
- addRequestSequence();
- addSuccess(false);
- addRunning();
- response.insert(QStringLiteral("message"), msg);
- }
-
- int requestSequenceNr() const
- { return seq.toInt(-1); }
-
-protected:
- QString cmd;
- QJsonObject req;
- QJsonValue seq;
- QQmlDebugService *debugService;
- QV4DebugServicePrivate *debugServicePrivate;
- QJsonObject response;
-};
-
-class UnknownV8CommandHandler: public V8CommandHandler
-{
-public:
- UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
-
- virtual void handleRequest()
- {
- QString msg = QStringLiteral("unimplemented command \"");
- msg += req.value(QStringLiteral("command")).toString();
- msg += QStringLiteral("\"");
- createErrorResponse(msg);
- }
-};
-
-namespace {
-class V8VersionRequest: public V8CommandHandler
-{
-public:
- V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
-
- virtual void handleRequest()
- {
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("V8Version"),
- QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
- addBody(body);
- }
-};
-
-class V8SetBreakPointRequest: public V8CommandHandler
-{
-public:
- V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- QString type = args.value(QStringLiteral("type")).toString();
- if (type != QStringLiteral("scriptRegExp")) {
- createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
- return;
- }
-
- QString fileName = args.value(QStringLiteral("target")).toString();
- if (fileName.isEmpty()) {
- createErrorResponse(QStringLiteral("breakpoint has no file name"));
- return;
- }
-
- int line = args.value(QStringLiteral("line")).toInt(-1);
- if (line < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
- return;
- }
-
- bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
- QString condition = args.value(QStringLiteral("condition")).toString();
-
- // set the break point:
- int id = debugServicePrivate->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), type);
- body.insert(QStringLiteral("breakpoint"), id);
- // It's undocumented, but V8 sends back an actual_locations array too. However, our
- // Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
- // pending until the breakpoint is hit for the first time.
- addBody(body);
- }
-};
-
-class V8ClearBreakPointRequest: public V8CommandHandler
-{
-public:
- V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- int id = args.value(QStringLiteral("breakpoint")).toInt(-1);
- if (id < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
- return;
- }
-
- // remove the break point:
- debugServicePrivate->debuggerAgent.removeBreakPoint(id);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
- body.insert(QStringLiteral("breakpoint"), id);
- addBody(body);
- }
-};
-
-class V8BacktraceRequest: public V8CommandHandler
-{
-public:
- V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
-
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int fromFrame = arguments.value(QStringLiteral("fromFrame")).toInt(0);
- int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
- // no idea what the bottom property is for, so we'll ignore it.
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- QJsonArray frameArray;
- QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
- for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
- frameArray.push_back(debugServicePrivate->buildFrame(frames[i], i, debugger));
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- if (frameArray.isEmpty()) {
- body.insert(QStringLiteral("totalFrames"), 0);
- } else {
- body.insert(QStringLiteral("fromFrame"), fromFrame);
- body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
- body.insert(QStringLiteral("frames"), frameArray);
- }
- addBody(body);
- addRefs();
- }
-};
-
-class V8FrameRequest: public V8CommandHandler
-{
-public:
- V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("number")).toInt(debugServicePrivate->selectedFrame());
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("frame command has invalid frame number"));
- return;
- }
-
- debugServicePrivate->selectFrame(frameNr);
- QJsonObject frame = debugServicePrivate->buildFrame(frames[frameNr], frameNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(frame);
- addRefs();
- }
-};
-
-class V8ScopeRequest: public V8CommandHandler
-{
-public:
- V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(debugServicePrivate->selectedFrame());
- const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("scope command has invalid frame number"));
- return;
- }
- if (scopeNr < 0) {
- createErrorResponse(QStringLiteral("scope command has invalid scope number"));
- return;
- }
-
- QJsonObject scope = debugServicePrivate->buildScope(frameNr, scopeNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(scope);
- addRefs();
- }
-};
-
-class V8LookupRequest: public V8CommandHandler
-{
-public:
- V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
-
- QJsonObject body;
- foreach (QJsonValue handle, handles)
- body[QString::number(handle.toInt())] = debugServicePrivate->lookup(handle.toInt());
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(body);
- addRefs();
- }
-};
-
-class V8ContinueRequest: public V8CommandHandler
-{
-public:
- V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- if (arguments.empty()) {
- debugger->resume(QV4::Debugging::Debugger::FullThrottle);
- } else {
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
- const int stepcount = arguments.value(QStringLiteral("stepcount")).toInt(1);
- if (stepcount != 1)
- qWarning() << "Step count other than 1 is not supported.";
-
- if (stepAction == QStringLiteral("in")) {
- debugger->resume(QV4::Debugging::Debugger::StepIn);
- } else if (stepAction == QStringLiteral("out")) {
- debugger->resume(QV4::Debugging::Debugger::StepOut);
- } else if (stepAction == QStringLiteral("next")) {
- debugger->resume(QV4::Debugging::Debugger::StepOver);
- } else {
- createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
- return;
- }
- }
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8DisconnectRequest: public V8CommandHandler
-{
-public:
- V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
-
- virtual void handleRequest()
- {
- debugServicePrivate->debuggerAgent.removeAllBreakPoints();
- debugServicePrivate->debuggerAgent.resumeAll();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8SetExceptionBreakRequest: public V8CommandHandler
-{
-public:
- V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
-
- virtual void handleRequest()
- {
- bool wasEnabled = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString type = arguments.value(QStringLiteral("type")).toString();
- bool enabled = arguments.value(QStringLiteral("number")).toBool(!wasEnabled);
-
- if (type == QStringLiteral("all")) {
- // that's fine
- } else if (type == QStringLiteral("uncaught")) {
- createErrorResponse(QStringLiteral("breaking only on uncaught exceptions is not supported yet"));
- return;
- } else {
- createErrorResponse(QStringLiteral("invalid type for break on exception"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.setBreakOnThrow(enabled);
-
- QJsonObject body;
- body[QLatin1String("type")] = type;
- body[QLatin1String("enabled")] = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- // response:
- addBody(body);
- addRunning();
- addSuccess(true);
- addRequestSequence();
- addCommand();
- }
-};
-
-class V8ScriptsRequest: public V8CommandHandler
-{
-public:
- V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int types = arguments.value(QStringLiteral("types")).toInt(-1);
- if (types < 0 || types > 7) {
- createErrorResponse(QStringLiteral("invalid types value in scripts command"));
- return;
- } else if (types != 4) {
- createErrorResponse(QStringLiteral("unsupported types value in scripts command"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.firstDebugger()->gatherSources(requestSequenceNr());
-
- // response will be send by
- }
-};
-
-// Request:
-// {
-// "seq": 4,
-// "type": "request",
-// "command": "evaluate",
-// "arguments": {
-// "expression": "a",
-// "frame": 0
-// }
-// }
-//
-// Response:
-// {
-// "body": {
-// "handle": 3,
-// "type": "number",
-// "value": 1
-// },
-// "command": "evaluate",
-// "refs": [],
-// "request_seq": 4,
-// "running": false,
-// "seq": 5,
-// "success": true,
-// "type": "response"
-// }
-//
-// The "value" key in "body" is the result of evaluating the expression in the request.
-class V8EvaluateRequest: public V8CommandHandler
-{
-public:
- V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString expression = arguments.value(QStringLiteral("expression")).toString();
- const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- Q_ASSERT(debugger->state() == QV4::Debugging::Debugger::Paused);
-
- VariableCollector *collector = debugServicePrivate->collector();
- QJsonArray dest;
- collector->setDestination(&dest);
- debugger->evaluateExpression(frame, expression, collector);
-
- const int ref = dest.at(0).toObject().value(QStringLiteral("value")).toObject()
- .value(QStringLiteral("ref")).toInt();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(collector->lookup(ref).toObject());
- addRefs();
- }
-};
-} // anonymous namespace
-
-QV4DebugServicePrivate::QV4DebugServicePrivate()
- : debuggerAgent(this)
- , version(1)
- , theSelectedFrame(0)
- , unknownV8CommandHandler(new UnknownV8CommandHandler)
-{
- addHandler(new V8VersionRequest);
- addHandler(new V8SetBreakPointRequest);
- addHandler(new V8ClearBreakPointRequest);
- addHandler(new V8BacktraceRequest);
- addHandler(new V8FrameRequest);
- addHandler(new V8ScopeRequest);
- addHandler(new V8LookupRequest);
- addHandler(new V8ContinueRequest);
- addHandler(new V8DisconnectRequest);
- addHandler(new V8SetExceptionBreakRequest);
- addHandler(new V8ScriptsRequest);
- addHandler(new V8EvaluateRequest);
-}
-
-void QV4DebugServicePrivate::addHandler(V8CommandHandler* handler)
-{
- handlers[handler->command()] = handler;
-}
-
-V8CommandHandler *QV4DebugServicePrivate::v8CommandHandler(const QString &command) const
-{
- V8CommandHandler *handler = handlers.value(command, 0);
- if (handler)
- return handler;
- else
- return unknownV8CommandHandler.data();
-}
-
-QV4DebugService::QV4DebugService(QObject *parent)
- : QQmlConfigurableDebugService(*(new QV4DebugServicePrivate()),
- QStringLiteral("V8Debugger"), 1, parent)
-{}
-
-QV4DebugService::~QV4DebugService()
-{
-}
-
-QV4DebugService *QV4DebugService::instance()
-{
- return v4ServiceInstance();
-}
-
-void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (QQmlDebugServer *server = QQmlDebugServer::instance()) {
- if (ee) {
- ee->enableDebugger();
- QV4::Debugging::Debugger *debugger = ee->debugger;
- d->debuggerMap.insert(d->debuggerIndex++, debugger);
- d->debuggerAgent.addDebugger(debugger);
- d->debuggerAgent.moveToThread(server->thread());
- moveToThread(server->thread());
- }
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
-}
-
-void QV4DebugService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine){
- const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (ee) {
- QV4::Debugging::Debugger *debugger = ee->debugger;
- typedef QMap<int, QV4::Debugging::Debugger *>::const_iterator DebuggerMapIterator;
- const DebuggerMapIterator end = d->debuggerMap.constEnd();
- for (DebuggerMapIterator i = d->debuggerMap.constBegin(); i != end; ++i) {
- if (i.value() == debugger) {
- d->debuggerMap.remove(i.key());
- break;
- }
- }
- d->debuggerAgent.removeDebugger(debugger);
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeRemoved(engine);
-}
-
-void QV4DebugService::signalEmitted(const QString &signal)
-{
- //This function is only called by QQmlBoundSignal
- //only if there is a slot connected to the signal. Hence, there
- //is no need for additional check.
- Q_D(QV4DebugService);
-
- //Parse just the name and remove the class info
- //Normalize to Lower case.
- QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
-
- foreach (const QString &signal, d->breakOnSignals) {
- if (signal == signalName) {
- // TODO: pause debugger
- break;
- }
- }
-}
-
-void QV4DebugService::messageReceived(const QByteArray &message)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
-
- QQmlDebugStream ms(message);
- QByteArray header;
- ms >> header;
-
- TRACE_PROTOCOL(qDebug() << "received message with header" << header);
-
- if (header == "V8DEBUG") {
- QByteArray type;
- QByteArray payload;
- ms >> type >> payload;
- TRACE_PROTOCOL(qDebug() << "... type:" << type);
-
- if (type == V4_CONNECT) {
- sendMessage(d->packMessage(type));
- stopWaiting();
- } else if (type == V4_PAUSE) {
- d->debuggerAgent.pauseAll();
- sendSomethingToSomebody(type);
- } else if (type == V4_BREAK_ON_SIGNAL) {
- QByteArray signal;
- bool enabled;
- ms >> signal >> enabled;
- //Normalize to lower case.
- QString signalName(QString::fromUtf8(signal).toLower());
- if (enabled)
- d->breakOnSignals.append(signalName);
- else
- d->breakOnSignals.removeOne(signalName);
- } else if (type == "v8request") {
- handleV8Request(payload);
- } else if (type == V4_DISCONNECT) {
- TRACE_PROTOCOL(qDebug() << "... payload:" << payload);
- handleV8Request(payload);
- } else {
- sendSomethingToSomebody(type, 0);
- }
- }
-}
-
-void QV4DebugService::sendSomethingToSomebody(const char *type, int magicNumber)
-{
- Q_D(QV4DebugService);
-
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
- rs << QByteArray(type)
- << QByteArray::number(d->version) << QByteArray::number(magicNumber);
- sendMessage(d->packMessage(type, response));
-}
-
-void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason)
-{
- Q_UNUSED(reason);
-
- debugServicePrivate->clearHandles(debugger->engine());
-
- QJsonObject event, body, script;
- event.insert(QStringLiteral("type"), QStringLiteral("event"));
-
- switch (reason) {
- case QV4::Debugging::Step:
- case QV4::Debugging::PauseRequest:
- case QV4::Debugging::BreakPoint: {
- event.insert(QStringLiteral("event"), QStringLiteral("break"));
- QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
- if (frames.isEmpty())
- break;
-
- const QV4::StackFrame &topFrame = frames.first();
- body.insert(QStringLiteral("invocationText"), topFrame.function);
- body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
- if (topFrame.column > 0)
- body.insert(QStringLiteral("sourceColumn"), topFrame.column);
- QJsonArray breakPoints;
- foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
- breakPoints.push_back(breakPointId);
- body.insert(QStringLiteral("breakpoints"), breakPoints);
- script.insert(QStringLiteral("name"), topFrame.source);
- } break;
- case QV4::Debugging::Throwing:
- // TODO: complete this!
- event.insert(QStringLiteral("event"), QStringLiteral("exception"));
- break;
- }
-
- if (!script.isEmpty())
- body.insert(QStringLiteral("script"), script);
- if (!body.isEmpty())
- event.insert(QStringLiteral("body"), body);
- debugServicePrivate->send(event);
-}
-
-void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr)
-{
- QJsonArray body;
- foreach (const QString source, sources) {
- QJsonObject src;
- src[QLatin1String("name")] = source;
- src[QLatin1String("scriptType")] = 4;
- body.append(src);
- }
-
- QJsonObject response;
- response[QLatin1String("success")] = true;
- response[QLatin1String("running")] = debugger->state() == QV4::Debugging::Debugger::Running;
- response[QLatin1String("body")] = body;
- response[QLatin1String("command")] = QStringLiteral("scripts");
- response[QLatin1String("request_seq")] = requestSequenceNr;
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
-}
-
-void QV4DebugService::handleV8Request(const QByteArray &payload)
-{
- Q_D(QV4DebugService);
-
- TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload);
-
- QJsonDocument request = QJsonDocument::fromJson(payload);
- QJsonObject o = request.object();
- QJsonValue type = o.value(QStringLiteral("type"));
- if (type.toString() == QStringLiteral("request")) {
- QJsonValue command = o.value(QStringLiteral("command"));
- V8CommandHandler *h = d->v8CommandHandler(command.toString());
- if (h)
- h->handle(o, this, d);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/qml/debugger/qv4debugservice_p.h
deleted file mode 100644
index f7b38b11b6..0000000000
--- a/src/qml/debugger/qv4debugservice_p.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QV4DEBUGSERVICE_P_H
-#define QV4DEBUGSERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmlconfigurabledebugservice_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 { struct ExecutionEngine; }
-class QQmlEngine;
-class QV4DebugServicePrivate;
-
-class QV4DebugService : public QQmlConfigurableDebugService
-{
- Q_OBJECT
-public:
- explicit QV4DebugService(QObject *parent = 0);
- ~QV4DebugService();
-
- static QV4DebugService *instance();
- void engineAboutToBeAdded(QQmlEngine *engine);
- void engineAboutToBeRemoved(QQmlEngine *engine);
-
- void signalEmitted(const QString &signal);
-
-protected:
- void messageReceived(const QByteArray &);
- void sendSomethingToSomebody(const char *type, int magicNumber = 1);
-
-private:
- void handleV8Request(const QByteArray &payload);
-
-private:
- Q_DISABLE_COPY(QV4DebugService)
- Q_DECLARE_PRIVATE(QV4DebugService)
-};
-
-QT_END_NAMESPACE
-
-#endif // QV4DEBUGSERVICE_P_H
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/qml/debugger/qv4profileradapter.cpp
deleted file mode 100644
index 2b8183dc69..0000000000
--- a/src/qml/debugger/qv4profileradapter.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4profileradapter_p.h"
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugservice_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
- QQmlAbstractProfilerAdapter(service)
-{
- engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)));
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
- Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)));
-}
-
-qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
-{
- QByteArray message;
- while (!memory_data.empty() && memory_data.front().timestamp <= until) {
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- QV4::Profiling::MemoryAllocationProperties &props = memory_data.front();
- d << props.timestamp << MemoryAllocation << props.type << props.size;
- memory_data.pop_front();
- messages.append(message);
- }
- return memory_data.empty() ? -1 : memory_data.front().timestamp;
-}
-
-qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- QByteArray message;
- while (true) {
- while (!stack.empty() && (data.empty() || stack.top() <= data.front().start)) {
- if (stack.top() > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? stack.top() : qMin(stack.top(), memory_next);
- }
- appendMemoryEvents(stack.top(), messages);
- QQmlDebugStream d(&message, QIODevice::WriteOnly);
- d << stack.pop() << RangeEnd << Javascript;
- messages.append(message);
- }
- while (!data.empty() && (stack.empty() || data.front().start < stack.top())) {
- const QV4::Profiling::FunctionCallProperties &props = data.front();
- if (props.start > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? props.start : qMin(props.start, memory_next);
- }
- appendMemoryEvents(props.start, messages);
-
- QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
- d_start << props.start << RangeStart << Javascript;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_location(&message, QIODevice::WriteOnly);
- d_location << props.start << RangeLocation << Javascript << props.file << props.line
- << props.column;
- messages.push_back(message);
- message.clear();
- QQmlDebugStream d_data(&message, QIODevice::WriteOnly);
- d_data << props.start << RangeData << Javascript << props.name;
- messages.push_back(message);
- message.clear();
- stack.push(props.end);
- data.pop_front();
- }
- if (stack.empty() && data.empty())
- return appendMemoryEvents(until, messages);
- }
-}
-
-void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data,
- const QList<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
-{
- data = new_data;
- memory_data = new_memory_data;
- stack.clear();
- service->dataReady(this);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4profileradapter_p.h b/src/qml/debugger/qv4profileradapter_p.h
deleted file mode 100644
index 2f467f4beb..0000000000
--- a/src/qml/debugger/qv4profileradapter_p.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QV4PROFILERADAPTER_P_H
-#define QV4PROFILERADAPTER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qv4profiling_p.h"
-#include "qqmlabstractprofileradapter_p.h"
-
-#include <QStack>
-#include <QList>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlProfilerService;
-class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter {
- Q_OBJECT
-
-public:
- QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
-
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-
-public slots:
- void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
-
-private:
- QList<QV4::Profiling::FunctionCallProperties> data;
- QList<QV4::Profiling::MemoryAllocationProperties> memory_data;
- QStack<qint64> stack;
- qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages);
-};
-
-QT_END_NAMESPACE
-
-#endif // QV4PROFILERADAPTER_P_H
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 09e5b14c97..b5765b5705 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -241,16 +241,16 @@ void Assembler::enterStandardStackFrame(const RegisterInformation &regularRegist
subPtr(TrustedImm32(frameSize), StackPointerRegister);
Address slotAddr(StackFrameRegister, 0);
- for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
- Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
- slotAddr.offset -= RegisterSize;
- storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
- }
for (int i = 0, ei = fpRegistersToSave.size(); i < ei; ++i) {
Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
slotAddr.offset -= sizeof(double);
JSC::MacroAssembler::storeDouble(fpRegistersToSave.at(i).reg<FPRegisterID>(), slotAddr);
}
+ for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
+ Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
+ slotAddr.offset -= RegisterSize;
+ storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
+ }
}
void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave,
@@ -259,16 +259,16 @@ void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegist
Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize - fpRegistersToSave.size() * sizeof(double));
// restore the callee saved registers
- for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
- Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
- JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
- slotAddr.offset += sizeof(double);
- }
for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) {
Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>());
slotAddr.offset += RegisterSize;
}
+ for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
+ Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
+ JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
+ slotAddr.offset += sizeof(double);
+ }
Q_ASSERT(slotAddr.offset == 0);
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 3b65acb26c..ab74211d23 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -478,7 +478,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -491,7 +491,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -500,7 +500,7 @@ public:
Q_UNUSED(argumentNumber);
QV4::Value v = convertToValue(c);
- move(TrustedImm64(v.val), dest);
+ move(TrustedImm64(v.rawValue()), dest);
}
void loadArgumentInRegister(IR::Expr* expr, RegisterID dest, int argumentNumber)
@@ -509,7 +509,7 @@ public:
if (!expr) {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
} else if (IR::Temp *t = expr->asTemp()){
loadArgumentInRegister(t, dest, argumentNumber);
} else if (IR::ArgLocal *al = expr->asArgLocal()) {
@@ -565,6 +565,8 @@ public:
moveIntsToDouble(JSC::ARMRegisters::r0, JSC::ARMRegisters::r1, dest, FPGpr0);
#elif defined(Q_PROCESSOR_X86)
moveIntsToDouble(JSC::X86Registers::eax, JSC::X86Registers::edx, dest, FPGpr0);
+#elif defined(Q_PROCESSOR_MIPS)
+ moveIntsToDouble(JSC::MIPSRegisters::v0, JSC::MIPSRegisters::v1, dest, FPGpr0);
#else
subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister);
Pointer tmp(StackPointerRegister, 0);
@@ -595,6 +597,14 @@ public:
destination.offset += 4;
store32(JSC::ARMRegisters::r1, destination);
}
+#elif defined(Q_PROCESSOR_MIPS)
+ void storeReturnValue(const Pointer &dest)
+ {
+ Pointer destination = dest;
+ store32(JSC::MIPSRegisters::v0, destination);
+ destination.offset += 4;
+ store32(JSC::MIPSRegisters::v1, destination);
+ }
#endif
void storeReturnValue(IR::Expr *target)
@@ -781,11 +791,11 @@ public:
void storeValue(QV4::Primitive value, Address destination)
{
#ifdef VALUE_FITS_IN_REGISTER
- store64(TrustedImm64(value.val), destination);
+ store64(TrustedImm64(value.rawValue()), destination);
#else
- store32(TrustedImm32(value.int_32), destination);
+ store32(TrustedImm32(value.int_32()), destination);
destination.offset += 4;
- store32(TrustedImm32(value.tag), destination);
+ store32(TrustedImm32(value.tag()), destination);
#endif
}
@@ -820,6 +830,8 @@ public:
else
#if OS(WINDOWS) && CPU(X86_64)
loadArgumentOnStack<argumentNumber>(value, argumentNumber);
+#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms.
+ loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4);
#else // Sanity:
loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber);
#endif
@@ -945,8 +957,8 @@ public:
tagAddr.offset += 4;
QV4::Primitive v = convertToValue(c);
- store32(TrustedImm32(v.int_32), addr);
- store32(TrustedImm32(v.tag), tagAddr);
+ store32(TrustedImm32(v.int_32()), addr);
+ store32(TrustedImm32(v.tag()), tagAddr);
return Pointer(addr);
}
@@ -961,7 +973,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag()), addr);
}
void storeBool(RegisterID src, RegisterID dest)
@@ -1005,7 +1017,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag()), addr);
}
void storeInt32(RegisterID reg, IR::Expr *target)
@@ -1084,7 +1096,7 @@ public:
RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg)
{
if (IR::Const *c = e->asConst()) {
- move(TrustedImm32(convertToValue(c).int_32), scratchReg);
+ move(TrustedImm32(convertToValue(c).int_32()), scratchReg);
return scratchReg;
}
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index c6c8023cd7..8b051fcb3d 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -352,7 +352,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
}
- if (op == IR::OpSub) {
+ // Special cases:
+ switch (op) {
+ case IR::OpSub:
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
&& targetTemp
&& targetTemp->kind == IR::Temp::PhysicalRegister
@@ -368,11 +370,27 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
as->storeInt32(targetReg, target);
return true;
+
+ case IR::OpLShift:
+ case IR::OpRShift:
+ case IR::OpURShift:
+ if (IR::Const *c = rightSource->asConst()) {
+ if ((QV4::Primitive::toUInt32(c->value) & 0x1f) == 0) {
+ Assembler::RegisterID r = as->toInt32Register(leftSource, targetReg);
+ as->storeInt32(r, target);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ break;
}
Assembler::RegisterID l = as->toInt32Register(leftSource, targetReg);
if (IR::Const *c = rightSource->asConst()) { // All cases of Y = X op Const
Assembler::TrustedImm32 r(int(c->value));
+ Assembler::TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f);
switch (op) {
case IR::OpBitAnd: as->and32(r, l, targetReg); break;
@@ -381,9 +399,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(r, l, targetReg); break;
case IR::OpMul: as->mul32(r, l, targetReg); break;
- case IR::OpLShift: r.m_value &= 0x1f; as->lshift32(l, r, targetReg); break;
- case IR::OpRShift: r.m_value &= 0x1f; as->rshift32(l, r, targetReg); break;
- case IR::OpURShift: r.m_value &= 0x1f; as->urshift32(l, r, targetReg);
+ case IR::OpLShift: as->lshift32(l, ur, targetReg); break;
+ case IR::OpRShift: as->rshift32(l, ur, targetReg); break;
+ case IR::OpURShift: as->urshift32(l, ur, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
@@ -415,32 +433,33 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(l, r, targetReg); break;
case IR::OpMul: as->mul32(l, r, targetReg); break;
-#if CPU(ARM) || CPU(X86) || CPU(X86_64)
- // The ARM assembler will generate an and with 0x1f for us, and Intel will do it on the CPU.
-
+#if CPU(X86) || CPU(X86_64)
+ // Intel does the & 0x1f on the CPU, so:
case IR::OpLShift: as->lshift32(l, r, targetReg); break;
case IR::OpRShift: as->rshift32(l, r, targetReg); break;
case IR::OpURShift: as->urshift32(l, r, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
#else
- case IR::OpLShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->lshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
- case IR::OpRShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->rshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
+ // Not all CPUs accept shifts over more than 31 bits, and some CPUs (like ARM) will do
+ // surprising stuff when shifting over 0 bits.
+#define CHECK_RHS(op) { \
+ as->and32(Assembler::TrustedImm32(0x1f), r, Assembler::ScratchRegister); \
+ Assembler::Jump notZero = as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); \
+ as->move(l, targetReg); \
+ Assembler::Jump done = as->jump(); \
+ notZero.link(as); \
+ op; \
+ done.link(as); \
+}
+ case IR::OpLShift: CHECK_RHS(as->lshift32(l, Assembler::ScratchRegister, targetReg)); break;
+ case IR::OpRShift: CHECK_RHS(as->rshift32(l, Assembler::ScratchRegister, targetReg)); break;
case IR::OpURShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
+ CHECK_RHS(as->urshift32(l, Assembler::ScratchRegister, targetReg));
+ as->storeUInt32(targetReg, target);
+ // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
+#undef CHECK_RHS
#endif
case IR::OpSub: // already handled before
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index da511cd1eb..acead2088b 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -317,7 +317,7 @@ const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -574,9 +574,9 @@ void InstructionSelection::loadThisObject(IR::Expr *temp)
#endif
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
+void InstructionSelection::loadQmlContext(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::EngineRegister);
+ generateFunctionCall(temp, Runtime::getQmlContext, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
@@ -584,16 +584,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::EngineRegister);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::EngineRegister);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::EngineRegister);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name));
@@ -614,7 +604,7 @@ void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
_as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
} else if (targetTemp->type == IR::BoolType) {
Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32()),
(Assembler::RegisterID) targetTemp->index);
} else {
Q_UNREACHABLE();
@@ -680,6 +670,18 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::
}
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(target, Runtime::getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(target, Runtime::getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfIdObjectsArray)
+ generateFunctionCall(target, Runtime::getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
@@ -708,6 +710,18 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
}
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
@@ -901,6 +915,24 @@ void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr
binop.generate(leftSource, rightSource, target);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ prepareCallData(args, base);
+
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(result, Runtime::callQmlScopeObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(result, Runtime::callQmlContextObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -1297,11 +1329,11 @@ void InstructionSelection::visitCJump(IR::CJump *s)
} else {
Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
- tag.offset += qOffsetOf(QV4::Value, tag);
+ tag.offset += QV4::Value::tagOffset();
Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
Address data = temp;
- data.offset += qOffsetOf(QV4::Value, int_32);
+ data.offset += QV4::Value::valueOffset();
_as->load32(data, Assembler::ReturnValueRegister);
Assembler::Jump testBoolean = _as->jump();
@@ -1383,11 +1415,14 @@ void InstructionSelection::visitRet(IR::Ret *s)
// this only happens if the method doesn't have a return statement and can
// only exit through an exception
} else if (IR::Temp *t = s->expr->asTemp()) {
-#if CPU(X86) || CPU(ARM)
+#if CPU(X86) || CPU(ARM) || CPU(MIPS)
# if CPU(X86)
Assembler::RegisterID lowReg = JSC::X86Registers::eax;
Assembler::RegisterID highReg = JSC::X86Registers::edx;
+# elif CPU(MIPS)
+ Assembler::RegisterID lowReg = JSC::MIPSRegisters::v0;
+ Assembler::RegisterID highReg = JSC::MIPSRegisters::v1;
# else // CPU(ARM)
Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
@@ -1472,13 +1507,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
} else if (IR::Const *c = s->expr->asConst()) {
QV4::Primitive retVal = convertToValue(c);
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
#else
- _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
} else {
Q_UNREACHABLE();
@@ -1499,13 +1537,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
_as->exceptionReturnLabel = _as->label();
QV4::Primitive retVal = Primitive::undefinedValue();
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
#else
- _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
_as->jump(leaveStackFrame);
}
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 87b4a20bfc..6e842f5fb4 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -91,14 +91,13 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
virtual void loadThisObject(IR::Expr *temp);
- virtual void loadQmlIdArray(IR::Expr *target);
+ virtual void loadQmlContext(IR::Expr *target);
virtual void loadQmlImportedScripts(IR::Expr *target);
- virtual void loadQmlContextObject(IR::Expr *target);
- virtual void loadQmlScopeObject(IR::Expr *target);
virtual void loadQmlSingleton(const QString &name, IR::Expr *target);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -107,8 +106,10 @@ protected:
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index ae06a99d2a..b9178c0ea0 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -35,7 +35,7 @@
#include <QtCore/QDebug>
#include "qv4regalloc_p.h"
#include "qv4alloca_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <algorithm>
#if defined(Q_CC_MINGW)
@@ -299,6 +299,16 @@ protected: // IRDecoder
addCall();
}
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+ {
+ Q_UNUSED(propertyIndex)
+
+ addDef(result);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addUses(args, Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -421,7 +431,7 @@ protected: // IRDecoder
addDef(temp);
}
- virtual void loadQmlIdArray(IR::Expr *temp)
+ virtual void loadQmlContext(IR::Expr *temp)
{
addDef(temp);
addCall();
@@ -433,20 +443,6 @@ protected: // IRDecoder
addCall();
}
- virtual void loadQmlContextObject(Expr *temp)
- {
- addDef(temp);
- addCall();
- }
-
- virtual void loadQmlScopeObject(Expr *temp)
- {
- Q_UNUSED(temp);
-
- addDef(temp);
- addCall();
- }
-
virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp)
{
Q_UNUSED(temp);
@@ -511,6 +507,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind /*kind*/, int /*propertyIndex*/)
+ {
+ addUses(source->asTemp(), Use::CouldHaveRegister);
+ addUses(targetBase->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int /*propertyIndex*/)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
@@ -518,6 +521,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target)
+ {
+ addDef(target);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target)
{
addDef(target);
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 05741f0ae5..76c768e4f9 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -346,6 +346,71 @@ public:
static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::ARMRegisters::lr); }
#endif // Linux on ARM (32 bit)
+#if defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+ enum { RegAllocIsSupported = 1 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::MIPSRegisters::fp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::MIPSRegisters::sp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::MIPSRegisters::s0;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::MIPSRegisters::s1;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::MIPSRegisters::v0;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::MIPSRegisters::s2;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::MIPSRegisters::f0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::MIPSRegisters::f2;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ // Note: t0, t1, t2, t3 and f16 are already used by MacroAssemblerMIPS.
+ << RI(JSC::MIPSRegisters::t4, QStringLiteral("t4"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t5, QStringLiteral("t5"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t6, QStringLiteral("t6"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t7, QStringLiteral("t7"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t8, QStringLiteral("t8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::s0, QStringLiteral("s0"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s1, QStringLiteral("s1"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s2, QStringLiteral("s2"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s3, QStringLiteral("s3"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f4, QStringLiteral("f4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f6, QStringLiteral("f6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f8, QStringLiteral("f8"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f10, QStringLiteral("f10"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f18, QStringLiteral("f18"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f20, QStringLiteral("f20"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f22, QStringLiteral("f22"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f24, QStringLiteral("f24"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f26, QStringLiteral("f26"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f28, QStringLiteral("f28"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ ;
+ }
+
+#undef HAVE_ALU_OPS_WITH_MEM_OPERAND
+#undef VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 4;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 4;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::MIPSRegisters::a0,
+ JSC::MIPSRegisters::a1,
+ JSC::MIPSRegisters::a2,
+ JSC::MIPSRegisters::a3
+ };
+
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 8;
+ static const int StackShadowSpace = 4 * RegisterSize; // Stack space for 4 argument registers.
+ static const int StackSpaceAllocatedUponFunctionEntry = 1 * RegisterSize; // Registers saved in platformEnterStandardStackFrame below.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { as->push(JSC::MIPSRegisters::ra); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::MIPSRegisters::ra); }
+#endif // Linux on MIPS (32 bit)
+
public: // utility functions
static RegisterInformation getRegisterInfo()
{
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index ee27c21aed..d9615d496f 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -77,7 +77,6 @@ Q_DECLARE_METATYPE(QList<int>)
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
\section1 Evaluating Scripts
@@ -271,7 +270,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
if (val)
obj = val;
if (!obj)
- obj = scope.engine->globalObject();
+ obj = scope.engine->globalObject;
#ifndef QT_NO_TRANSLATION
obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
@@ -281,7 +280,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
// string prototype extension
- scope.engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
+ scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"),
QV4::GlobalExtensions::method_string_arg);
#endif
}
@@ -319,7 +318,7 @@ 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());
- if (ctx->d() != v4->rootContext())
+ if (ctx->d() != v4->rootContext()->d())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -331,7 +330,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())
+ if (ctx->d() != v4->rootContext()->d())
v4->popContext();
return QJSValue(v4, result->asReturnedValue());
}
@@ -414,7 +413,7 @@ QJSValue QJSEngine::globalObject() const
{
Q_D(const QJSEngine);
QV4::Scope scope(d->m_v4Engine);
- QV4::ScopedValue v(scope, d->m_v4Engine->globalObject());
+ QV4::ScopedValue v(scope, d->m_v4Engine->globalObject);
return QJSValue(d->m_v4Engine, v->asReturnedValue());
}
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 50669c46a8..6d0c7cfdda 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -37,13 +37,14 @@
#include "qjsengine.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4dateobject_p.h"
#include "qv4runtime_p.h"
#include "qv4variantobject_p.h"
#include "qv4regexpobject_p.h"
+#include "qv4errorobject_p.h"
#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -57,7 +58,6 @@
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
QJSValue supports the types defined in the \l{ECMA-262}
standard: The primitive types, which are Undefined, Null, Boolean,
@@ -317,8 +317,7 @@ bool QJSValue::isError() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- Object *o = val->asObject();
- return o && o->asErrorObject();
+ return val->as<ErrorObject>();
}
/*!
@@ -332,7 +331,7 @@ bool QJSValue::isArray() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asArrayObject();
+ return val->as<ArrayObject>();
}
/*!
@@ -349,7 +348,7 @@ bool QJSValue::isObject() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asObject();
+ return val->as<Object>();
}
/*!
@@ -363,7 +362,7 @@ bool QJSValue::isCallable() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asFunctionObject();
+ return val->as<FunctionObject>();
}
/*!
@@ -589,7 +588,7 @@ QVariant QJSValue::toVariant() const
QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
Q_ASSERT(val);
- if (Object *o = val->asObject())
+ if (Object *o = val->as<Object>())
return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
if (val->isString())
@@ -628,7 +627,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -637,7 +636,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
Scope scope(engine);
ScopedCallData callData(scope, args.length());
- callData->thisObject = engine->globalObject()->asReturnedValue();
+ callData->thisObject = engine->globalObject;
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
@@ -679,7 +678,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -733,7 +732,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -789,7 +788,7 @@ QJSValue QJSValue::prototype() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this)->asObject());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>());
if (!o)
return QJSValue();
ScopedObject p(scope, o->prototype());
@@ -1029,7 +1028,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
if (!o)
return QJSValue();
- QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex));
+ QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->getIndexed(arrayIndex));
if (engine->hasException)
engine->catchException();
return QJSValue(engine, result->asReturnedValue());
@@ -1108,7 +1107,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
- o->put(engine->id_uintMax, v);
+ o->put(engine->id_uintMax(), v);
if (engine->hasException)
engine->catchException();
}
@@ -1224,7 +1223,7 @@ QDateTime QJSValue::toDateTime() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
if (val) {
- QV4::DateObject *date = val->asDateObject();
+ QV4::DateObject *date = val->as<DateObject>();
if (date)
return date->toQDateTime();
}
@@ -1238,7 +1237,7 @@ QDateTime QJSValue::toDateTime() const
bool QJSValue::isDate() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->asDateObject();
+ return val && val->as<DateObject>();
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 93a28a4a5f..08dc184412 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -47,7 +47,7 @@
#include <qjsvalue.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 1ee4121f5c..a24953ae3f 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -52,9 +52,6 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
QV4::Scope scope(e);
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
iterator.set(e, e->newForEachIteratorObject(o));
-
- currentName = (QV4::String *)0;
- nextName = (QV4::String *)0;
}
@@ -102,8 +99,10 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
}
/*!
@@ -125,7 +124,7 @@ bool QJSValueIterator::hasNext() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return false;
- return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
+ return d_ptr->nextName.as<QV4::String>() || d_ptr->nextIndex != UINT_MAX;
}
/*!
@@ -143,8 +142,6 @@ bool QJSValueIterator::next()
return false;
d_ptr->currentName = d_ptr->nextName;
d_ptr->currentIndex = d_ptr->nextIndex;
- d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes);
- d_ptr->currentAttributes = d_ptr->nextAttributes;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4)
@@ -152,9 +149,11 @@ bool QJSValueIterator::next()
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
- return !!d_ptr->currentName || d_ptr->currentIndex != UINT_MAX;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
+ return d_ptr->currentName.as<QV4::String>() || d_ptr->currentIndex != UINT_MAX;
}
/*!
@@ -168,8 +167,8 @@ QString QJSValueIterator::name() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return QString();
- if (!!d_ptr->currentName)
- return d_ptr->currentName->toQString();
+ if (QV4::String *s = d_ptr->currentName.as<QV4::String>())
+ return s->toQString();
if (d_ptr->currentIndex < UINT_MAX)
return QString::number(d_ptr->currentIndex);
return QString();
@@ -192,10 +191,10 @@ QJSValue QJSValueIterator::value() const
if (!obj)
return QJSValue();
- if (!d_ptr->currentName && d_ptr->currentIndex == UINT_MAX)
+ if (!d_ptr->currentName.as<QV4::String>() && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
- QV4::ScopedValue v(scope, obj->getValue(*obj, &d_ptr->currentProperty, d_ptr->currentAttributes));
+ QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->getIndexed(d_ptr->currentIndex));
if (scope.hasException()) {
engine->catchException();
return QJSValue();
@@ -214,8 +213,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
d_ptr->value = object;
d_ptr->currentIndex = UINT_MAX;
d_ptr->nextIndex = UINT_MAX;
- d_ptr->currentName = (QV4::String *)0;
- d_ptr->nextName = (QV4::String *)0;
+ d_ptr->currentName.clear();
+ d_ptr->nextName.clear();
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4) {
d_ptr->iterator.clear();
@@ -228,8 +227,10 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
return *this;
}
diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h
index c17fedf73e..b0d0b2efda 100644
--- a/src/qml/jsapi/qjsvalueiterator_p.h
+++ b/src/qml/jsapi/qjsvalueiterator_p.h
@@ -48,15 +48,9 @@ public:
QJSValue value;
QV4::PersistentValue iterator;
- // ### GC
- QV4::Property currentProperty;
- QV4::PropertyAttributes currentAttributes;
- QV4::StringValue currentName;
+ QV4::PersistentValue currentName;
uint currentIndex;
- // ### GC
- QV4::Property nextProperty;
- QV4::PropertyAttributes nextAttributes;
- QV4::StringValue nextName;
+ QV4::PersistentValue nextName;
uint nextIndex;
};
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index ef44ca6f4d..5ffdebe328 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -10,7 +10,6 @@ SOURCES += \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
- $$PWD/qv4mm.cpp \
$$PWD/qv4managed.cpp \
$$PWD/qv4internalclass.cpp \
$$PWD/qv4sparsearray.cpp \
@@ -40,7 +39,6 @@ SOURCES += \
$$PWD/qv4sequenceobject.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
- $$PWD/qv4qmlextensions.cpp \
$$PWD/qv4vme_moth.cpp \
$$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
@@ -57,7 +55,6 @@ HEADERS += \
$$PWD/qv4lookup_p.h \
$$PWD/qv4identifier_p.h \
$$PWD/qv4identifiertable_p.h \
- $$PWD/qv4mm_p.h \
$$PWD/qv4managed_p.h \
$$PWD/qv4internalclass_p.h \
$$PWD/qv4sparsearray_p.h \
@@ -90,7 +87,6 @@ HEADERS += \
$$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
- $$PWD/qv4qmlextensions_p.h \
$$PWD/qv4vme_moth_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
@@ -102,7 +98,7 @@ HEADERS += \
HEADERS += \
$$PWD/qv4runtime_p.h \
- $$PWD/qv4value_inl_p.h \
+ $$PWD/qv4value_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4value_p.h
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 92c77570af..39dce8efe0 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -33,6 +33,7 @@
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
+#include "qv4string_p.h"
using namespace QV4;
@@ -40,11 +41,11 @@ 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.asObject())
+ context->d()->engine->objectPrototype())
, context(context->d())
, fullyCreated(false)
{
- Q_ASSERT(vtable == QV4::ArgumentsObject::staticVTable());
+ Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
@@ -53,21 +54,21 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
args->setArrayType(Heap::ArrayData::Complex);
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;
+ 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->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));
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
}
- Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->callData->argc);
}
@@ -144,9 +145,9 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
return result;
}
-ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
@@ -199,11 +200,11 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
-ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
+ReturnedValue ArgumentsGetterFunction::call(const Managed *getter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsGetterFunction *>(getter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsGetterFunction *>(getter)->engine();
Scope scope(v4);
- Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter));
+ Scoped<ArgumentsGetterFunction> g(scope, static_cast<const ArgumentsGetterFunction *>(getter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
@@ -214,11 +215,11 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
-ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
+ReturnedValue ArgumentsSetterFunction::call(const Managed *setter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsSetterFunction *>(setter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsSetterFunction *>(setter)->engine();
Scope scope(v4);
- Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter));
+ Scoped<ArgumentsSetterFunction> s(scope, static_cast<const ArgumentsSetterFunction *>(setter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 43cd6d1dee..aab5e2c156 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -59,9 +59,9 @@ struct ArgumentsObject : Object {
CallerPropertyIndex = 3
};
ArgumentsObject(QV4::CallContext *context);
- CallContext *context;
+ Pointer<CallContext> context;
bool fullyCreated;
- MemberData *mappedArguments;
+ Pointer<MemberData> mappedArguments;
};
}
@@ -71,7 +71,7 @@ struct ArgumentsGetterFunction: FunctionObject
V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *d);
};
inline
@@ -86,7 +86,7 @@ struct ArgumentsSetterFunction: FunctionObject
V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
inline
@@ -106,12 +106,12 @@ struct ArgumentsObject: Object {
Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
- return m->d()->vtable->type == Type_ArgumentsObject &&
+ return m->d()->vtable()->type == Type_ArgumentsObject &&
!static_cast<ArgumentsObject *>(m)->context()->strictMode;
}
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index dc65b5d21a..23c9695cf4 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -33,6 +33,7 @@
#include "qv4arraybuffer_p.h"
#include "qv4typedarray_p.h"
#include "qv4dataview_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -44,9 +45,9 @@ Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue l(scope, callData->argument(0));
@@ -64,7 +65,7 @@ ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -83,7 +84,7 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
{
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
@@ -96,7 +97,7 @@ Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
}
Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
, data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
@@ -138,10 +139,10 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
}
@@ -172,7 +173,7 @@ ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index fe3150618d..a7f9e92c80 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -61,8 +61,8 @@ struct ArrayBufferCtor: FunctionObject
{
V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static ReturnedValue method_isView(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index afcfa00905..da91db6aae 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -33,13 +33,14 @@
#include "qv4arraydata_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4runtime_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
-const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
@@ -90,6 +91,13 @@ const ArrayVTable SparseArrayData::static_vtbl =
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
+static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
+{
+ Value v = Value::fromReturnedValue(*target);
+ v.setValue(value);
+ *target = v.asReturnedValue();
+}
+
void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes)
{
Scope scope(o->engine());
@@ -165,7 +173,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
- uint *lastFree;
+ ReturnedValue *lastFree;
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
@@ -180,20 +188,20 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
}
}
if (toCopy < sparse->alloc) {
for (uint i = toCopy; i < sparse->alloc; ++i) {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
- *lastFree = UINT_MAX;
+ storeValue(lastFree, UINT_MAX);
}
// ### Could explicitly free the old data
}
@@ -230,7 +238,7 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
bool SimpleArrayData::put(Object *o, uint index, const Value &value)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
dd->data(index) = value;
@@ -244,7 +252,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value)
bool SimpleArrayData::del(Object *o, uint index)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index >= dd->len)
return true;
@@ -266,12 +274,12 @@ void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes att
void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (dd->len + n > dd->alloc) {
realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
dd->offset = (dd->offset - n) % dd->alloc;
dd->len += n;
@@ -281,7 +289,7 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (!dd->len)
return Encode::undefined();
@@ -294,7 +302,7 @@ ReturnedValue SimpleArrayData::pop_front(Object *o)
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (dd->len < newLen)
return newLen;
@@ -318,10 +326,10 @@ uint SimpleArrayData::length(const Heap::ArrayData *d)
bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index + n > dd->alloc) {
reallocate(o, index + n + 1, false);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
for (uint i = dd->len; i < index; ++i)
dd->data(i) = Primitive::emptyValue();
@@ -337,13 +345,10 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->arrayData + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].tag = Value::Empty_Type;
- v[1].uint_32 = d->freeList;
- v[0].tag = Value::Empty_Type;
- v[0].uint_32 = idx + 1;
+ v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
+ v[0].setTagValue(Value::Empty_Type, idx + 1);
} else {
- v->tag = Value::Empty_Type;
- v->uint_32 = d->freeList;
+ v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
}
d->freeList = idx;
if (d->attrs)
@@ -369,35 +374,37 @@ Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttr
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
- uint *last = &dd->freeList;
+ ReturnedValue *last = &dd->freeList;
while (1) {
- if (*last == UINT_MAX) {
+ if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
reallocate(o, dd->alloc + 2, true);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->freeList;
- Q_ASSERT(*last != UINT_MAX);
+ Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
- Q_ASSERT(dd->arrayData[*last].uint_32 != *last);
- if (dd->arrayData[*last].uint_32 == (*last + 1)) {
+ Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
+ if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
- uint idx = *last;
- *last = dd->arrayData[*last + 1].uint_32;
+ uint idx = Value::fromReturnedValue(*last).uint_32();
+ Value lastV = Value::fromReturnedValue(*last);
+ lastV.setValue(dd->arrayData[lastV.value() + 1].value());
+ *last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData[*last].uint_32;
+ last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
- if (dd->freeList == UINT_MAX) {
+ if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) {
reallocate(o, dd->alloc + 1, false);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- uint idx = dd->freeList;
+ uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].uint_32;
+ dd->freeList = dd->arrayData[idx].uint_32();
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -418,12 +425,12 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
if (value.isEmpty())
return true;
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
s->arrayData[n->value] = value;
if (s->attrs)
s->attrs[n->value] = Attr_Data;
@@ -432,7 +439,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
bool SparseArrayData::del(Object *o, uint index)
{
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *dd = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = dd->sparse->findNode(index);
if (!n)
@@ -452,13 +459,10 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].tag = Value::Empty_Type;
- dd->arrayData[pidx + 1].uint_32 = dd->freeList;
- dd->arrayData[pidx].tag = Value::Undefined_Type;
- dd->arrayData[pidx].uint_32 = pidx + 1;
+ dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
+ dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1);
} else {
- dd->arrayData[pidx].tag = Value::Empty_Type;
- dd->arrayData[pidx].uint_32 = dd->freeList;
+ dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
}
dd->freeList = pidx;
@@ -468,28 +472,28 @@ bool SparseArrayData::del(Object *o, uint index)
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = d->sparse->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
// need to convert the slot
free(o->arrayData(), n->value);
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
d->attrs[n->value] = attrs;
}
void SparseArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
d->arrayData[idx] = values[i];
d->sparse->push_front(idx);
}
@@ -497,7 +501,7 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
uint idx = d->sparse->pop_front();
ReturnedValue v;
@@ -512,7 +516,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *begin = d->sparse->lowerBound(newLen);
if (begin != d->sparse->end()) {
SparseArrayNode *it = d->sparse->end()->previousNode();
@@ -606,11 +610,11 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index < 0x1000 || index < d->len + (d->len >> 2)) {
if (index >= d->alloc) {
o->arrayReserve(index + 1);
- d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
if (index >= d->len) {
// mark possible hole in the array
@@ -623,11 +627,11 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
}
o->initSparseArray();
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
return reinterpret_cast<Property *>(s->arrayData + n->value);
}
@@ -737,7 +741,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!arrayData || !arrayData->length())
return;
- if (!(comparefn.isUndefined() || comparefn.asObject())) {
+ if (!(comparefn.isUndefined() || comparefn.as<Object>())) {
engine->throwTypeError();
return;
}
@@ -755,7 +759,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
thisObject->setArrayData(0);
ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
@@ -795,7 +799,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
} else {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > d->len)
len = d->len;
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 915e862bbb..729e657b1a 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -47,17 +47,17 @@ namespace QV4 {
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
static const QV4::ArrayVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return static_cast<const Data *>(m); } \
- Data *d() { return static_cast<Data *>(m); }
+ const Data *d() const { return static_cast<const Data *>(m()); } \
+ Data *d() { return static_cast<Data *>(m()); }
struct ArrayData;
struct ArrayVTable
{
- ManagedVTable managedVTable;
+ VTable vTable;
uint type;
Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
@@ -86,7 +86,7 @@ struct ArrayData : public Base {
PropertyAttributes *attrs;
union {
uint len;
- uint freeList;
+ ReturnedValue freeList;
};
union {
uint offset;
@@ -96,7 +96,7 @@ struct ArrayData : public Base {
bool isSparse() const { return type == Sparse; }
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable); }
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
@@ -239,8 +239,8 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
V4_ARRAYDATA(SparseArrayData)
V4_NEEDS_DESTROY
- uint &freeList() { return d()->freeList; }
- uint freeList() const { return d()->freeList; }
+ ReturnedValue &freeList() { return d()->freeList; }
+ ReturnedValue freeList() const { return d()->freeList; }
SparseArray *sparse() const { return d()->sparse; }
void setSparse(SparseArray *s) { d()->sparse = s; }
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 231eb93dd5..25d3d9329b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -37,6 +37,7 @@
#include "qv4scopedvalue_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -47,9 +48,9 @@ Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArrayCtor *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const ArrayCtor *>(m)->engine();
Scope scope(v4);
ScopedArrayObject a(scope, v4->newArrayObject());
uint len;
@@ -72,7 +73,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
return a.asReturnedValue();
}
-ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -81,11 +82,11 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
defineDefaultProperty(QStringLiteral("join"), method_join, 1);
@@ -110,7 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
- bool isArray = ctx->argc() && ctx->args()[0].asArrayObject();
+ bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>();
return Encode(isArray);
}
@@ -185,7 +186,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
r4 = arg->toQString();
ScopedObject self(scope, ctx->thisObject());
- ScopedValue length(scope, self->get(ctx->d()->engine->id_length));
+ ScopedValue length(scope, self->get(ctx->d()->engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
@@ -194,7 +195,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->asArrayObject()) {
+ if (ArrayObject *a = self->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -242,7 +243,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -256,7 +257,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -282,7 +283,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
}
double newLen = l + ctx->argc();
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return ctx->engine()->throwRangeError(str);
@@ -303,7 +304,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
return Encode(len);
}
@@ -354,7 +355,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -388,7 +389,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -523,7 +524,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
ctx->d()->strictMode = true;
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
return newArray.asReturnedValue();
}
@@ -561,7 +562,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
return Encode(newLen);
}
@@ -619,7 +620,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
return Encode(-1);
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData);
+ Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > sa->len)
len = sa->len;
uint idx = fromIndex;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 4e67eb2e31..422a0de675 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ArrayPrototype: ArrayObject
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 9c293e783b..53f8abf3f2 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4booleanobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -43,14 +44,14 @@ Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
+ReturnedValue BooleanCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<BooleanCtor *>(m)->engine());
+ Scope scope(static_cast<const BooleanCtor *>(m)->engine());
bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Encode(scope.engine->newBooleanObject(n));
}
-ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
+ReturnedValue BooleanCtor::call(const Managed *, CallData *callData)
{
bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Encode(value);
@@ -60,11 +61,11 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
}
ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
@@ -73,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
if (ctx->thisObject().isBoolean()) {
result = ctx->thisObject().booleanValue();
} else {
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
result = thisObject->value();
@@ -87,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
if (ctx->thisObject().isBoolean())
return ctx->thisObject().asReturnedValue();
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 903261bdce..77b5a74fde 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject
{
V4_OBJECT2(BooleanCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct BooleanPrototype: BooleanObject
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 9330f10780..f50c5ab017 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -36,10 +36,12 @@
#include <qv4context_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include "qv4function_p.h"
#include "qv4errorobject_p.h"
+#include "qv4string_p.h"
+#include "private/qqmlcontextwrapper_p.h"
using namespace QV4;
@@ -48,8 +50,9 @@ DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
+DEFINE_MANAGED_VTABLE(QmlContext);
-Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData)
{
Q_ASSERT(function->function());
@@ -90,31 +93,37 @@ Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName,
return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
}
-Heap::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- Scope scope(this);
- Scoped<CallContext> c(scope, d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(f, 0)));
- new (c->d()) Heap::CallContext(d()->engine, qml, f);
- return c->d();
+ return d()->engine->memoryManager->alloc<QmlContext>(this, qml);
}
-
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, d()->engine->globalObject());
+ ScopedObject activation(scope, d()->engine->globalObject);
ScopedContext ctx(scope, this);
while (ctx) {
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
if (!c->activation)
c->activation = scope.engine->newObject();
activation = c->activation;
break;
}
+ case Heap::ExecutionContext::Type_QmlContext: {
+ Heap::QmlContext *qml = static_cast<Heap::QmlContext *>(ctx->d());
+ activation = qml->qml;
+ break;
+ }
+ default:
+ break;
+ }
ctx = ctx->d()->outer;
}
@@ -130,7 +139,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
: Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext)
{
- global = eng->globalObject()->d();
+ global = eng->globalObject->d();
}
Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
@@ -153,34 +162,23 @@ Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exception
lookups = parent->lookups;
compilationUnit = parent->compilationUnit;
- this->exceptionVarName = exceptionVarName;
+ this->exceptionVarName = exceptionVarName->d();
this->exceptionValue = exceptionValue;
}
-Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outer->engine(), Heap::ExecutionContext::Type_QmlContext)
{
- this->function = function->d();
- callData = reinterpret_cast<CallData *>(this + 1);
- callData->tag = QV4::Value::_Integer_Type;
- callData->argc = 0;
- callData->thisObject = Primitive::undefinedValue();
-
strictMode = false;
- outer = function->scope();
-
- activation = qml->d();
-
- if (function->function()) {
- compilationUnit = function->function()->compilationUnit;
- lookups = compilationUnit->runtimeLookups;
- }
+ callData = parent->callData;
+ this->outer = outer->d();
+ lookups = parent->lookups;
+ compilationUnit = parent->compilationUnit;
- locals = (Value *)(this + 1);
- if (function->varCount())
- std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
+ this->qml = qml->d();
}
+
Identifier * const *CallContext::formals() const
{
return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0;
@@ -209,16 +207,28 @@ bool ExecutionContext::deleteProperty(String *name)
bool hasWith = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return false;
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
hasWith = true;
ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (withObject->hasProperty(name))
return withObject->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return false;
- } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ if (global->hasProperty(name))
+ return global->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->needsActivation() || hasWith) {
@@ -227,13 +237,14 @@ bool ExecutionContext::deleteProperty(String *name)
// ### throw in strict mode?
return false;
}
- ScopedObject activation(scope, c->activation);
- if (activation && activation->hasProperty(name))
- return activation->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
- if (global->hasProperty(name))
- return global->deleteProperty(name);
+ ScopedObject qml(scope, c->activation);
+ if (qml && qml->hasProperty(name))
+ return qml->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext:
+ // can't delete properties on qml objects
+ break;
}
}
@@ -254,7 +265,27 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (ctx->outer)
ctx->outer->mark(engine);
- if (ctx->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
+ c->exceptionVarName->mark(engine);
+ c->exceptionValue.mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
+ WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
+ if (w->withObject)
+ w->withObject->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
+ g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_SimpleCallContext:
+ break;
+ case Heap::ExecutionContext::Type_CallContext: {
QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
ctx->callData->thisObject.mark(engine);
for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->function->formalParameterCount()); ++arg)
@@ -264,17 +295,13 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (c->activation)
c->activation->mark(engine);
c->function->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) {
- WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
- if (w->withObject)
- w->withObject->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) {
- CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) {
- GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
- g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx);
+ g->qml->mark(engine);
+ break;
+ }
}
}
@@ -282,57 +309,71 @@ void ExecutionContext::setProperty(String *name, const Value &value)
{
Scope scope(this);
ScopedContext ctx(scope, this);
+ ScopedObject activation(scope);
+
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ activation = (Object *)0;
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d())) {
+ c->exceptionValue = value;
+ return;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) {
- static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value;
- return;
- } else {
- ScopedObject activation(scope, (Object *)0);
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->function->function) {
- uint index = c->function->function->internalClass->find(name);
- if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount()) {
- c->callData->args[c->function->formalParameterCount() - index - 1] = value;
- } else {
- index -= c->function->formalParameterCount();
- c->locals[index] = value;
- }
- return;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (c->function->function) {
+ uint index = c->function->function->internalClass->find(name);
+ if (index < UINT_MAX) {
+ if (index < c->function->formalParameterCount()) {
+ c->callData->args[c->function->formalParameterCount() - index - 1] = value;
+ } else {
+ index -= c->function->formalParameterCount();
+ c->locals[index] = value;
}
+ return;
}
- activation = c->activation;
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
}
+ activation = c->activation;
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ activation = static_cast<Heap::QmlContext *>(ctx->d())->qml;
+ activation->put(name, value);
+ return;
+ }
+ }
- if (activation) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) {
- activation->put(name, value);
- return;
- } else {
- uint member = activation->internalClass()->find(name);
- if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
- return;
- }
- }
+ if (activation) {
+ uint member = activation->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
+ return;
}
}
}
- if (d()->strictMode || name->equals(d()->engine->id_this)) {
+
+ if (d()->strictMode || name->equals(d()->engine->id_this())) {
ScopedValue n(scope, name->asReturnedValue());
engine()->throwReferenceError(n);
return;
}
- d()->engine->globalObject()->put(name, value);
+ d()->engine->globalObject->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
@@ -341,14 +382,22 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ScopedValue v(scope);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
@@ -356,17 +405,18 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty) {
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
@@ -387,85 +437,97 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
+ v = qml->get(name, &hasProperty);
if (hasProperty)
return v->asReturnedValue();
+ break;
+ }
}
}
ScopedValue n(scope, name);
return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
Scope scope(this);
ScopedValue v(scope);
- *base = (Heap::Object *)0;
+ base->setM(0);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
- *base = w->d();
+ base->setM(w->d());
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < f->formalParameterCount())
- return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - f->formalParameterCount()].asReturnedValue();
+ if (index < c->function->formalParameterCount())
+ return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
}
}
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
v = activation->get(name, &hasProperty);
- if (hasProperty) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext)
- *base = activation->d();
+ if (hasProperty)
return v->asReturnedValue();
- }
}
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
- return c->function->asReturnedValue();
+ return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
- if (hasProperty)
+ v = qml->get(name, &hasProperty);
+ if (hasProperty) {
+ base->setM(qml->d());
return v->asReturnedValue();
+ }
+ break;
+ }
}
}
ScopedValue n(scope, name);
@@ -487,3 +549,14 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
return 0;
}
+
+
+QObject *QmlContext::qmlScope() const
+{
+ return d()->qml->scopeObject;
+}
+
+QQmlContextData *QmlContext::qmlContext() const
+{
+ return d()->qml->context;
+}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 8392dd836d..2667bbe0b2 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -38,6 +38,9 @@
QT_BEGIN_NAMESPACE
+class QQmlContextData;
+class QObject;
+
namespace QV4 {
namespace CompiledData {
@@ -45,6 +48,8 @@ struct CompilationUnit;
struct Function;
}
+struct QmlContextWrapper;
+struct Identifier;
struct CallContext;
struct CatchContext;
struct WithContext;
@@ -74,9 +79,9 @@ struct ExecutionContext : Base {
Type_GlobalContext = 0x1,
Type_CatchContext = 0x2,
Type_WithContext = 0x3,
- Type_SimpleCallContext = 0x4,
- Type_CallContext = 0x5,
- Type_QmlContext = 0x6
+ Type_QmlContext = 0x4,
+ Type_SimpleCallContext = 0x5,
+ Type_CallContext = 0x6
};
inline ExecutionContext(ExecutionEngine *engine, ContextType t);
@@ -84,8 +89,8 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
+ Pointer<ExecutionContext> parent;
+ Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -102,29 +107,34 @@ struct CallContext : ExecutionContext {
locals = 0;
activation = 0;
}
- CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function);
- FunctionObject *function;
+ Pointer<FunctionObject> function;
Value *locals;
- Object *activation;
+ Pointer<Object> activation;
};
struct GlobalContext : ExecutionContext {
GlobalContext(ExecutionEngine *engine);
- Object *global;
+ Pointer<Object> global;
};
struct CatchContext : ExecutionContext {
CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
- StringValue exceptionVarName;
+ Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
WithContext(ExecutionEngine *engine, QV4::Object *with);
- Object *withObject;
+ Pointer<Object> withObject;
};
+struct QmlContextWrapper;
+
+struct QmlContext : ExecutionContext {
+ QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml);
+ Pointer<QmlContextWrapper> qml;
+};
}
@@ -139,16 +149,16 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
- Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData);
+ Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
Heap::WithContext *newWithContext(Object *with);
Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
- Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml);
+ Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
void createMutableBinding(String *name, bool deletable);
void setProperty(String *name, const Value &value);
ReturnedValue getProperty(String *name);
- ReturnedValue getPropertyAndBase(String *name, Heap::Object **base);
+ ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
inline CallContext *asCallContext();
@@ -160,7 +170,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- const Value &thisObject() const {
+ Value &thisObject() const {
return d()->callData->thisObject;
}
int argc() const {
@@ -174,7 +184,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
}
};
-struct CallContext : public ExecutionContext
+struct Q_QML_EXPORT CallContext : public ExecutionContext
{
V4_MANAGED(CallContext, ExecutionContext)
@@ -208,6 +218,14 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
+struct QmlContext : public ExecutionContext
+{
+ V4_MANAGED(QmlContext, ExecutionContext)
+
+ QObject *qmlScope() const;
+ QQmlContextData *qmlContext() const;
+};
+
inline CallContext *ExecutionContext::asCallContext()
{
return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 8a66c2cbfc..a741d61d10 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -33,6 +33,7 @@
#include "qv4dataview_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include "qendian.h"
@@ -46,9 +47,9 @@ Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
if (!buffer)
return scope.engine->throwTypeError();
@@ -69,14 +70,14 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue DataViewCtor::call(Managed *that, CallData *callData)
+ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype.asObject()),
+ : Heap::Object(e->emptyClass, e->dataViewPrototype()),
buffer(0),
byteLength(0),
byteOffset(0)
@@ -94,9 +95,9 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 3f0c1e9e23..e98239396a 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -48,7 +48,7 @@ struct DataViewCtor : FunctionObject {
struct DataView : Object {
DataView(ExecutionEngine *e);
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
};
@@ -59,8 +59,8 @@ struct DataViewCtor: FunctionObject
{
V4_OBJECT2(DataViewCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct DataView : Object
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 451ef2486d..3f45751695 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -36,6 +36,7 @@
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
@@ -628,14 +629,14 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->datePrototype())
{
- value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
+ this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
QDateTime DateObject::toQDateTime() const
{
- return ToDateTime(date().asDouble(), Qt::LocalTime);
+ return ToDateTime(date(), Qt::LocalTime);
}
DEFINE_OBJECT_VTABLE(DateCtor);
@@ -645,9 +646,9 @@ Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DateCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<DateCtor *>(m)->engine());
+ Scope scope(static_cast<const DateCtor *>(m)->engine());
double t = 0;
if (callData->argc == 0)
@@ -655,15 +656,16 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
else if (callData->argc == 1) {
ScopedValue arg(scope, callData->args[0]);
- if (DateObject *d = arg->asDateObject())
- arg = d->date();
- else
+ if (DateObject *d = arg->as<DateObject>()) {
+ t = d->date();
+ } else {
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
- if (arg->isString())
- t = ParseString(arg->stringValue()->toQString());
- else
- t = TimeClip(arg->toNumber());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
+ else
+ t = TimeClip(arg->toNumber());
+ }
}
else { // d.argc > 1
@@ -683,18 +685,18 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
return Encode(scope.engine->newDateObject(Primitive::fromDouble(t)));
}
-ReturnedValue DateCtor::call(Managed *m, CallData *)
+ReturnedValue DateCtor::call(const Managed *m, CallData *)
{
double t = currentTime();
- return static_cast<DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
+ return static_cast<const DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
}
void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(7));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(7));
LocalTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
@@ -702,13 +704,13 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("now"), method_now, 0);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toDateString"), method_toDateString, 0);
defineDefaultProperty(QStringLiteral("toTimeString"), method_toTimeString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString, 0);
defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString, 0);
- defineDefaultProperty(engine->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("getTime"), method_getTime, 0);
defineDefaultProperty(QStringLiteral("getYear"), method_getYear, 0);
defineDefaultProperty(QStringLiteral("getFullYear"), method_getFullYear, 0);
@@ -752,8 +754,8 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
- if (DateObject *thisObject = ctx->thisObject().asDateObject())
- return thisObject->date().asDouble();
+ if (DateObject *thisObject = ctx->thisObject().as<DateObject>())
+ return thisObject->date();
else {
ctx->engine()->throwTypeError();
return 0;
@@ -994,8 +996,8 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
return ctx->engine()->throwTypeError();
double t = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(t));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(t));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
@@ -1005,175 +1007,175 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (std::isnan(t))
t = 0;
else
@@ -1189,49 +1191,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = UTC(MakeDate(r, TimeWithinDay(t)));
r = TimeClip(r);
}
- self->date().setDouble(r);
- return self->date().asReturnedValue();
+ self->setDate(r);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
if (std::isnan(t))
t = 0;
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
}
@@ -1250,11 +1252,11 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (!std::isfinite(t))
return ctx->engine()->throwRangeError(ctx->thisObject());
@@ -1297,7 +1299,7 @@ ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
ScopedValue v(scope, O->objectValue()->get(s));
- FunctionObject *toIso = v->asFunctionObject();
+ FunctionObject *toIso = v->as<FunctionObject>();
if (!toIso)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index dad3689054..7a6413e820 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -49,18 +49,19 @@ struct DateObject : Object {
DateObject(InternalClass *ic, QV4::Object *prototype)
: Object(ic, prototype)
{
- value = Encode(qSNaN());
+ date = qSNaN();
}
DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype.asObject())
+ : Object(engine->emptyClass, engine->datePrototype())
{
- value = date;
+ this->date = date.toNumber();
}
DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
- Value value;
+ double date;
};
+
struct DateCtor : FunctionObject {
DateCtor(QV4::ExecutionContext *scope);
};
@@ -72,19 +73,23 @@ struct DateObject: Object {
Q_MANAGED_TYPE(DateObject)
- Value date() const { return d()->value; }
- Value &date() { return d()->value; }
- void setDate(const Value &date) { d()->value = date; }
+ double date() const { return d()->date; }
+ void setDate(double date) { d()->date = date; }
QDateTime toQDateTime() const;
};
+template<>
+inline const DateObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0;
+}
+
struct DateCtor: FunctionObject
{
V4_OBJECT2(DateCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *);
};
struct DatePrototype: DateObject
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 36e7a3558c..ceeef80b9f 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -38,69 +38,65 @@
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
-#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
-#include <iostream>
+#include "qv4string_p.h"
+#include "qv4objectiterator_p.h"
+#include <iostream>
#include <algorithm>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonValue>
+
+QT_BEGIN_NAMESPACE
+
using namespace QV4;
using namespace QV4::Debugging;
-namespace {
-class JavaScriptJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- int frameNr;
- const QString &script;
+Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &script)
+ : engine(engine)
+ , frameNr(frameNr)
+ , script(script)
+{}
-public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script)
- : engine(engine)
- , frameNr(frameNr)
- , script(script)
- {}
-
- void run()
- {
- Scope scope(engine);
+void Debugger::JavaScriptJob::run()
+{
+ Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope, engine->currentContext());
- if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
- for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
- }
+ if (frameNr > 0) {
+ Value *savedContexts = scope.alloc(frameNr);
+ for (int i = 0; i < frameNr; ++i) {
+ savedContexts[i] = engine->currentContext();
+ engine->popContext();
}
-
- 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
- // is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
- if (scope.engine->hasException)
- result = scope.engine->catchException();
- handleResult(result);
}
-protected:
- virtual void handleResult(QV4::ScopedValue &result) = 0;
-};
+ 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
+ // is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException)
+ result = scope.engine->catchException();
+ handleResult(result);
+}
-class EvalJob: public JavaScriptJob
+class EvalJob: public Debugger::JavaScriptJob
{
bool result;
public:
EvalJob(QV4::ExecutionEngine *engine, const QString &script)
- : JavaScriptJob(engine, /*frameNr*/-1, script)
+ : Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
, result(false)
{}
@@ -115,58 +111,8 @@ public:
}
};
-class ExpressionEvalJob: public JavaScriptJob
-{
- Debugger::Collector *collector;
-
-public:
- ExpressionEvalJob(ExecutionEngine *engine, int frameNr, const QString &expression, Debugger::Collector *collector)
- : JavaScriptJob(engine, frameNr, expression)
- , collector(collector)
- {
- }
-
- virtual void handleResult(QV4::ScopedValue &result)
- {
- collector->collect(QStringLiteral("body"), result);
- }
-};
-
-class GatherSourcesJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- const int seq;
-
-public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
- : engine(engine)
- , seq(seq)
- {}
-
- ~GatherSourcesJob() {}
-
- void run()
- {
- QStringList sources;
-
- foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
- QString fileName = unit->fileName();
- if (!fileName.isEmpty())
- sources.append(fileName);
- }
-
- Debugger *debugger = engine->debugger;
- QMetaObject::invokeMethod(debugger->agent(), "sourcesCollected", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, debugger),
- Q_ARG(QStringList, sources),
- Q_ARG(int, seq));
- }
-};
-}
-
Debugger::Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
- , m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
@@ -180,41 +126,6 @@ Debugger::Debugger(QV4::ExecutionEngine *engine)
qMetaTypeId<PauseReason>();
}
-Debugger::~Debugger()
-{
- detachFromAgent();
-}
-
-void Debugger::attachToAgent(DebuggerAgent *agent)
-{
- Q_ASSERT(!m_agent);
- m_agent = agent;
-}
-
-void Debugger::detachFromAgent()
-{
- DebuggerAgent *agent = 0;
- {
- QMutexLocker locker(&m_lock);
- agent = m_agent;
- m_agent = 0;
- }
- if (agent)
- agent->removeDebugger(this);
-}
-
-void Debugger::gatherSources(int requestSequenceNr)
-{
- QMutexLocker locker(&m_lock);
-
- m_gatherSources = new GatherSourcesJob(m_engine, requestSequenceNr);
- if (m_state == Paused) {
- runInEngine_havingLock(m_gatherSources);
- delete m_gatherSources;
- m_gatherSources = 0;
- }
-}
-
void Debugger::pause()
{
QMutexLocker locker(&m_lock);
@@ -272,251 +183,6 @@ QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
return m_engine->stackTrace(frameLimit);
}
-static inline Heap::CallContext *findContext(Heap::ExecutionContext *ctxt, int frame)
-{
- if (!ctxt)
- return 0;
-
- Scope scope(ctxt->engine);
- ScopedContext ctx(scope, ctxt);
- while (ctx) {
- CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->function) {
- if (frame < 1)
- return cCtxt->d();
- --frame;
- }
- ctx = ctx->d()->parent;
- }
-
- return 0;
-}
-
-static inline Heap::CallContext *findScope(Heap::ExecutionContext *ctxt, int scope)
-{
- if (!ctxt)
- return 0;
-
- Scope s(ctxt->engine);
- ScopedContext ctx(s, ctxt);
- for (; scope > 0 && ctx; --scope)
- ctx = ctx->d()->outer;
-
- return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
-}
-
-void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class ArgumentCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- ArgumentCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- ~ArgumentCollectJob() {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- v = ctxt->argument(i);
- collector->collect(qName, v);
- }
- }
- };
-
- ArgumentCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-/// Same as \c retrieveArgumentsFromContext, but now for locals.
-void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class LocalCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- LocalCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->variables()[i])
- qName = name->string;
- v = ctxt->d()->locals[i];
- collector->collect(qName, v);
- }
- }
- };
-
- LocalCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
-{
- if (state() != Paused)
- return false;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- bool *foundThis;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, bool *foundThis)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , foundThis(foundThis)
- {}
-
- void run()
- {
- *foundThis = myRun();
- }
-
- bool myRun()
- {
- Scope scope(engine);
- ScopedContext ctxt(scope, findContext(engine->currentContext(), frameNr));
- while (ctxt) {
- if (CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->d()->activation)
- break;
- ctxt = ctxt->d()->outer;
- }
-
- if (!ctxt)
- return false;
-
- ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
- collector->collect(o);
- return true;
- }
- };
-
- bool foundThis = false;
- ThisCollectJob job(m_engine, collector, frame, &foundThis);
- runInEngine(&job);
- return foundThis;
-}
-
-void Debugger::collectThrownValue(Collector *collector)
-{
- if (state() != Paused || !m_engine->hasException)
- return;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector)
- : engine(engine)
- , collector(collector)
- {}
-
- void run()
- {
- Scope scope(engine);
- ScopedValue v(scope, engine->exceptionValue);
- collector->collect(QStringLiteral("exception"), v);
- }
- };
-
- ThisCollectJob job(m_engine, collector);
- runInEngine(&job);
-}
-
-void Debugger::collectReturnedValue(Collector *collector) const
-{
- if (state() != Paused)
- return;
-
- Scope scope(m_engine);
- ScopedObject o(scope, m_returnedValue.valueRef());
- collector->collect(o);
-}
-
-QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
-{
- QVector<Heap::ExecutionContext::ContextType> types;
-
- if (state() != Paused)
- return types;
-
- Scope scope(m_engine);
- Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
- if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
- return types;
-
- ScopedContext it(scope, sctxt->d());
- for (; it; it = it->d()->outer)
- types.append(it->d()->type);
-
- return types;
-}
-
-
-void Debugger::evaluateExpression(int frameNr, const QString &expression, Debugger::Collector *resultsCollector)
-{
- Q_ASSERT(state() == Paused);
-
- Q_ASSERT(m_runningJob == 0);
- ExpressionEvalJob job(m_engine, frameNr, expression, resultsCollector);
- runInEngine(&job);
-}
-
void Debugger::maybeBreakAtInstruction()
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
@@ -610,9 +276,7 @@ void Debugger::pauseAndWait(PauseReason reason)
return;
m_state = Paused;
- QMetaObject::invokeMethod(m_agent, "debuggerPaused", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, this),
- Q_ARG(QV4::Debugging::PauseReason, reason));
+ emit debuggerPaused(this, reason);
while (true) {
m_runningCondition.wait(&m_lock);
@@ -662,174 +326,8 @@ void Debugger::runInEngine_havingLock(Debugger::Job *job)
m_runningJob = 0;
}
-void DebuggerAgent::addDebugger(Debugger *debugger)
-{
- Q_ASSERT(!m_debuggers.contains(debugger));
- m_debuggers << debugger;
- debugger->attachToAgent(this);
-
- debugger->setBreakOnThrow(m_breakOnThrow);
-
- foreach (const BreakPoint &breakPoint, m_breakPoints.values())
- if (breakPoint.enabled)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
-}
-
-void DebuggerAgent::removeDebugger(Debugger *debugger)
-{
- m_debuggers.removeAll(debugger);
- debugger->detachFromAgent();
-}
-
-void DebuggerAgent::pause(Debugger *debugger) const
-{
- debugger->pause();
-}
-
-void DebuggerAgent::pauseAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- pause(debugger);
-}
-
-void DebuggerAgent::resumeAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- if (debugger->state() == Debugger::Paused)
- debugger->resume(Debugger::FullThrottle);
-}
-
-int DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
-{
- if (enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->addBreakPoint(fileName, lineNumber, condition);
-
- int id = m_breakPoints.size();
- m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
- return id;
-}
-
-void DebuggerAgent::removeBreakPoint(int id)
-{
- BreakPoint breakPoint = m_breakPoints.value(id);
- if (!breakPoint.isValid())
- return;
-
- m_breakPoints.remove(id);
-
- if (breakPoint.enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
-}
-
-void DebuggerAgent::removeAllBreakPoints()
-{
- QList<int> ids = m_breakPoints.keys();
- foreach (int id, ids)
- removeBreakPoint(id);
-}
-
-void DebuggerAgent::enableBreakPoint(int id, bool onoff)
-{
- BreakPoint &breakPoint = m_breakPoints[id];
- if (!breakPoint.isValid() || breakPoint.enabled == onoff)
- return;
- breakPoint.enabled = onoff;
-
- foreach (Debugger *debugger, m_debuggers) {
- if (onoff)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
- else
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
- }
-}
-
-QList<int> DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
-{
- QList<int> ids;
-
- for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
- if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
- ids.push_back(i.key());
-
- return ids;
-}
-
-void DebuggerAgent::setBreakOnThrow(bool onoff)
-{
- if (onoff != m_breakOnThrow) {
- m_breakOnThrow = onoff;
- foreach (Debugger *debugger, m_debuggers)
- debugger->setBreakOnThrow(onoff);
- }
-}
-
-DebuggerAgent::~DebuggerAgent()
-{
- foreach (Debugger *debugger, m_debuggers)
- debugger->detachFromAgent();
-
- Q_ASSERT(m_debuggers.isEmpty());
-}
-
-Debugger::Collector::~Collector()
-{
-}
-
-void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
-{
- switch (value->type()) {
- case Value::Empty_Type:
- Q_ASSERT(!"empty Value encountered");
- break;
- case Value::Undefined_Type:
- addUndefined(name);
- break;
- case Value::Null_Type:
- addNull(name);
- break;
- case Value::Boolean_Type:
- addBoolean(name, value->booleanValue());
- break;
- case Value::Managed_Type:
- if (String *s = value->asString())
- addString(name, s->toQString());
- else
- addObject(name, value);
- break;
- case Value::Integer_Type:
- addInteger(name, value->int_32);
- break;
- default: // double
- addDouble(name, value->doubleValue());
- break;
- }
-}
-
-void Debugger::Collector::collect(Object *object)
-{
- bool property = true;
- qSwap(property, m_isProperty);
-
- Scope scope(m_engine);
- ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
- ScopedValue name(scope);
- ScopedValue value(scope);
- while (true) {
- Value v;
- name = it.nextPropertyNameAsString(&v);
- if (name->isNull())
- break;
- QString key = name->toQStringNoThrow();
- value = v;
- collect(key, value);
- }
-
- qSwap(property, m_isProperty);
-}
-
-
Debugger::Job::~Job()
{
}
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index e6a9750351..ac0c934d42 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -44,6 +44,8 @@
#include <QMutex>
#include <QWaitCondition>
+#include <QtCore/QJsonObject>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -59,8 +61,6 @@ enum PauseReason {
Step
};
-class DebuggerAgent;
-
struct DebuggerBreakPoint {
DebuggerBreakPoint(const QString &fileName, int line)
: fileName(fileName), lineNumber(line)
@@ -79,43 +79,29 @@ inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b)
typedef QHash<DebuggerBreakPoint, QString> BreakPoints;
-
-class Q_QML_EXPORT Debugger
+class Q_QML_EXPORT Debugger : public QObject
{
+ Q_OBJECT
public:
- class Job
+ class Q_QML_EXPORT Job
{
public:
virtual ~Job() = 0;
virtual void run() = 0;
};
- class Q_QML_EXPORT Collector
+ class Q_QML_EXPORT JavaScriptJob: public Job
{
- public:
- Collector(ExecutionEngine *engine): m_engine(engine), m_isProperty(false) {}
- virtual ~Collector();
+ QV4::ExecutionEngine *engine;
+ int frameNr;
+ const QString &script;
- void collect(const QString &name, const ScopedValue &value);
- void collect(Object *object);
+ public:
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
+ void run();
protected:
- virtual void addUndefined(const QString &name) = 0;
- virtual void addNull(const QString &name) = 0;
- virtual void addBoolean(const QString &name, bool value) = 0;
- virtual void addString(const QString &name, const QString &value) = 0;
- virtual void addObject(const QString &name, const Value &value) = 0;
- virtual void addInteger(const QString &name, int value) = 0;
- virtual void addDouble(const QString &name, double value) = 0;
-
- QV4::ExecutionEngine *engine() const { return m_engine; }
-
- bool isProperty() const { return m_isProperty; }
- void setIsProperty(bool onoff) { m_isProperty = onoff; }
-
- private:
- QV4::ExecutionEngine *m_engine;
- bool m_isProperty;
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
};
enum State {
@@ -133,16 +119,10 @@ public:
};
Debugger(ExecutionEngine *engine);
- ~Debugger();
ExecutionEngine *engine() const
{ return m_engine; }
- void attachToAgent(DebuggerAgent *agent);
- void detachFromAgent();
- DebuggerAgent *agent() const { return m_agent; }
-
- void gatherSources(int requestSequenceNr);
void pause();
void resume(Speed speed);
@@ -166,14 +146,10 @@ public:
}
QVector<StackFrame> stackTrace(int frameLimit = -1) const;
- void collectArgumentsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- void collectLocalsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- bool collectThisInContext(Collector *collector, int frame = 0);
- void collectThrownValue(Collector *collector);
- void collectReturnedValue(Collector *collector) const;
QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
- void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
+ Function *getFunction() const;
+ void runInEngine(Job *job);
public: // compile-time interface
void maybeBreakAtInstruction();
@@ -183,21 +159,19 @@ public: // execution hooks
void leavingFunction(const ReturnedValue &retVal);
void aboutToThrow();
-private:
- Function *getFunction() const;
+signals:
+ void sourcesCollected(QV4::Debugging::Debugger *self, const QStringList &sources, int seq);
+ void debuggerPaused(QV4::Debugging::Debugger *self, QV4::Debugging::PauseReason reason);
+private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
-
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
-
- void runInEngine(Job *job);
void runInEngine_havingLock(Debugger::Job *job);
private:
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;
- DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
@@ -214,54 +188,6 @@ private:
QWaitCondition m_jobIsRunning;
};
-class Q_QML_EXPORT DebuggerAgent : public QObject
-{
- Q_OBJECT
-public:
- DebuggerAgent(): m_breakOnThrow(false) {}
- ~DebuggerAgent();
-
- void addDebugger(Debugger *debugger);
- void removeDebugger(Debugger *debugger);
-
- void pause(Debugger *debugger) const;
- void pauseAll() const;
- void resumeAll() const;
- int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
- void removeBreakPoint(int id);
- void removeAllBreakPoints();
- void enableBreakPoint(int id, bool onoff);
- QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
-
- bool breakOnThrow() const { return m_breakOnThrow; }
- void setBreakOnThrow(bool onoff);
-
- Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger,
- QV4::Debugging::PauseReason reason) = 0;
- Q_INVOKABLE virtual void sourcesCollected(QV4::Debugging::Debugger *debugger,
- QStringList sources, int requestSequenceNr) = 0;
-
-protected:
- QList<Debugger *> m_debuggers;
-
- struct BreakPoint {
- QString fileName;
- int lineNr;
- bool enabled;
- QString condition;
-
- BreakPoint(): lineNr(-1), enabled(false) {}
- BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
- : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
- {}
-
- bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
- };
-
- QHash<int, BreakPoint> m_breakPoints;
- bool m_breakOnThrow;
-};
-
} // namespace Debugging
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index e1282eeca9..7424dc4e4c 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4context_p.h>
-#include <qv4value_inl_p.h>
+#include <qv4value_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
@@ -48,7 +48,7 @@
#include <qv4regexp_p.h>
#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include <qv4dateobject_p.h>
#include <qv4jsonobject_p.h>
@@ -59,7 +59,6 @@
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#include "qv4qobjectwrapper_p.h"
-#include "qv4qmlextensions_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4dataview_p.h"
@@ -197,6 +196,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
+ , hasException(false)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -211,13 +211,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
- , m_qmlExtensions(0)
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
- exceptionValue = Encode::undefined();
- hasException = false;
-
if (!factory) {
#ifdef V4_ENABLE_JIT
@@ -241,6 +237,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
+ exceptionValue = jsAlloca(1);
+ globalObject = static_cast<Object *>(jsAlloca(1));
+ jsObjects = jsAlloca(NJSObjects);
+ typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
+ typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
+ jsStrings = jsAlloca(NJSStrings);
+
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
@@ -251,208 +254,208 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
if (!recheckCStackLimits())
qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
- Scope scope(this);
-
identifierTable = new IdentifierTable(this);
classPool = new InternalClassPool;
emptyClass = new (classPool) InternalClass(this);
- id_empty = newIdentifier(QString());
- id_undefined = newIdentifier(QStringLiteral("undefined"));
- id_null = newIdentifier(QStringLiteral("null"));
- id_true = newIdentifier(QStringLiteral("true"));
- id_false = newIdentifier(QStringLiteral("false"));
- id_boolean = newIdentifier(QStringLiteral("boolean"));
- id_number = newIdentifier(QStringLiteral("number"));
- id_string = newIdentifier(QStringLiteral("string"));
- id_object = newIdentifier(QStringLiteral("object"));
- id_function = newIdentifier(QStringLiteral("function"));
- id_length = newIdentifier(QStringLiteral("length"));
- id_prototype = newIdentifier(QStringLiteral("prototype"));
- id_constructor = newIdentifier(QStringLiteral("constructor"));
- id_arguments = newIdentifier(QStringLiteral("arguments"));
- id_caller = newIdentifier(QStringLiteral("caller"));
- id_callee = newIdentifier(QStringLiteral("callee"));
- id_this = newIdentifier(QStringLiteral("this"));
- id___proto__ = newIdentifier(QStringLiteral("__proto__"));
- id_enumerable = newIdentifier(QStringLiteral("enumerable"));
- id_configurable = newIdentifier(QStringLiteral("configurable"));
- id_writable = newIdentifier(QStringLiteral("writable"));
- id_value = newIdentifier(QStringLiteral("value"));
- id_get = newIdentifier(QStringLiteral("get"));
- id_set = newIdentifier(QStringLiteral("set"));
- id_eval = newIdentifier(QStringLiteral("eval"));
- id_uintMax = newIdentifier(QStringLiteral("4294967295"));
- id_name = newIdentifier(QStringLiteral("name"));
- id_index = newIdentifier(QStringLiteral("index"));
- id_input = newIdentifier(QStringLiteral("input"));
- id_toString = newIdentifier(QStringLiteral("toString"));
- id_destroy = newIdentifier(QStringLiteral("destroy"));
- id_valueOf = newIdentifier(QStringLiteral("valueOf"));
- id_byteLength = newIdentifier(QStringLiteral("byteLength"));
- id_byteOffset = newIdentifier(QStringLiteral("byteOffset"));
- id_buffer = newIdentifier(QStringLiteral("buffer"));
- id_lastIndex = newIdentifier(QStringLiteral("lastIndex"));
-
- objectPrototype = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
-
- arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject());
-
- InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
- argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
- strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-
- m_globalObject = newObject();
- Q_ASSERT(globalObject()->d()->vtable);
+ jsStrings[String_Empty] = newIdentifier(QString());
+ jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
+ jsStrings[String_null] = newIdentifier(QStringLiteral("null"));
+ jsStrings[String_true] = newIdentifier(QStringLiteral("true"));
+ jsStrings[String_false] = newIdentifier(QStringLiteral("false"));
+ jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
+ jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
+ jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
+ jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
+ jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
+ jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
+ jsStrings[String_prototype] = newIdentifier(QStringLiteral("prototype"));
+ jsStrings[String_constructor] = newIdentifier(QStringLiteral("constructor"));
+ jsStrings[String_arguments] = newIdentifier(QStringLiteral("arguments"));
+ jsStrings[String_caller] = newIdentifier(QStringLiteral("caller"));
+ jsStrings[String_callee] = newIdentifier(QStringLiteral("callee"));
+ jsStrings[String_this] = newIdentifier(QStringLiteral("this"));
+ jsStrings[String___proto__] = newIdentifier(QStringLiteral("__proto__"));
+ jsStrings[String_enumerable] = newIdentifier(QStringLiteral("enumerable"));
+ jsStrings[String_configurable] = newIdentifier(QStringLiteral("configurable"));
+ jsStrings[String_writable] = newIdentifier(QStringLiteral("writable"));
+ jsStrings[String_value] = newIdentifier(QStringLiteral("value"));
+ jsStrings[String_get] = newIdentifier(QStringLiteral("get"));
+ jsStrings[String_set] = newIdentifier(QStringLiteral("set"));
+ jsStrings[String_eval] = newIdentifier(QStringLiteral("eval"));
+ jsStrings[String_uintMax] = newIdentifier(QStringLiteral("4294967295"));
+ jsStrings[String_name] = newIdentifier(QStringLiteral("name"));
+ jsStrings[String_index] = newIdentifier(QStringLiteral("index"));
+ jsStrings[String_input] = newIdentifier(QStringLiteral("input"));
+ jsStrings[String_toString] = newIdentifier(QStringLiteral("toString"));
+ jsStrings[String_destroy] = newIdentifier(QStringLiteral("destroy"));
+ jsStrings[String_valueOf] = newIdentifier(QStringLiteral("valueOf"));
+ jsStrings[String_byteLength] = newIdentifier(QStringLiteral("byteLength"));
+ jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
+ jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
+ jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+
+ jsObjects[ObjectProto] = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
+
+ arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
+ jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype());
+
+ InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
+ argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
+ strictArgumentsObjectClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+
+ *static_cast<Value *>(globalObject) = newObject();
+ Q_ASSERT(globalObject->d()->vtable());
initRootContext();
- stringPrototype = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype.asObject());
- numberPrototype = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype.asObject());
- booleanPrototype = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype.asObject());
- datePrototype = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype.asObject());
+ 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());
uint index;
- InternalClass *functionProtoClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable, &index);
+ InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject());
- functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ jsObjects[FunctionProto] = memoryManager->alloc<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);
+ simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name);
- simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length);
- protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index);
+ protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- regExpPrototype = memoryManager->alloc<RegExpPrototype>(this);
- regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
+ jsObjects[RegExpProto] = memoryManager->alloc<RegExpPrototype>(this);
+ regExpExecArrayClass = arrayClass->addMember(id_index(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
- regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
+ regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- errorPrototype = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype.asObject());
- evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype.asObject());
- rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype.asObject());
- referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype.asObject());
- syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype.asObject());
- typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype.asObject());
- uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype.asObject());
+ 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());
- variantPrototype = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype.asObject());
- Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d());
+ jsObjects[VariantProto] = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype());
+ Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
- sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject()));
+ Scope scope(this);
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype()));
ScopedContext global(scope, rootContext());
- objectCtor = memoryManager->alloc<ObjectCtor>(global);
- stringCtor = memoryManager->alloc<StringCtor>(global);
- numberCtor = memoryManager->alloc<NumberCtor>(global);
- booleanCtor = memoryManager->alloc<BooleanCtor>(global);
- arrayCtor = memoryManager->alloc<ArrayCtor>(global);
- functionCtor = memoryManager->alloc<FunctionCtor>(global);
- dateCtor = memoryManager->alloc<DateCtor>(global);
- regExpCtor = memoryManager->alloc<RegExpCtor>(global);
- errorCtor = memoryManager->alloc<ErrorCtor>(global);
- evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global);
- rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global);
- referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global);
- syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global);
- typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global);
- uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global);
-
- static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject());
- static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject());
- static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());
- static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject());
- static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject());
- static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject());
- static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject());
- static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject());
- static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject());
- static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject());
- static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject());
- static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject());
- static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject());
- static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject());
- static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject());
-
- static_cast<VariantPrototype *>(variantPrototype.asObject())->init();
- sequencePrototype.cast<SequencePrototype>()->init();
+ 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);
+
+ static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
+ static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
+ static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
+ static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
+ static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
+ static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
+ static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
+ static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
+ static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+
+ static_cast<VariantPrototype *>(variantPrototype())->init();
+ sequencePrototype()->cast<SequencePrototype>()->init();
// typed arrays
- arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global);
- arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->alloc<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype());
+ static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- dataViewCtor = memoryManager->alloc<DataViewCtor>(global);
- dataViewPrototype = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject());
+ jsObjects[DataView_Ctor] = memoryManager->alloc<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype());
+ static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
+ jsObjects[ValueTypeProto] = (Heap::Base *) 0;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
- typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject()));
+ 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));
+ typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
//
// set up the global object
//
- rootContext()->global = globalObject()->d();
- rootContext()->callData->thisObject = globalObject();
- Q_ASSERT(globalObject()->d()->vtable);
-
- globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
-
- globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor);
+ rootContext()->d()->global = globalObject->d();
+ rootContext()->d()->callData->thisObject = globalObject;
+ Q_ASSERT(globalObject->d()->vtable());
+
+ globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
+
+ 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].asFunctionObject()->name())->toQString(), typedArrayCtors[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->alloc<MathObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
- 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));
+ 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));
- evalFunction = memoryManager->alloc<EvalFunction>(global);
- globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
+ jsObjects[Eval_Function] = memoryManager->alloc<EvalFunction>(global);
+ globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
- globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
+ globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
ScopedString name(scope, newString(QStringLiteral("thrower")));
- thrower = BuiltinFunction::create(global, name, ::throwTypeError);
+ jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
@@ -471,7 +474,6 @@ ExecutionEngine::~ExecutionEngine()
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
unit->unlink();
- delete m_qmlExtensions;
emptyClass->destroy();
delete classPool;
delete bumperPointerAllocator;
@@ -504,10 +506,10 @@ void ExecutionEngine::initRootContext()
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
r->d()->callData->tag = QV4::Value::_Integer_Type;
r->d()->callData->argc = 0;
- r->d()->callData->thisObject = globalObject();
+ r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
- m_rootContext = r->d();
+ jsObjects[RootContect] = r;
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -519,7 +521,7 @@ Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
{
Scope scope(this);
Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->callData;
+ g->d()->callData = rootContext()->d()->callData;
Q_ASSERT(currentContext() == g->d());
return g->d();
@@ -551,10 +553,10 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
return identifierTable->insertString(text);
}
-Heap::Object *ExecutionEngine::newStringObject(const Value &value)
+Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
+ Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, string));
return object->d();
}
@@ -653,7 +655,7 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype.asObject(), value));
+ ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype(), value));
return object->d();
}
@@ -723,7 +725,7 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
return obj->d();
}
-Heap::Object *ExecutionEngine::qmlContextObject() const
+Heap::QmlContext *ExecutionEngine::qmlContext() const
{
Heap::ExecutionContext *ctx = currentContext();
@@ -740,8 +742,28 @@ Heap::Object *ExecutionEngine::qmlContextObject() const
if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
return 0;
- Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation);
- return static_cast<Heap::CallContext *>(ctx)->activation;
+ return static_cast<Heap::QmlContext *>(ctx);
+}
+
+Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+ Q_ASSERT(ctx->qml);
+ return ctx->qml;
+}
+
+QObject *ExecutionEngine::qmlScopeObject() const
+{
+ return qmlContextObject()->scopeObject;
+}
+
+QQmlContextData *ExecutionEngine::callingQmlContext() const
+{
+ Heap::QmlContextWrapper *w = qmlContextObject();
+
+ return w ? w->context.contextData() : 0;
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -777,7 +799,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext()->lineNumber;
+ frame.line = rootContext()->d()->lineNumber;
frame.column = -1;
stack.append(frame);
@@ -889,8 +911,6 @@ void ExecutionEngine::markObjects()
{
identifierTable->mark(this);
- globalObject()->mark(this);
-
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
@@ -904,98 +924,11 @@ void ExecutionEngine::markObjects()
Q_ASSERT(c->inUse());
if (!c->isMarked()) {
c->setMarkBit();
- c->gcGetVtable()->markObjects(c, this);
+ c->vtable()->markObjects(c, this);
}
c = c->parent;
}
- id_empty->mark(this);
- id_undefined->mark(this);
- id_null->mark(this);
- id_true->mark(this);
- id_false->mark(this);
- id_boolean->mark(this);
- id_number->mark(this);
- id_string->mark(this);
- id_object->mark(this);
- id_function->mark(this);
- id_length->mark(this);
- id_prototype->mark(this);
- id_constructor->mark(this);
- id_arguments->mark(this);
- id_caller->mark(this);
- id_callee->mark(this);
- id_this->mark(this);
- id___proto__->mark(this);
- id_enumerable->mark(this);
- id_configurable->mark(this);
- id_writable->mark(this);
- id_value->mark(this);
- id_get->mark(this);
- id_set->mark(this);
- id_eval->mark(this);
- id_uintMax->mark(this);
- id_name->mark(this);
- id_index->mark(this);
- id_input->mark(this);
- id_toString->mark(this);
- id_destroy->mark(this);
- id_valueOf->mark(this);
- id_byteLength->mark(this);
- id_byteOffset->mark(this);
- id_buffer->mark(this);
- id_lastIndex->mark(this);
-
- objectCtor.mark(this);
- stringCtor.mark(this);
- numberCtor.mark(this);
- booleanCtor.mark(this);
- arrayCtor.mark(this);
- functionCtor.mark(this);
- dateCtor.mark(this);
- regExpCtor.mark(this);
- errorCtor.mark(this);
- evalErrorCtor.mark(this);
- rangeErrorCtor.mark(this);
- referenceErrorCtor.mark(this);
- syntaxErrorCtor.mark(this);
- typeErrorCtor.mark(this);
- uRIErrorCtor.mark(this);
- arrayBufferCtor.mark(this);
- dataViewCtor.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayCtors[i].mark(this);
-
- objectPrototype.mark(this);
- arrayPrototype.mark(this);
- stringPrototype.mark(this);
- numberPrototype.mark(this);
- booleanPrototype.mark(this);
- datePrototype.mark(this);
- functionPrototype.mark(this);
- regExpPrototype.mark(this);
- errorPrototype.mark(this);
- evalErrorPrototype.mark(this);
- rangeErrorPrototype.mark(this);
- referenceErrorPrototype.mark(this);
- syntaxErrorPrototype.mark(this);
- typeErrorPrototype.mark(this);
- uRIErrorPrototype.mark(this);
- variantPrototype.mark(this);
- sequencePrototype.mark(this);
-
- arrayBufferPrototype.mark(this);
- dataViewPrototype.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayPrototype[i].mark(this);
-
- exceptionValue.mark(this);
-
- thrower->mark(this);
-
- if (m_qmlExtensions)
- m_qmlExtensions->markObjects(this);
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
@@ -1003,13 +936,6 @@ void ExecutionEngine::markObjects()
(*it)->markObjects(this);
}
-QmlExtensions *ExecutionEngine::qmlExtensions()
-{
- if (!m_qmlExtensions)
- m_qmlExtensions = new QmlExtensions;
- return m_qmlExtensions;
-}
-
ReturnedValue ExecutionEngine::throwError(const Value &value)
{
// we can get in here with an exception already set, as the runtime
@@ -1020,7 +946,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
return Encode::undefined();
hasException = true;
- exceptionValue = value;
+ *exceptionValue = value;
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
@@ -1041,8 +967,8 @@ ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
*trace = exceptionStackTrace;
exceptionStackTrace.clear();
hasException = false;
- ReturnedValue res = exceptionValue.asReturnedValue();
- exceptionValue = Primitive::emptyValue();
+ ReturnedValue res = exceptionValue->asReturnedValue();
+ *exceptionValue = Primitive::emptyValue();
return res;
}
@@ -1175,7 +1101,7 @@ bool ExecutionEngine::recheckCStackLimits()
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = 0);
static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
const QByteArray &targetType,
void **result);
@@ -1198,7 +1124,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
Q_ASSERT (!value.isEmpty());
QV4::Scope scope(e);
- if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
return v->d()->data;
if (typeHint == QVariant::Bool)
@@ -1210,10 +1136,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (typeHint == qMetaTypeId<QJSValue>())
return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
- if (value.asObject()) {
+ if (value.as<Object>()) {
QV4::ScopedObject object(scope, value);
if (typeHint == QMetaType::QJsonObject
- && !value.asArrayObject() && !value.asFunctionObject()) {
+ && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
@@ -1229,7 +1155,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QV4::SequencePrototype::toVariant(object);
}
- if (value.asArrayObject()) {
+ if (value.as<ArrayObject>()) {
QV4::ScopedArrayObject a(scope, value);
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
@@ -1267,11 +1193,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
- if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
+ if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
return ld->d()->locale;
- if (QV4::DateObject *d = value.asDateObject())
+ if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
- if (QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -1287,7 +1213,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return objectToVariant(e, o, visitedObjects);
}
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects)
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
{
Q_ASSERT(o);
@@ -1298,7 +1224,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
- if (o->asArrayObject())
+ if (o->as<ArrayObject>())
return QVariantList();
return QVariantMap();
}
@@ -1306,7 +1232,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
QVariant result;
- if (o->asArrayObject()) {
+ if (o->as<ArrayObject>()) {
QV4::Scope scope(e);
QV4::ScopedArrayObject a(scope, o->asReturnedValue());
QV4::ScopedValue v(scope);
@@ -1319,7 +1245,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
}
result = list;
- } else if (!o->asFunctionObject()) {
+ } else if (!o->as<FunctionObject>()) {
QVariantMap map;
QV4::Scope scope(e);
QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
@@ -1497,7 +1423,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newVariantObject(variant));
}
-QVariantMap ExecutionEngine::variantMapFromJS(Object *o)
+QVariantMap ExecutionEngine::variantMapFromJS(const Object *o)
{
return objectToVariant(this, o).toMap();
}
@@ -1630,93 +1556,90 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-void ExecutionEngine::assertObjectBelongsToEngine(const Value &v)
+void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
{
- Q_UNUSED(v);
- Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this);
- Q_UNUSED(v);
+ Q_ASSERT(!baseObject.vtable()->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
+ Q_UNUSED(baseObject);
}
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
-bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *data)
+bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
{
- QV4::Scope scope(this);
-
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value.toBoolean();
+ *reinterpret_cast<bool*>(data) = value->toBoolean();
return true;
case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value.toInt32();
+ *reinterpret_cast<int*>(data) = value->toInt32();
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value.toUInt32();
+ *reinterpret_cast<uint*>(data) = value->toUInt32();
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value.toNumber();
+ *reinterpret_cast<double*>(data) = value->toNumber();
return true;
case QMetaType::QString:
- if (value.isUndefined() || value.isNull())
+ if (value->isUndefined() || value->isNull())
*reinterpret_cast<QString*>(data) = QString();
else
- *reinterpret_cast<QString*>(data) = value.toQString();
+ *reinterpret_cast<QString*>(data) = value->toQString();
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value.toNumber();
+ *reinterpret_cast<float*>(data) = value->toNumber();
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value.toInt32());
+ *reinterpret_cast<short*>(data) = short(value->toInt32());
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
+ *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value.toInt32());
+ *reinterpret_cast<char*>(data) = char(value->toInt32());
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
return true;
case QMetaType::QChar:
- if (value.isString()) {
- QString str = value.stringValue()->toQString();
+ if (value->isString()) {
+ QString str = value->stringValue()->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
}
return true;
case QMetaType::QDateTime:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
case QMetaType::QRegExp:
- if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
case QMetaType::QObjectStar: {
- QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value.isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
+ const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
+ if (qobjectWrapper || value->isNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(this, *value);
return true;
} break;
}
case QMetaType::QStringList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
@@ -1724,15 +1647,15 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariantList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
- *reinterpret_cast<QVariantList *>(data) = scope.engine->toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *reinterpret_cast<QVariantList *>(data) = toVariant(*a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
}
case QMetaType::QVariantMap: {
- QV4::ScopedObject o(scope, value);
+ const QV4::Object *o = value->as<QV4::Object>();
if (o) {
*reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
return true;
@@ -1740,20 +1663,19 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = scope.engine->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ *reinterpret_cast<QVariant*>(data) = toVariant(*value, /*typeHint*/-1, /*createJSValueForObjects*/false);
return true;
case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(*value);
return true;
case QMetaType::QJsonObject: {
- QV4::ScopedObject o(scope, value);
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->as<Object>());
return true;
}
case QMetaType::QJsonArray: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<ArrayObject>();
if (a) {
- *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
+ *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
return true;
}
break;
@@ -1763,7 +1685,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
{
- QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
+ const QQmlValueTypeWrapper *vtw = value->as<QQmlValueTypeWrapper>();
if (vtw && vtw->typeId() == type) {
return vtw->toGadget(data);
}
@@ -1788,21 +1710,22 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
#endif
- // Try to use magic; for compatibility with qscriptvalue_cast.
+ // Try to use magic; for compatibility with qjsvalue_cast.
QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(this, *value, name, reinterpret_cast<void* *>(data)))
return true;
- if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
+ if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value.as<QV4::VariantObject>()->d()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
- } else if (value.isObject()) {
+ } else if (value->isObject()) {
// Look in the prototype chain.
- QV4::ScopedObject proto(scope, value.objectValue()->prototype());
+ QV4::Scope scope(this);
+ QV4::ScopedObject proto(scope, value->objectValue()->prototype());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1812,7 +1735,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(scope.engine, p))
+ if (QObject *qobject = qtObjectFromJS(this, p))
canCast = qobject->qt_metacast(className) != 0;
}
if (canCast) {
@@ -1826,11 +1749,11 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
proto = proto->prototype();
}
}
- } else if (value.isNull() && name.endsWith('*')) {
+ } else if (value->isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = 0;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value.asReturnedValue());
+ *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
return true;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c0c88abaa5..9f44745e4c 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -37,6 +37,7 @@
#include "private/qv4isel_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4internalclass_p.h"
#include <private/qintrusivelist_p.h>
namespace WTF {
@@ -50,6 +51,7 @@ class QV8Engine;
class QQmlError;
class QJSEngine;
class QQmlEngine;
+class QQmlContextData;
namespace QV4 {
namespace Debugging {
@@ -80,8 +82,6 @@ public:
Value *jsStackTop;
quint32 hasException;
- Heap::GlobalContext *m_rootContext;
- Heap::GlobalContext *rootContext() const { return m_rootContext; }
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
@@ -106,14 +106,19 @@ public:
--jsStackTop;
return jsStackTop->heapObject();
}
+ Value *jsAlloca(int nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ memset(ptr, 0, nValues*sizeof(Value));
+ return ptr;
+ }
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
- Value m_globalObject;
- Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
+ Object *globalObject;
Function *globalCode;
@@ -121,47 +126,97 @@ public:
QQmlEngine *qmlEngine() const;
QV8Engine *v8Engine;
- Value objectCtor;
- Value stringCtor;
- Value numberCtor;
- Value booleanCtor;
- Value arrayCtor;
- Value functionCtor;
- Value dateCtor;
- Value regExpCtor;
- Value errorCtor;
- Value evalErrorCtor;
- Value rangeErrorCtor;
- Value referenceErrorCtor;
- Value syntaxErrorCtor;
- Value typeErrorCtor;
- Value uRIErrorCtor;
- Value arrayBufferCtor;
- Value dataViewCtor;
- enum { NTypedArrayTypes = 9 }; // avoid header dependency
- Value typedArrayCtors[NTypedArrayTypes];
-
- Value objectPrototype;
- Value arrayPrototype;
- Value stringPrototype;
- Value numberPrototype;
- Value booleanPrototype;
- Value datePrototype;
- Value functionPrototype;
- Value regExpPrototype;
- Value errorPrototype;
- Value evalErrorPrototype;
- Value rangeErrorPrototype;
- Value referenceErrorPrototype;
- Value syntaxErrorPrototype;
- Value typeErrorPrototype;
- Value uRIErrorPrototype;
- Value variantPrototype;
- Value sequencePrototype;
-
- Value arrayBufferPrototype;
- Value dataViewPrototype;
- Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+ enum JSObjects {
+ RootContect,
+ ObjectProto,
+ ArrayProto,
+ StringProto,
+ NumberProto,
+ BooleanProto,
+ DateProto,
+ FunctionProto,
+ RegExpProto,
+ ErrorProto,
+ EvalErrorProto,
+ RangeErrorProto,
+ ReferenceErrorProto,
+ SyntaxErrorProto,
+ TypeErrorProto,
+ URIErrorProto,
+ VariantProto,
+ SequenceProto,
+ ArrayBufferProto,
+ DataViewProto,
+ ValueTypeProto,
+
+ Object_Ctor,
+ String_Ctor,
+ Number_Ctor,
+ Boolean_Ctor,
+ Array_Ctor,
+ Function_Ctor,
+ Date_Ctor,
+ RegExp_Ctor,
+ Error_Ctor,
+ EvalError_Ctor,
+ RangeError_Ctor,
+ ReferenceError_Ctor,
+ SyntaxError_Ctor,
+ TypeError_Ctor,
+ URIError_Ctor,
+ ArrayBuffer_Ctor,
+ DataView_Ctor,
+
+ Eval_Function,
+ ThrowerObject,
+ NJSObjects
+ };
+ Value *jsObjects;
+ enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
+
+ GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContect); }
+ 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); }
+ FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
+ FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
+ FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
+ FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
+ FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
+ FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
+ FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
+ FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
+ FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
+ FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
+ FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
+ FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
+ FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
+ FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
+ FunctionObject *typedArrayCtors;
+
+ Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
+ Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
+ Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
+ Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
+ Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
+ Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
+ Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
+ Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
+ Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
+ Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
+ Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
+ Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
+ Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
+ Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
+ Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
+ Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
+ Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
+
+ Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
+ Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
+ Object *typedArrayPrototype;
+
+ Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
InternalClassPool *classPool;
InternalClass *emptyClass;
@@ -177,48 +232,89 @@ public:
InternalClass *argumentsObjectClass;
InternalClass *strictArgumentsObjectClass;
- Heap::EvalFunction *evalFunction;
- Heap::FunctionObject *thrower;
+ EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
+ FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
Property *argumentsAccessors;
int nArgumentsAccessors;
- StringValue id_empty;
- StringValue id_undefined;
- StringValue id_null;
- StringValue id_true;
- StringValue id_false;
- StringValue id_boolean;
- StringValue id_number;
- StringValue id_string;
- StringValue id_object;
- StringValue id_function;
- StringValue id_length;
- StringValue id_prototype;
- StringValue id_constructor;
- StringValue id_arguments;
- StringValue id_caller;
- StringValue id_callee;
- StringValue id_this;
- StringValue id___proto__;
- StringValue id_enumerable;
- StringValue id_configurable;
- StringValue id_writable;
- StringValue id_value;
- StringValue id_get;
- StringValue id_set;
- StringValue id_eval;
- StringValue id_uintMax;
- StringValue id_name;
- StringValue id_index;
- StringValue id_input;
- StringValue id_toString;
- StringValue id_destroy;
- StringValue id_valueOf;
- StringValue id_byteLength;
- StringValue id_byteOffset;
- StringValue id_buffer;
- StringValue id_lastIndex;
+ enum JSStrings {
+ String_Empty,
+ String_undefined,
+ String_null,
+ String_true,
+ String_false,
+ String_boolean,
+ String_number,
+ String_string,
+ String_object,
+ String_function,
+ String_length,
+ String_prototype,
+ String_constructor,
+ String_arguments,
+ String_caller,
+ String_callee,
+ String_this,
+ String___proto__,
+ String_enumerable,
+ String_configurable,
+ String_writable,
+ String_value,
+ String_get,
+ String_set,
+ String_eval,
+ String_uintMax,
+ String_name,
+ String_index,
+ String_input,
+ String_toString,
+ String_destroy,
+ String_valueOf,
+ String_byteLength,
+ String_byteOffset,
+ String_buffer,
+ String_lastIndex,
+ NJSStrings
+ };
+ Value *jsStrings;
+
+ String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
+ String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
+ String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
+ String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
+ String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
+ String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
+ String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
+ String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
+ String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
+ String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
+ String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
+ String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
+ String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
+ String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
+ String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
+ String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
+ String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
+ String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
+ String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
+ String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
+ String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
+ String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
+ String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
+ String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
+ String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
+ String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
+ String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
+ String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
+ String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
+ String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
+ String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
+ String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
+ String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
+ String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
+ String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
+ String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
QSet<CompiledData::CompilationUnit*> compilationUnits;
@@ -261,7 +357,7 @@ public:
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
- Heap::Object *newStringObject(const Value &value);
+ Heap::Object *newStringObject(const String *string);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
@@ -291,7 +387,11 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
- Heap::Object *qmlContextObject() const;
+ Heap::QmlContext *qmlContext() const;
+ QV4::Heap::QmlContextWrapper *qmlContextObject() const;
+ QObject *qmlScopeObject() const;
+ QQmlContextData *callingQmlContext() const;
+
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -305,12 +405,10 @@ public:
InternalClass *newClass(const InternalClass &other);
- QmlExtensions *qmlExtensions();
-
bool recheckCStackLimits();
// Exception handling
- Value exceptionValue;
+ Value *exceptionValue;
StackTrace exceptionStackTrace;
ReturnedValue throwError(const Value &value);
@@ -335,15 +433,12 @@ public:
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
QV4::ReturnedValue fromVariant(const QVariant &);
- QVariantMap variantMapFromJS(QV4::Object *o);
+ QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value &value, int type, void *data);
+ bool metaTypeFromJS(const Value *value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- void assertObjectBelongsToEngine(const Value &v);
-
-private:
- QmlExtensions *m_qmlExtensions;
+ void assertObjectBelongsToEngine(const Heap::Base &baseObject);
};
inline void ExecutionEngine::pushContext(CallContext *context)
@@ -376,29 +471,26 @@ Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
}
-// ### Remove me
inline
-void Managed::mark(QV4::ExecutionEngine *engine)
+void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
- if (markBit())
+ if (isMarked())
return;
#ifndef QT_NO_DEBUG
engine->assertObjectBelongsToEngine(*this);
#endif
- d()->setMarkBit();
- engine->pushForGC(d());
+ setMarkBit();
+ engine->pushForGC(this);
}
-
-inline
-void Heap::Base::mark(QV4::ExecutionEngine *engine)
+inline void Value::mark(ExecutionEngine *e)
{
- Q_ASSERT(inUse());
- if (isMarked())
+ if (!_val)
return;
- setMarkBit();
- engine->pushForGC(this);
+ Managed *m = as<Managed>();
+ if (m)
+ m->d()->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9034dee6a0..a6c2a25b91 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -33,11 +33,14 @@
#include "qv4errorobject_p.h"
-#include "qv4mm_p.h"
+#include <QtCore/qnumeric.h>
+#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include "qv4string_p.h"
+#include <private/qv4mm_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
@@ -179,57 +182,57 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError)
+ : 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.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError)
+ : 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.asObject(), message, EvalError)
+ : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype(), message, EvalError)
{
}
Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
{
}
Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
{
}
Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError)
+ : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
{
}
Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+ : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
{
}
Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype.asObject(), message, URIError)
+ : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype(), message, URIError)
{
}
@@ -251,16 +254,16 @@ Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
{
}
-ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return Encode(scope.engine->newErrorObject(v));
}
-ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
+ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
{
- return static_cast<Object *>(that)->construct(callData);
+ return static_cast<const Object *>(that)->construct(callData);
}
Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
@@ -268,9 +271,9 @@ Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<EvalErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const EvalErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -280,9 +283,9 @@ Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<RangeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const RangeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -292,9 +295,9 @@ Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ReferenceErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -304,9 +307,9 @@ Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<SyntaxErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -316,9 +319,9 @@ Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<TypeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const TypeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -328,9 +331,9 @@ Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<URIErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const URIErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
}
@@ -340,10 +343,10 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
Scope scope(engine);
ScopedString s(scope);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = obj));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ 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(engine->id_toString(), method_toString, 0);
obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
}
@@ -351,18 +354,18 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
- ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
+ ScopedValue name(scope, o->get(ctx->d()->engine->id_name()));
QString qname;
if (name->isUndefined())
- qname = QString::fromLatin1("Error");
+ qname = QStringLiteral("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message")));
ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 071f5b8c9a..e0fbcb4d8d 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -62,7 +62,7 @@ struct ErrorObject : Object {
ErrorType errorType;
StackTrace stackTrace;
- String *stack;
+ Pointer<String> stack;
};
struct EvalErrorObject : ErrorObject {
@@ -141,8 +141,8 @@ struct ErrorObject: Object {
};
template<>
-inline ErrorObject *value_cast(const Value &v) {
- return v.asErrorObject();
+inline const ErrorObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0;
}
struct EvalErrorObject: ErrorObject {
@@ -183,50 +183,50 @@ struct ErrorCtor: FunctionObject
{
V4_OBJECT2(ErrorCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct EvalErrorCtor: ErrorCtor
{
V4_OBJECT2(EvalErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
V4_OBJECT2(RangeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
V4_OBJECT2(TypeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
V4_OBJECT2(URIErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index be63b31e1e..98a4490211 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -34,10 +34,10 @@
#include "qv4function_p.h"
#include "qv4managed_p.h"
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 0a12d013ac..da01592c0d 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4function_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4arrayobject_p.h"
#include "qv4scopedvalue_p.h"
@@ -63,7 +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.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -73,7 +73,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.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -84,7 +84,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.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -95,7 +95,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.asObject())
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
, scope(scope)
, function(Q_NULLPTR)
{
@@ -106,7 +106,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.asObject())
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
, scope(scope->d())
, function(Q_NULLPTR)
{
@@ -117,7 +117,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.asObject())
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
, scope(scope)
, function(Q_NULLPTR)
{
@@ -129,7 +129,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
- , scope(ic->engine->rootContext())
+ , scope(ic->engine->rootContext()->d())
, function(Q_NULLPTR)
{
Scope scope(ic->engine);
@@ -152,7 +152,7 @@ void FunctionObject::init(String *n, bool createProto)
ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
if (createProto) {
- ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject()));
+ 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();
@@ -161,12 +161,12 @@ void FunctionObject::init(String *n, bool createProto)
}
ScopedValue v(s, n);
- defineReadonlyProperty(s.engine->id_name, v);
+ defineReadonlyProperty(s.engine->id_name(), v);
}
-ReturnedValue FunctionObject::name()
+ReturnedValue FunctionObject::name() const
{
- return get(scope()->engine->id_name);
+ return get(scope()->engine->id_name());
}
@@ -177,13 +177,12 @@ ReturnedValue FunctionObject::newInstance()
return construct(callData);
}
-ReturnedValue FunctionObject::construct(Managed *that, CallData *)
+ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
{
- static_cast<FunctionObject *>(that)->internalClass()->engine->throwTypeError();
- return Encode::undefined();
+ return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(Managed *, CallData *)
+ReturnedValue FunctionObject::call(const Managed *, CallData *)
{
return Encode::undefined();
}
@@ -209,12 +208,12 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco
bool FunctionObject::isBinding() const
{
- return d()->vtable == QQmlBindingFunction::staticVTable();
+ return d()->vtable() == QQmlBindingFunction::staticVTable();
}
bool FunctionObject::isBoundFunction() const
{
- return d()->vtable == BoundFunction::staticVTable();
+ return d()->vtable() == BoundFunction::staticVTable();
}
QQmlSourceLocation FunctionObject::sourceLocation() const
@@ -237,10 +236,10 @@ Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
}
// 15.3.2
-ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<Object *>(that)->engine());
- Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that));
+ 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;
@@ -287,7 +286,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
}
// 15.3.1: This is equivalent to new Function(...)
-ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -304,12 +303,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- defineReadonlyProperty(engine->id_length, Primitive::fromInt32(0));
+ defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
defineDefaultProperty(QStringLiteral("call"), method_call, 1);
defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
@@ -318,7 +317,7 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
- FunctionObject *fun = ctx->thisObject().asFunctionObject();
+ FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
if (!fun)
return ctx->engine()->throwTypeError();
@@ -328,7 +327,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -370,7 +369,7 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -409,15 +408,15 @@ Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *fun
{
}
-ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
@@ -441,15 +440,15 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
return obj.asReturnedValue();
}
-ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
ScopedContext context(scope, v4->currentContext());
Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
@@ -458,7 +457,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
+ QmlContextWrapper::registerQmlDependencies(scope.engine, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -466,7 +465,7 @@ ReturnedValue ScriptFunction::call(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.asObject())
+ : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype())
{
this->scope = scope->d();
@@ -481,7 +480,7 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (createProto) {
ScopedString name(s, function->name());
f->init(name, createProto);
- f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
} else {
f->ensureMemberIndex(s.engine, Index_Length);
memberData->data[Index_Name] = function->name();
@@ -490,22 +489,22 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (scope->d()->strictMode) {
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(scope->d()->engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(scope->d()->engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
-ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
@@ -514,7 +513,10 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#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
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -536,20 +538,23 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
return result.asReturnedValue();
}
-ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<SimpleScriptFunction *>(that)->internalClass()->engine;
+ ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#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
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -575,7 +580,7 @@ Heap::Object *SimpleScriptFunction::protoForConstructor()
ScopedObject p(scope, protoProperty());
if (p)
return p->d();
- return scope.engine->objectPrototype.asObject()->d();
+ return scope.engine->objectPrototype()->d();
}
@@ -588,14 +593,14 @@ Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String
{
}
-ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
+ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *)
{
- return static_cast<BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+ return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
}
-ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
{
- BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
+ const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
@@ -605,7 +610,10 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#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
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
@@ -614,9 +622,9 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
return f->d()->code(sctx);
}
-ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
{
- IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
+ const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
@@ -626,7 +634,10 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+#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
+#endif
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
@@ -650,24 +661,24 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb
Scope s(scope);
ScopedObject f(s, this);
- ScopedValue l(s, target->get(s.engine->id_length));
+ ScopedValue l(s, target->get(s.engine->id_length()));
int len = l->toUInt32();
if (boundArgs)
len -= boundArgs->size();
if (len < 0)
len = 0;
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -685,9 +696,9 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
return t->call(callData);
}
-ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 252ff40a1a..2c6a195746 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -36,7 +36,7 @@
#include "qv4object_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +65,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
bool needsActivation() const { return function ? function->needsActivation() : false; }
- ExecutionContext *scope;
+ Pointer<ExecutionContext> scope;
Function *function;
};
@@ -102,9 +102,9 @@ struct ScriptFunction : SimpleScriptFunction {
struct BoundFunction : FunctionObject {
BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
- FunctionObject *target;
+ Pointer<FunctionObject> target;
Value boundThis;
- MemberData *boundArgs;
+ Pointer<MemberData> boundArgs;
};
}
@@ -117,12 +117,12 @@ struct Q_QML_EXPORT FunctionObject: Object {
Q_MANAGED_TYPE(FunctionObject)
V4_NEEDS_DESTROY
- Heap::ExecutionContext *scope() { return d()->scope; }
- Function *function() { return d()->function; }
+ Heap::ExecutionContext *scope() const { return d()->scope; }
+ Function *function() const { return d()->function; }
- ReturnedValue name();
- unsigned int formalParameterCount() { return d()->formalParameterCount(); }
- unsigned int varCount() { return d()->varCount(); }
+ ReturnedValue name() const;
+ unsigned int formalParameterCount() const { return d()->formalParameterCount(); }
+ unsigned int varCount() const { return d()->varCount(); }
void init(String *name, bool createProto);
@@ -130,12 +130,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::construct;
using Object::call;
- static ReturnedValue construct(Managed *that, CallData *);
- static ReturnedValue call(Managed *that, CallData *d);
-
- static FunctionObject *cast(const Value &v) {
- return v.asFunctionObject();
- }
+ static ReturnedValue construct(const Managed *that, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
@@ -152,16 +148,17 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
template<>
-inline FunctionObject *value_cast(const Value &v) {
- return v.asFunctionObject();
+inline const FunctionObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0;
}
+
struct FunctionCtor: FunctionObject
{
V4_OBJECT2(FunctionCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct FunctionPrototype: FunctionObject
@@ -184,20 +181,20 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
}
- static ReturnedValue construct(Managed *, CallData *);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct IndexedBuiltinFunction: FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *)
+ static ReturnedValue construct(const Managed *m, CallData *)
{
- return static_cast<IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
+ return static_cast<const IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
}
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
@@ -212,8 +209,8 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
Heap::Object *protoForConstructor();
};
@@ -221,8 +218,8 @@ struct SimpleScriptFunction: FunctionObject {
struct ScriptFunction: SimpleScriptFunction {
V4_OBJECT2(ScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -234,12 +231,12 @@ struct BoundFunction: FunctionObject {
return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
}
- Heap::FunctionObject *target() { return d()->target; }
+ Heap::FunctionObject *target() const { return d()->target; }
Value boundThis() const { return d()->boundThis; }
Heap::MemberData *boundArgs() const { return d()->boundArgs; }
- static ReturnedValue construct(Managed *, CallData *d);
- static ReturnedValue call(Managed *that, CallData *dd);
+ static ReturnedValue construct(const Managed *, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *dd);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4b08194b60..759c6795e2 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -88,6 +88,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#define V4_ENABLE_JIT
#endif
+#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+#define V4_ENABLE_JIT
#endif
// Black list some platforms
@@ -168,7 +170,7 @@ struct Property;
struct Value;
struct Lookup;
struct ArrayData;
-struct ManagedVTable;
+struct VTable;
struct BooleanObject;
struct NumberObject;
@@ -211,7 +213,6 @@ class WeakValue;
struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-struct QmlExtensions;
namespace Global {
enum {
@@ -277,8 +278,6 @@ struct PropertyAttributes
setConfigurable(!(f & Attr_NotConfigurable));
}
}
- PropertyAttributes(const PropertyAttributes &other) : m_all(other.m_all) {}
- PropertyAttributes & operator=(const PropertyAttributes &other) { m_all = other.m_all; return *this; }
void setType(Type t) { m_type = t; type_set = true; }
Type type() const { return type_set ? (Type)m_type : Generic; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 8e33cec57f..ec7b9b3f7d 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -32,13 +32,15 @@
****************************************************************************/
#include "qv4globalobject_p.h"
-#include "qv4mm_p.h"
-#include "qv4value_inl_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
#include "qv4context_p.h"
#include "qv4function_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4script_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -47,6 +49,7 @@
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
+#include "private/qtools_p.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
@@ -56,25 +59,8 @@
#include <wtf/MathExtras.h>
using namespace QV4;
-
-
-static inline char toHex(char c)
-{
- static const char hexnumbers[] = "0123456789ABCDEF";
- return hexnumbers[c & 0xf];
-}
-
-static int fromHex(QChar ch)
-{
- ushort c = ch.unicode();
- if ((c >= '0') && (c <= '9'))
- return c - '0';
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
- return -1;
-}
+using QtMiscUtils::toHexUpper;
+using QtMiscUtils::fromHex;
static QString escape(const QString &input)
{
@@ -93,16 +79,16 @@ static QString escape(const QString &input)
output.append(QChar(uc));
} else {
output.append('%');
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
} else {
output.append('%');
output.append('u');
- output.append(QLatin1Char(toHex(uc >> 12)));
- output.append(QLatin1Char(toHex(uc >> 8)));
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 12)));
+ output.append(QLatin1Char(toHexUpper(uc >> 8)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
}
return output;
@@ -119,10 +105,10 @@ static QString unescape(const QString &input)
if ((c == '%') && (i + 1 < length)) {
QChar a = input.at(i);
if ((a == 'u') && (i + 4 < length)) {
- int d3 = fromHex(input.at(i+1));
- int d2 = fromHex(input.at(i+2));
- int d1 = fromHex(input.at(i+3));
- int d0 = fromHex(input.at(i+4));
+ int d3 = fromHex(input.at(i+1).unicode());
+ int d2 = fromHex(input.at(i+2).unicode());
+ int d1 = fromHex(input.at(i+3).unicode());
+ int d0 = fromHex(input.at(i+4).unicode());
if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) {
ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0);
result.append(QChar(uc));
@@ -131,8 +117,8 @@ static QString unescape(const QString &input)
result.append(c);
}
} else {
- int d1 = fromHex(a);
- int d0 = fromHex(input.at(i+1));
+ int d1 = fromHex(a.unicode());
+ int d0 = fromHex(input.at(i+1).unicode());
if ((d1 != -1) && (d0 != -1)) {
c = (d1 << 4) | d0;
i += 2;
@@ -153,8 +139,8 @@ static const char uriUnescapedReserved[] = "-_.!~*'();/?:@&=+$,#";
static void addEscapeSequence(QString &output, uchar ch)
{
output.append(QLatin1Char('%'));
- output.append(QLatin1Char(toHex(ch >> 4)));
- output.append(QLatin1Char(toHex(ch & 0xf)));
+ output.append(QLatin1Char(toHexUpper(ch >> 4)));
+ output.append(QLatin1Char(toHexUpper(ch & 0xf)));
}
static QString encode(const QString &input, const char *unescapedSet, bool *ok)
@@ -246,8 +232,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (i + 2 >= length)
goto error;
- int d1 = fromHex(input.at(i+1));
- int d0 = fromHex(input.at(i+2));
+ int d1 = fromHex(input.at(i+1).unicode());
+ int d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -281,8 +267,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (input.at(i) != percent)
goto error;
- d1 = fromHex(input.at(i+1));
- d0 = fromHex(input.at(i+2));
+ d1 = fromHex(input.at(i+1).unicode());
+ d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -339,14 +325,14 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval())
{
Scope s(scope);
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
-ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
+ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
{
if (callData->argc < 1)
return Encode::undefined();
@@ -395,14 +381,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ctx->d()->strictMode = false;
ctx->d()->compilationUnit = function->compilationUnit;
- return function->code(ctx->engine(), function->codeData);
+ return Q_V4_PROFILE(ctx->engine(), function);
}
-ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
+ReturnedValue EvalFunction::call(const Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(callData, false);
+ return static_cast<const EvalFunction *>(that)->evalCall(callData, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 74de233b47..ba1d5d2e0b 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -52,10 +52,10 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
{
V4_OBJECT2(EvalFunction, FunctionObject)
- ReturnedValue evalCall(CallData *callData, bool directCall);
+ ReturnedValue evalCall(CallData *callData, bool directCall) const;
using Object::construct;
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct GlobalFunctions
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index ff374225f4..58f808b4d5 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -80,8 +80,8 @@ public:
if (!entry || entry->isMarked())
continue;
entry->setMarkBit();
- Q_ASSERT(entry->gcGetVtable()->markObjects);
- entry->gcGetVtable()->markObjects(entry, e);
+ Q_ASSERT(entry->vtable()->markObjects);
+ entry->vtable()->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index e4bd460966..2eb61081c7 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -54,7 +54,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContex
: v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
{
m_qmlglobal.set(engine, qmlglobal);
- if (callback.asFunctionObject())
+ if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
m_resultObject.set(v4, resultValue(v4));
@@ -94,14 +94,14 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
{
if (!callback.isObject())
return;
- QV4::ExecutionEngine *v4 = callback.asObject()->engine();
+ QV4::ExecutionEngine *v4 = callback.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, callback);
if (!f)
return;
QV4::ScopedCallData callData(scope, 1);
- callData->thisObject = v4->globalObject()->asReturnedValue();
+ callData->thisObject = v4->globalObject->asReturnedValue();
callData->args[0] = status;
f->call(callData);
if (scope.hasException())
@@ -176,7 +176,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QV4::Scope scope(ctx->engine());
- QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
+ QQmlContextData *context = scope.engine->callingQmlContext();
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
@@ -184,7 +184,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->argc() >= 2 && ctx->args()[1].asFunctionObject())
+ if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
@@ -224,7 +224,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QV4::ScopedValue ex(scope, scope.engine->catchException());
result = resultValue(scope.engine, Exception);
QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception")));
- result->asObject()->put(exception, ex);
+ result->as<QV4::Object>()->put(exception, ex);
} else {
result = resultValue(scope.engine, Ok);
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5dc94e8555..5ef4442b03 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -50,7 +50,7 @@
#include <private/qqmlcontext_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 3289058cb7..80590fe72e 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -46,7 +46,7 @@ struct String;
struct ExecutionEngine;
struct Object;
struct Identifier;
-struct ManagedVTable;
+struct VTable;
struct PropertyHashData;
struct PropertyHash
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index e7905974df..f703e85399 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -38,8 +38,8 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include "qv4string_p.h"
-#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -62,33 +62,6 @@ static int indent = 0;
DEFINE_OBJECT_VTABLE(JsonObject);
-class JsonParser
-{
-public:
- JsonParser(ExecutionEngine *engine, const QChar *json, int length);
-
- ReturnedValue parse(QJsonParseError *error);
-
-private:
- inline bool eatSpace();
- inline QChar nextToken();
-
- ReturnedValue parseObject();
- ReturnedValue parseArray();
- bool parseMember(Object *o);
- bool parseString(QString *string);
- bool parseValue(Value *val);
- bool parseNumber(Value *val);
-
- ExecutionEngine *engine;
- const QChar *head;
- const QChar *json;
- const QChar *end;
-
- int nestingLevel;
- QJsonParseError::ParseError lastError;
-};
-
static const int nestingLimit = 1024;
@@ -639,17 +612,22 @@ bool JsonParser::parseString(QString *string)
struct Stringify
{
- ExecutionContext *ctx;
+ ExecutionEngine *v4;
FunctionObject *replacerFunction;
- // ### GC
- QVector<Heap::String *> propertyList;
+ QV4::String *propertyList;
+ int propertyListSize;
QString gap;
QString indent;
+ QStack<Object *> stack;
- // ### GC
- QStack<Heap::Object *> stack;
+ bool stackContains(Object *o) {
+ for (int i = 0; i < stack.size(); ++i)
+ if (stack.at(i)->d() == o->d())
+ return true;
+ return false;
+ }
- Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
+ Stringify(ExecutionEngine *e) : v4(e), replacerFunction(0), propertyList(0), propertyListSize(0) {}
QString Str(const QString &key, const Value &v);
QString JA(ArrayObject *a);
@@ -701,26 +679,26 @@ static QString quote(const QString &str)
QString Stringify::Str(const QString &key, const Value &v)
{
- Scope scope(ctx);
+ Scope scope(v4);
ScopedValue value(scope, v);
ScopedObject o(scope, value);
if (o) {
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
+ ScopedString s(scope, v4->newString(QStringLiteral("toJSON")));
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
value = toJSON->call(callData);
}
}
if (replacerFunction) {
- ScopedObject holder(scope, ctx->d()->engine->newObject());
+ ScopedObject holder(scope, v4->newObject());
holder->put(scope.engine, QString(), value);
ScopedCallData callData(scope, 2);
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
callData->args[1] = value;
callData->thisObject = holder;
value = replacerFunction->call(callData);
@@ -728,11 +706,11 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (NumberObject *n = o->asNumberObject())
+ if (NumberObject *n = o->as<NumberObject>())
value = Encode(n->value());
- else if (StringObject *so = o->asStringObject())
- value = so->d()->value;
- else if (BooleanObject *b =o->asBooleanObject())
+ else if (StringObject *so = o->as<StringObject>())
+ value = so->d()->string;
+ else if (BooleanObject *b = o->as<BooleanObject>())
value = Encode(b->value());
}
@@ -750,8 +728,8 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (!o->asFunctionObject()) {
- if (o->asArrayObject()) {
+ if (!o->as<FunctionObject>()) {
+ if (o->as<ArrayObject>()) {
return JA(static_cast<ArrayObject *>(o.getPointer()));
} else {
return JO(o);
@@ -777,20 +755,20 @@ QString Stringify::makeMember(const QString &key, const Value &v)
QString Stringify::JO(Object *o)
{
- if (stack.contains(o->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(o)) {
+ v4->throwTypeError();
return QString();
}
- Scope scope(ctx);
+ Scope scope(v4);
QString result;
- stack.push(o->d());
+ stack.push(o);
QString stepback = indent;
indent += gap;
QStringList partial;
- if (propertyList.isEmpty()) {
+ if (!propertyListSize) {
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -805,11 +783,13 @@ QString Stringify::JO(Object *o)
partial += member;
}
} else {
- ScopedString s(scope);
- for (int i = 0; i < propertyList.size(); ++i) {
+ ScopedValue v(scope);
+ for (int i = 0; i < propertyListSize; ++i) {
bool exists;
- s = propertyList.at(i);
- ScopedValue v(scope, o->get(s, &exists));
+ String *s = propertyList + i;
+ if (!s)
+ continue;
+ v = o->get(s, &exists);
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -834,15 +814,15 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(a)) {
+ v4->throwTypeError();
return QString();
}
Scope scope(a->engine());
QString result;
- stack.push(a->d());
+ stack.push(a);
QString stepback = indent;
indent += gap;
@@ -879,7 +859,7 @@ QString Stringify::JA(ArrayObject *a)
Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+ : Heap::Object(e->emptyClass, e->objectPrototype())
{
Scope scope(e);
ScopedObject o(scope, this);
@@ -911,32 +891,38 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
{
Scope scope(ctx);
- Stringify stringify(ctx);
+ Stringify stringify(scope.engine);
ScopedObject o(scope, ctx->argument(1));
if (o) {
- stringify.replacerFunction = o->asFunctionObject();
+ stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
uint arrayLen = o->getLength();
- ScopedValue v(scope);
+ stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
for (uint i = 0; i < arrayLen; ++i) {
- v = o->getIndexed(i);
- if (v->asNumberObject() || v->asStringObject() || v->isNumber())
- v = RuntimeHelpers::toString(scope.engine, v);
- if (v->isString()) {
- String *s = v->stringValue();
- if (!stringify.propertyList.contains(s->d()))
- stringify.propertyList.append(s->d());
+ Value *v = stringify.propertyList + i;
+ *v = o->getIndexed(i);
+ if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
+ *v = RuntimeHelpers::toString(scope.engine, *v);
+ if (!v->isString()) {
+ v->setM(0);
+ } else {
+ for (uint j = 0; j <i; ++j) {
+ if (stringify.propertyList[j].m() == v->m()) {
+ v->setM(0);
+ break;
+ }
+ }
}
}
}
}
ScopedValue s(scope, ctx->argument(2));
- if (NumberObject *n = s->asNumberObject())
+ if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
- else if (StringObject *so = s->asStringObject())
- s = so->d()->value;
+ else if (StringObject *so = s->as<StringObject>())
+ s = so->d()->string;
if (s->isNumber()) {
stringify.gap = QString(qMin(10, (int)s->toInteger()), ' ');
@@ -986,7 +972,7 @@ QJsonValue JsonObject::toJsonValue(const Value &value, V4ObjectSet &visitedObjec
return QJsonValue(value.toQString());
Q_ASSERT(value.isObject());
- Scope scope(value.asObject()->engine());
+ Scope scope(value.as<Object>()->engine());
ScopedArrayObject a(scope, value);
if (a)
return toJsonArray(a, visitedObjects);
@@ -1009,22 +995,22 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs
return o.asReturnedValue();
}
-QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
+QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObjects)
{
QJsonObject result;
- if (!o || o->asFunctionObject())
+ if (!o || o->as<FunctionObject>())
return result;
Scope scope(o->engine());
- if (visitedObjects.contains(o->d())) {
+ if (visitedObjects.contains(ObjectItem(o))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
return result;
}
- visitedObjects.insert(o->d());
+ visitedObjects.insert(ObjectItem(o));
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -1035,11 +1021,11 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
break;
QString key = name->toQStringNoThrow();
- if (!val->asFunctionObject())
+ if (!val->as<FunctionObject>())
result.insert(key, toJsonValue(val, visitedObjects));
}
- visitedObjects.remove(o->d());
+ visitedObjects.remove(ObjectItem(o));
return result;
}
@@ -1057,7 +1043,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
return a.asReturnedValue();
}
-QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
+QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects)
{
QJsonArray result;
if (!a)
@@ -1065,25 +1051,25 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
Scope scope(a->engine());
- if (visitedObjects.contains(a->d())) {
+ if (visitedObjects.contains(ObjectItem(a))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty array (and no error is thrown).
return result;
}
- visitedObjects.insert(a->d());
+ visitedObjects.insert(ObjectItem(a));
ScopedValue v(scope);
quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
- if (v->asFunctionObject())
+ if (v->as<FunctionObject>())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
}
- visitedObjects.remove(a->d());
+ visitedObjects.remove(ObjectItem(a));
return result;
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 81a783ee92..1ad0e2c5de 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -37,6 +37,8 @@
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <qjsonvalue.h>
+#include <qjsondocument.h>
+#include <qhash.h>
QT_BEGIN_NAMESPACE
@@ -50,12 +52,23 @@ struct JsonObject : Object {
}
+struct ObjectItem {
+ const QV4::Object *o;
+ ObjectItem(const QV4::Object *o) : o(o) {}
+};
+
+inline bool operator ==(const ObjectItem &a, const ObjectItem &b)
+{ return a.o->d() == b.o->d(); }
+
+inline int qHash(const ObjectItem &i, uint seed = 0)
+{ return ::qHash((void *)i.o->d(), seed); }
+
struct JsonObject : Object {
Q_MANAGED_TYPE(JsonObject)
V4_OBJECT2(JsonObject, Object)
private:
- // ### GC
- typedef QSet<QV4::Heap::Base *> V4ObjectSet;
+
+ typedef QSet<ObjectItem> V4ObjectSet;
public:
static ReturnedValue method_parse(CallContext *ctx);
@@ -67,18 +80,45 @@ public:
static inline QJsonValue toJsonValue(const QV4::Value &value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
- static inline QJsonObject toJsonObject(QV4::Object *o)
+ static inline QJsonObject toJsonObject(const QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
- static inline QJsonArray toJsonArray(QV4::ArrayObject *a)
+ static inline QJsonArray toJsonArray(const QV4::ArrayObject *a)
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::Value &value, V4ObjectSet &visitedObjects);
- static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects);
- static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects);
+ static QJsonObject toJsonObject(const Object *o, V4ObjectSet &visitedObjects);
+ static QJsonArray toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects);
};
+class JsonParser
+{
+public:
+ JsonParser(ExecutionEngine *engine, const QChar *json, int length);
+
+ ReturnedValue parse(QJsonParseError *error);
+
+private:
+ inline bool eatSpace();
+ inline QChar nextToken();
+
+ ReturnedValue parseObject();
+ ReturnedValue parseArray();
+ bool parseMember(Object *o);
+ bool parseString(QString *string);
+ bool parseValue(Value *val);
+ bool parseNumber(Value *val);
+
+ ExecutionEngine *engine;
+ const QChar *head;
+ const QChar *json;
+ const QChar *end;
+
+ int nestingLevel;
+ QJsonParseError::ParseError lastError;
+};
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 82b20337cb..443427b024 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -33,6 +33,7 @@
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -72,7 +73,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
+ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs)
{
Heap::Object *obj = thisObject->d();
ExecutionEngine *engine = thisObject->engine();
@@ -123,7 +124,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -168,7 +169,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
@@ -200,7 +201,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
uint idx = index.asArrayIndex();
if (idx < UINT_MAX) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = value;
return;
@@ -224,7 +225,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = v;
return;
@@ -235,7 +236,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (Object *o = object.asObject())
+ if (const Object *o = object.as<Object>())
return o->getLookup(l);
Object *proto;
@@ -244,14 +245,14 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
case Value::Null_Type:
return engine->throwTypeError();
case Value::Boolean_Type:
- proto = engine->booleanPrototype.asObject();
+ proto = engine->booleanPrototype();
break;
case Value::Managed_Type: {
Q_ASSERT(object.isString());
- proto = engine->stringPrototype.asObject();
+ proto = engine->stringPrototype();
Scope scope(engine);
ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(engine->id_length)) {
+ if (name->equals(engine->id_length())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
return stringLengthGetter(l, engine, object);
@@ -260,7 +261,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
}
case Value::Integer_Type:
default: // Number
- proto = engine->numberPrototype.asObject();
+ proto = engine->numberPrototype();
}
PropertyAttributes attrs;
@@ -291,7 +292,7 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const
Lookup l1 = *l;
if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) {
- if (Object *o = object.asObject()) {
+ if (const Object *o = object.as<Object>()) {
ReturnedValue v = o->getLookup(l);
Lookup l2 = *l;
@@ -560,7 +561,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (String *s = object.asString())
+ if (const String *s = object.as<String>())
return Encode(s->d()->length());
l->getter = getterGeneric;
@@ -569,7 +570,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (ArrayObject *a = object.asArrayObject())
+ if (const ArrayObject *a = object.as<ArrayObject>())
return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
l->getter = getterGeneric;
@@ -579,7 +580,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, cons
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -608,7 +609,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
return o->memberData()->data[l->index].asReturnedValue();
@@ -618,7 +619,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
return o->prototype()->memberData->data[l->index].asReturnedValue();
@@ -629,7 +630,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
@@ -645,7 +646,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
@@ -662,7 +663,7 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
@@ -680,7 +681,7 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
@@ -701,7 +702,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object);
@@ -716,11 +717,11 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &obje
o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Lookup l1 = *l;
- if (Object *o = object.asObject()) {
+ if (Object *o = object.as<Object>()) {
o->setLookup(l, value);
if (l->setter == Lookup::setter0) {
@@ -735,7 +736,7 @@ void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &o
setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
@@ -745,9 +746,9 @@ void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &obj
}
}
-void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
o->memberData()->data[l->index] = value;
return;
@@ -756,9 +757,9 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, co
setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
if (!o->memberData() || l->index >= o->memberData()->size)
@@ -773,9 +774,9 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
@@ -791,9 +792,9 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
@@ -812,9 +813,9 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
o->memberData()->data[l->index] = value;
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 88397dc36c..232e909c48 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -51,7 +51,7 @@ struct Lookup {
void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v);
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
- void (*setter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &v);
+ void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
ExecutionEngine *engine;
@@ -107,17 +107,17 @@ struct Lookup {
static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
- static void setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
+ static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
- ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index c4b9fc597e..bb7ee43b4e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -32,13 +32,13 @@
****************************************************************************/
#include "qv4managed_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4errorobject_p.h"
using namespace QV4;
-const ManagedVTable Managed::static_vtbl =
+const VTable Managed::static_vtbl =
{
0,
Managed::IsExecutionContext,
@@ -59,7 +59,7 @@ const ManagedVTable Managed::static_vtbl =
QString Managed::className() const
{
const char *s = 0;
- switch (Type(d()->vtable->type)) {
+ switch (Type(d()->vtable()->type)) {
case Type_Invalid:
case Type_String:
return QString();
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 0fe5c7ee49..6f5564300f 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -35,7 +35,7 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
@@ -65,10 +65,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
- static const QV4::ManagedVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
+ static const QV4::VTable static_vtbl; \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
#define Q_MANAGED_TYPE(type) \
public: \
@@ -78,31 +78,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
(classname::func == QV4::Managed::func ? 0 : classname::func)
-struct GCDeletable
-{
- GCDeletable() : next(0), lastCall(false) {}
- virtual ~GCDeletable() {}
- GCDeletable *next;
- bool lastCall;
-};
-
-struct ManagedVTable
-{
- const ManagedVTable * const parent;
- uint isExecutionContext : 1;
- uint isString : 1;
- uint isObject : 1;
- uint isFunctionObject : 1;
- uint isErrorObject : 1;
- uint isArrayData : 1;
- uint unused : 18;
- uint type : 8;
- const char *className;
- void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, ExecutionEngine *e);
- bool (*isEqualTo)(Managed *m, Managed *other);
-};
-
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
@@ -121,7 +96,7 @@ struct ManagedVTable
}
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
@@ -141,8 +116,6 @@ private:
public:
- inline void mark(QV4::ExecutionEngine *engine);
-
enum Type {
Type_Invalid,
Type_String,
@@ -167,55 +140,15 @@ public:
};
Q_MANAGED_TYPE(Invalid)
- template <typename T>
- T *as() {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
- template <typename T>
- const T *as() const {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
-
- String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return d()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return d()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return d()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return d()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return d()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return d()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return d()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
-
- bool isListType() const { return d()->vtable->type == Type_QmlSequence; }
-
- bool isArrayObject() const { return d()->vtable->type == Type_ArrayObject; }
- bool isStringObject() const { return d()->vtable->type == Type_StringObject; }
+ bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
+
+ bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
+ bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
QString className() const;
bool isEqualTo(const Managed *other) const
- { return d()->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
+ { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
static bool isEqualTo(Managed *m, Managed *other);
@@ -231,37 +164,15 @@ private:
template<>
-inline Managed *value_cast(const Value &v) {
- return v.asManaged();
+inline const Managed *Value::as() const {
+ if (isManaged())
+ return managed();
+ return 0;
}
-template<typename T>
-inline T *managed_cast(Managed *m)
-{
- return m ? m->as<T>() : 0;
-}
-
-template<>
-inline String *managed_cast(Managed *m)
-{
- return m ? m->asString() : 0;
-}
template<>
-inline Object *managed_cast(Managed *m)
-{
- return m ? m->asObject() : 0;
-}
-template<>
-inline FunctionObject *managed_cast(Managed *m)
-{
- return m ? m->asFunctionObject() : 0;
-}
-
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- return *m;
+inline const Object *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isObject ? objectValue() : 0;
}
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 473e05bf88..c498160c36 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -48,7 +48,7 @@ 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.asObject())
+ : Heap::Object(e->emptyClass, e->objectPrototype())
{
Scope scope(e);
ScopedObject m(scope, this);
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index 03dfee3dcf..5ec5cb1f58 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4memberdata_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
using namespace QV4;
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 4a1a94e872..4ae30a7f35 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -33,6 +33,7 @@
#include "qv4numberobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
@@ -50,14 +51,14 @@ Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
+ReturnedValue NumberCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(m->cast<NumberCtor>()->engine());
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(scope.engine->newNumberObject(dbl));
}
-ReturnedValue NumberCtor::call(Managed *, CallData *callData)
+ReturnedValue NumberCtor::call(const Managed *, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(dbl);
@@ -67,8 +68,8 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qSNaN()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
@@ -81,9 +82,9 @@ QT_WARNING_DISABLE_INTEL(239)
QT_WARNING_POP
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
+ defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
defineDefaultProperty(QStringLiteral("toFixed"), method_toFixed, 1);
defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential);
defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
@@ -93,7 +94,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asReturnedValue();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return Encode(n->value());
@@ -103,7 +104,7 @@ inline double thisNumber(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asDouble();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return n->value();
@@ -119,7 +120,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
if (ctx->argc() && !ctx->args()[0].isUndefined()) {
int radix = ctx->args()[0].toInt32();
if (radix < 2 || radix > 36)
- return ctx->engine()->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
+ return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
@@ -197,7 +198,7 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
QString str;
if (std::isnan(v))
- str = QString::fromLatin1("NaN");
+ str = QStringLiteral("NaN");
else if (qIsInf(v))
str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
else if (v < 1.e21) {
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 205995701b..04798d31fc 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject
{
V4_OBJECT2(NumberCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
};
struct NumberPrototype: NumberObject
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 211fd1812e..b3c0863e3e 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -37,12 +37,13 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4lookup_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4memberdata_p.h"
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
+#include "qv4string_p.h"
#include <stdint.h>
@@ -138,7 +139,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ScopedString s(scope, e->newIdentifier(name));
ScopedContext global(scope, e->rootContext());
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -148,7 +149,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
Scope scope(e);
ScopedContext global(scope, e->rootContext());
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -219,50 +220,50 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
}
// Section 8.12.1
-Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs)
+void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __getOwnProperty__(idx, attrs);
+ return getOwnProperty(idx, attrs, p);
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
- if (attrs)
- *attrs = internalClass()->propertyData[member];
- return propertyAt(member);
+ *attrs = internalClass()->propertyData[member];
+ if (p)
+ p->copy(propertyAt(member), *attrs);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
-Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
+void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
{
- Property *p = arrayData() ? arrayData()->getProperty(index) : 0;
- if (p) {
- if (attrs)
- *attrs = arrayData()->attributes(index);
- return p;
+ Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
+ if (pd) {
+ *attrs = arrayData()->attributes(index);
+ if (p)
+ p->copy(pd, *attrs);
+ return;
}
if (isStringObject()) {
- if (attrs)
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- return static_cast<StringObject *>(this)->getIndex(index);
+ *attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(this)->getIndex(index);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
// Section 8.12.2
Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return __getPropertyDescriptor__(idx, attrs);
-
+ Q_ASSERT(name->asArrayIndex() == UINT_MAX);
const Heap::Object *o = d();
while (o) {
@@ -286,16 +287,15 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
while (o) {
Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
- if (attrs)
- *attrs = o->arrayData->attributes(index);
+ *attrs = o->arrayData->attributes(index);
return p;
}
- if (o->vtable->type == Type_StringObject) {
- Property *p = static_cast<const Heap::StringObject *>(o)->getIndex(index);
- if (p) {
- if (attrs)
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return p;
+ 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);
}
}
o = o->prototype;
@@ -356,8 +356,7 @@ bool Object::hasOwnProperty(uint index) const
return true;
if (isStringObject()) {
- String *s = static_cast<const StringObject *>(this)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(this)->length())
return true;
}
if (!queryIndexed(index).isEmpty())
@@ -365,24 +364,24 @@ bool Object::hasOwnProperty(uint index) const
return false;
}
-ReturnedValue Object::construct(Managed *m, CallData *)
+ReturnedValue Object::construct(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::call(Managed *m, CallData *)
+ReturnedValue Object::call(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGet(name, hasProperty);
+ return static_cast<const Object *>(m)->internalGet(name, hasProperty);
}
-ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
+ return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
void Object::put(Managed *m, String *name, const Value &value)
@@ -416,8 +415,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
return o->arrayData()->attributes(index);
if (o->isStringObject()) {
- String *s = static_cast<const StringObject *>(o)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(o)->length())
return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
@@ -433,9 +431,9 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-ReturnedValue Object::getLookup(Managed *m, Lookup *l)
+ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
{
- Object *o = static_cast<Object *>(m);
+ const Object *o = static_cast<const Object *>(m);
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -516,10 +514,10 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
if (o->arrayData()) {
@@ -531,7 +529,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>();
Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
it->arrayNode = it->arrayNode->nextNode();
PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
@@ -548,7 +546,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// dense arrays
while (it->arrayIndex < o->d()->arrayData->len) {
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
@@ -574,7 +572,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- *name = o->engine()->newString(n->string);
+ name->setM(o->engine()->newString(n->string));
*attrs = a;
pd->copy(p, a);
return;
@@ -585,7 +583,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// Section 8.12.3
-ReturnedValue Object::internalGet(String *name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -611,7 +609,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
+ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
{
Property *pd = 0;
PropertyAttributes attrs;
@@ -625,10 +623,12 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
break;
}
if (o->isStringObject()) {
- pd = static_cast<StringObject *>(o.getPointer())->getIndex(index);
- if (pd) {
+ ScopedString str(scope, static_cast<StringObject *>(o.getPointer())->getIndex(index));
+ if (str) {
attrs = (Attr_NotWritable|Attr_NotConfigurable);
- break;
+ if (hasProperty)
+ *hasProperty = true;
+ return str.asReturnedValue();
}
}
o = o->prototype();
@@ -674,7 +674,7 @@ void Object::internalPut(String *name, const Value &value)
goto reject;
} else if (!attrs.isWritable())
goto reject;
- else if (isArrayObject() && name->equals(engine()->id_length)) {
+ else if (isArrayObject() && name->equals(engine()->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
@@ -710,7 +710,7 @@ void Object::internalPut(String *name, const Value &value)
// Clause 5
if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ Q_ASSERT(pd->setter() != 0);
Scope scope(engine());
ScopedFunctionObject setter(scope, pd->setter());
@@ -745,8 +745,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
attrs = arrayData()->attributes(index);
if (!pd && isStringObject()) {
- pd = static_cast<StringObject *>(this)->getIndex(index);
- if (pd)
+ if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
@@ -784,7 +783,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
// Clause 5
if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ Q_ASSERT(pd->setter() != 0);
Scope scope(engine());
ScopedFunctionObject setter(scope, pd->setter());
@@ -858,8 +857,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
PropertyAttributes *cattrs;
uint memberIndex;
- if (isArrayObject() && name->equals(engine->id_length)) {
- Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length));
+ 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))
@@ -926,16 +925,16 @@ reject:
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
- Property *current = 0;
+ bool hasProperty = 0;
// Clause 1
if (arrayData()) {
- current = arrayData()->getProperty(index);
- if (!current && isStringObject())
- current = static_cast<StringObject *>(this)->getIndex(index);
+ hasProperty = arrayData()->getProperty(index);
+ if (!hasProperty && isStringObject())
+ hasProperty = (index < static_cast<StringObject *>(this)->length());
}
- if (!current) {
+ if (!hasProperty) {
// clause 3
if (!isExtensible())
goto reject;
@@ -1029,9 +1028,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (!p->value.isEmpty() && current->value.val != p->value.val)
+ if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue())
goto reject;
- if (!p->set.isEmpty() && current->set.val != p->set.val)
+ if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue())
goto reject;
}
}
@@ -1097,7 +1096,7 @@ void Object::copyArrayData(Object *other)
uint Object::getLength(const Managed *m)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length));
+ ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length()));
return v->toUInt32();
}
@@ -1137,7 +1136,7 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype())
{
init();
Scope scope(engine);
@@ -1155,14 +1154,14 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
a->setArrayLengthUnchecked(len);
}
-ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
+ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(scope.engine->id_length)) {
+ if (name->equals(scope.engine->id_length())) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
- ArrayObject *a = static_cast<ArrayObject *>(m);
+ const ArrayObject *a = static_cast<const ArrayObject *>(m);
return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
}
return Object::getLookup(m, l);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 71a997e133..f129312819 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -36,6 +36,9 @@
#include "qv4managed_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraydata_p.h"
+#include "qv4engine_p.h"
+#include "qv4scopedvalue_p.h"
+#include "qv4value_p.h"
QT_BEGIN_NAMESPACE
@@ -44,20 +47,16 @@ namespace QV4 {
namespace Heap {
struct Object : Base {
- Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype.m))
- {
- }
+ inline Object(ExecutionEngine *engine);
Object(InternalClass *internal, QV4::Object *prototype);
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); }
InternalClass *internalClass;
- Heap::Object *prototype;
- MemberData *memberData;
- ArrayData *arrayData;
+ Pointer<Object> prototype;
+ Pointer<MemberData> memberData;
+ Pointer<ArrayData> arrayData;
};
}
@@ -67,9 +66,9 @@ struct Object : Base {
Q_MANAGED_CHECK \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- Data *d() const { return static_cast<Data *>(m); }
+ Data *d() const { return static_cast<Data *>(m()); }
#define V4_OBJECT2(DataClass, superClass) \
public: \
@@ -77,33 +76,33 @@ struct Object : Base {
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
struct ObjectVTable
{
- ManagedVTable managedVTable;
- ReturnedValue (*call)(Managed *, CallData *data);
- ReturnedValue (*construct)(Managed *, CallData *data);
- ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
- ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
+ VTable vTable;
+ ReturnedValue (*call)(const Managed *, CallData *data);
+ ReturnedValue (*construct)(const Managed *, CallData *data);
+ ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
+ ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, String *name, const Value &value);
void (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- ReturnedValue (*getLookup)(Managed *m, Lookup *l);
+ ReturnedValue (*getLookup)(const Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
#define DEFINE_OBJECT_VTABLE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
- DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
+ DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \
call, \
construct, \
get, \
@@ -141,15 +140,15 @@ struct Q_QML_EXPORT Object: Managed {
const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
Property *propertyAt(uint index) { return d()->propertyAt(index); }
- const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable); }
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
bool setPrototype(Object *proto);
- Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
- Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
+ void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
+ void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
+ Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const;
+ Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const;
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -272,9 +271,9 @@ public:
}
void ensureMemberIndex(uint idx);
- inline ReturnedValue get(String *name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
inline void put(String *name, const Value &v)
{ vtable()->put(this, name, v); }
@@ -288,38 +287,38 @@ public:
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
- ReturnedValue getLookup(Lookup *l)
+ ReturnedValue getLookup(Lookup *l) const
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const Value &v)
{ vtable()->setLookup(this, l, v); }
- void advanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
- inline ReturnedValue construct(CallData *d)
+ inline ReturnedValue construct(CallData *d) const
{ return vtable()->construct(this, d); }
- inline ReturnedValue call(CallData *d)
+ inline ReturnedValue call(CallData *d) const
{ return vtable()->call(this, d); }
protected:
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue construct(Managed *m, CallData *);
- static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue construct(const Managed *m, CallData *);
+ static ReturnedValue call(const Managed *m, CallData *);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const Value &v);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
private:
- ReturnedValue internalGet(String *name, bool *hasProperty);
- ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty) const;
+ ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
void internalPut(String *name, const Value &value);
void internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
@@ -331,6 +330,12 @@ 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),
@@ -339,7 +344,7 @@ struct BooleanObject : Object {
}
BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype.asObject()),
+ : Object(engine->emptyClass, engine->booleanPrototype()),
b(b)
{
}
@@ -354,7 +359,7 @@ struct NumberObject : Object {
}
NumberObject(ExecutionEngine *engine, double val)
- : Object(engine->emptyClass, engine->numberPrototype.asObject()),
+ : Object(engine->emptyClass, engine->numberPrototype()),
value(val)
{
}
@@ -367,7 +372,7 @@ struct ArrayObject : Object {
};
ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype())
{ init(); }
ArrayObject(ExecutionEngine *engine, const QStringList &list);
ArrayObject(InternalClass *ic, QV4::Object *prototype)
@@ -400,7 +405,7 @@ struct ArrayObject: Object {
void init(ExecutionEngine *engine);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
using Object::getLength;
static uint getLength(const Managed *m);
@@ -454,14 +459,10 @@ inline void Object::arraySet(uint index, const Value &value)
setArrayLengthUnchecked(index + 1);
}
-template<>
-inline Object *value_cast(const Value &v) {
- return v.asObject();
-}
template<>
-inline ArrayObject *value_cast(const Value &v) {
- return v.asArrayObject();
+inline const ArrayObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index f36ee554a7..585f9f5c2e 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -35,6 +35,7 @@
#include "qv4stringobject_p.h"
#include "qv4identifier_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -50,7 +51,7 @@ ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scrat
init(o);
}
-ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
+ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags)
: engine(scope.engine)
, object(scope.alloc(1))
, current(scope.alloc(1))
@@ -62,14 +63,14 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
init(o);
}
-void ObjectIterator::init(Object *o)
+void ObjectIterator::init(const Object *o)
{
- object->m = o ? o->m : 0;
- current->m = o ? o->m : 0;
+ object->setM(o ? o->m() : 0);
+ current->setM(o ? o->m() : 0);
#if QT_POINTER_SIZE == 4
- object->tag = QV4::Value::Managed_Type;
- current->tag = QV4::Value::Managed_Type;
+ object->setTag(QV4::Value::Managed_Type);
+ current->setTag(QV4::Value::Managed_Type);
#endif
if (object->as<ArgumentsObject>()) {
@@ -78,12 +79,12 @@ void ObjectIterator::init(Object *o)
}
}
-void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
- if (!object->asObject()) {
+ if (!object->as<Object>()) {
*attrs = PropertyAttributes();
return;
}
@@ -92,19 +93,19 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ScopedString n(scope);
while (1) {
- if (!current->asObject())
+ if (!current->as<Object>())
break;
while (1) {
- current->asObject()->advanceIterator(this, name, index, pd, attrs);
+ current->as<Object>()->advanceIterator(this, name, index, pd, attrs);
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
if (current->heapObject() != object->heapObject()) {
- o = object->asObject();
+ o = object->as<Object>();
n = *name;
bool shadowed = false;
- while (o->asObject()->d() != current->heapObject()) {
+ while (o->d() != current->heapObject()) {
if ((!!n && o->hasOwnProperty(n)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
@@ -119,9 +120,9 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
}
if (flags & WithProtoChain)
- current->m = current->objectValue()->prototype();
+ current->setM(current->objectValue()->prototype());
else
- current->m = (Heap::Base *)0;
+ current->setM(0);
arrayIndex = 0;
memberIndex = 0;
@@ -131,7 +132,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ReturnedValue ObjectIterator::nextPropertyName(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -147,13 +148,13 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value)
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(index);
}
ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -169,13 +170,13 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(engine->newString(QString::number(index)));
}
ReturnedValue ObjectIterator::nextPropertyNameAsString()
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index a7abd2ca10..bfe04b33aa 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -57,9 +57,9 @@ struct Q_QML_EXPORT ObjectIterator
uint flags;
ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
- ObjectIterator(Scope &scope, Object *o, uint flags);
- void init(Object *o);
- void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ ObjectIterator(Scope &scope, const Object *o, uint flags);
+ void init(const Object *o);
+ void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 9356ea434e..1edf76e2de 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -34,10 +34,11 @@
#include "qv4objectproto_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
@@ -52,14 +53,14 @@ Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
+ReturnedValue ObjectCtor::construct(const Managed *that, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(that);
ExecutionEngine *v4 = ctor->engine();
Scope scope(v4);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
ScopedObject obj(scope, v4->newObject());
- ScopedObject proto(scope, ctor->get(v4->id_prototype));
+ ScopedObject proto(scope, ctor->get(v4->id_prototype()));
if (!!proto)
obj->setPrototype(proto);
return obj.asReturnedValue();
@@ -67,9 +68,9 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
return RuntimeHelpers::toObject(scope.engine, callData->args[0]);
}
-ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
+ReturnedValue ObjectCtor::call(const Managed *m, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(m);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(m);
ExecutionEngine *v4 = ctor->engine();
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return v4->newObject()->asReturnedValue();
@@ -81,8 +82,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
Scope scope(v4);
ScopedObject o(scope, this);
- ctor->defineReadonlyProperty(v4->id_prototype, o);
- ctor->defineReadonlyProperty(v4->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(v4->id_prototype(), o);
+ ctor->defineReadonlyProperty(v4->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
@@ -98,9 +99,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("keys"), method_keys, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(v4->id_toString, method_toString, 0);
+ defineDefaultProperty(v4->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
- defineDefaultProperty(v4->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(v4->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("hasOwnProperty"), method_hasOwnProperty, 1);
defineDefaultProperty(QStringLiteral("isPrototypeOf"), method_isPrototypeOf, 1);
defineDefaultProperty(QStringLiteral("propertyIsEnumerable"), method_propertyIsEnumerable, 1);
@@ -109,9 +110,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ScopedContext global(scope, scope.engine->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);
- insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
+ p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
+ p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
+ insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -140,8 +141,9 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name, &attrs);
- return fromPropertyDescriptor(scope.engine, desc, attrs);
+ Property desc;
+ O->getOwnProperty(name, &attrs, &desc);
+ return fromPropertyDescriptor(scope.engine, &desc, attrs);
}
ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
@@ -163,7 +165,7 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
return ctx->engine()->throwTypeError();
ScopedObject newObject(scope, ctx->d()->engine->newObject());
- newObject->setPrototype(O->asObject());
+ newObject->setPrototype(O->as<Object>());
if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
ctx->d()->callData->args[0] = newObject.asReturnedValue();
@@ -390,7 +392,7 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
} else {
ScopedObject obj(scope, RuntimeHelpers::toObject(scope.engine, ctx->thisObject()));
QString className = obj->className();
- return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->asReturnedValue();
}
}
@@ -400,7 +402,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString));
+ ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString()));
if (!f)
return ctx->engine()->throwTypeError();
ScopedCallData callData(scope);
@@ -462,7 +464,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p, &attrs);
+ o->getOwnProperty(p, &attrs);
return Encode(attrs.isEnumerable());
}
@@ -484,7 +486,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -512,7 +514,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -525,7 +527,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().asObject());
+ ScopedObject o(scope, ctx->thisObject().as<Object>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -572,15 +574,15 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(engine->id_enumerable()))
+ attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(engine->id_configurable))->toBoolean());
+ if (o->hasProperty(engine->id_configurable()))
+ attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get)) {
- ScopedValue get(scope, o->get(engine->id_get));
- FunctionObject *f = get->asFunctionObject();
+ if (o->hasProperty(engine->id_get())) {
+ ScopedValue get(scope, o->get(engine->id_get()));
+ FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
desc->value = get;
} else {
@@ -590,9 +592,9 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set)) {
- ScopedValue set(scope, o->get(engine->id_set));
- FunctionObject *f = set->asFunctionObject();
+ if (o->hasProperty(engine->id_set())) {
+ ScopedValue set(scope, o->get(engine->id_set()));
+ FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
desc->set = set;
} else {
@@ -602,22 +604,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable)) {
+ if (o->hasProperty(engine->id_writable())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(engine->id_writable()))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value)) {
+ if (o->hasProperty(engine->id_value())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- desc->value = o->get(engine->id_value);
+ desc->value = o->get(engine->id_value());
attrs->setType(PropertyAttributes::Data);
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 4e96681017..d571e50cd4 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject
{
V4_OBJECT2(ObjectCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ObjectPrototype: Object
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 88dc1946b8..4ec7103644 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4persistent_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4object_p.h"
#include "PageAllocation.h"
@@ -78,11 +78,11 @@ Page *allocatePage(PersistentValueStorage *storage)
if (p->header.next)
p->header.next->header.prev = &p->header.next;
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
- p->values[i].tag = QV4::Value::Empty_Type;
- p->values[i].int_32 = i + 1;
+ p->values[i].setTag(QV4::Value::Empty_Type);
+ p->values[i].setInt_32(i + 1);
}
- p->values[kEntriesPerPage - 1].tag = QV4::Value::Empty_Type;
- p->values[kEntriesPerPage - 1].int_32 = -1;
+ p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
+ p->values[kEntriesPerPage - 1].setInt_32(-1);
storage->firstPage = p;
@@ -97,7 +97,7 @@ PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++()
while (p) {
while (index < kEntriesPerPage - 1) {
++index;
- if (static_cast<Page *>(p)->values[index].tag != QV4::Value::Empty_Type)
+ if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
return *this;
}
index = -1;
@@ -147,10 +147,10 @@ Value *PersistentValueStorage::allocate()
p = allocatePage(this);
Value *v = p->values + p->header.freeList;
- p->header.freeList = v->int_32;
+ p->header.freeList = v->int_32();
++p->header.refCount;
- v->val = Encode::undefined();
+ v->setRawValue(Encode::undefined());
return v;
}
@@ -162,8 +162,8 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
- v->tag = QV4::Value::Empty_Type;
- v->int_32 = p->header.freeList;
+ v->setTag(QV4::Value::Empty_Type);
+ v->setInt_32(p->header.freeList);
p->header.freeList = v - p->values;
if (!--p->header.refCount) {
if (p->header.prev)
@@ -178,8 +178,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -190,7 +190,7 @@ void PersistentValueStorage::mark(ExecutionEngine *e)
Page *p = static_cast<Page *>(firstPage);
while (p) {
for (int i = 0; i < kEntriesPerPage; ++i) {
- if (Managed *m = p->values[i].asManaged())
+ if (Managed *m = p->values[i].as<Managed>())
m->mark(e);
}
drainMarkStack(e, markBase);
@@ -312,6 +312,12 @@ WeakValue::WeakValue(const WeakValue &other)
}
}
+WeakValue::WeakValue(ExecutionEngine *engine, const Value &value)
+{
+ val = engine->memoryManager->m_weakValues->allocate();
+ *val = value;
+}
+
WeakValue &WeakValue::operator=(const WeakValue &other)
{
if (!val) {
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 7cac2ed95f..858734e9ed 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -33,7 +33,8 @@
#ifndef QV4PERSISTENT_H
#define QV4PERSISTENT_H
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -96,7 +97,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template<typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
@@ -122,6 +129,7 @@ class Q_QML_EXPORT WeakValue
public:
WeakValue() : val(0) {}
WeakValue(const WeakValue &other);
+ WeakValue(ExecutionEngine *engine, const Value &value);
WeakValue &operator=(const WeakValue &other);
~WeakValue();
@@ -138,7 +146,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template <typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index a7019d0558..9b77599904 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4profiling_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include <private/qv4string_p.h>
QT_BEGIN_NAMESPACE
@@ -55,10 +56,10 @@ FunctionCallProperties FunctionCall::resolve() const
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
- static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
- static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
- Q_UNUSED(metatype);
- Q_UNUSED(metatype2);
+ static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
+ static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
+ Q_UNUSED(meta);
+ Q_UNUSED(meta2);
m_timer.start();
}
@@ -75,7 +76,7 @@ void Profiler::stopProfiling()
void Profiler::reportData()
{
- QList<FunctionCallProperties> resolved;
+ QVector<FunctionCallProperties> resolved;
resolved.reserve(m_data.size());
FunctionCallComparator comp;
foreach (const FunctionCall &call, m_data) {
@@ -83,14 +84,13 @@ void Profiler::reportData()
resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
}
emit dataReady(resolved, m_memory_data);
+ m_data.clear();
+ m_memory_data.clear();
}
void Profiler::startProfiling(quint64 features)
{
if (featuresEnabled == 0) {
- m_data.clear();
- m_memory_data.clear();
-
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index c3441eaacd..cc00af0193 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -155,14 +155,14 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
QV4::ExecutionEngine *m_engine;
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
- QList<MemoryAllocationProperties> m_memory_data;
+ QVector<MemoryAllocationProperties> m_memory_data;
friend class FunctionCallProfiler;
};
@@ -202,7 +202,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
-Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 1b55abd1f7..db8c6017e1 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -35,7 +35,6 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -73,8 +72,8 @@ struct Property {
inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
- inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
- inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
+ inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
+ inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); }
void copy(const Property *other, PropertyAttributes attrs) {
value = other->value;
@@ -85,12 +84,12 @@ struct Property {
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
Property(FunctionObject *getter, FunctionObject *setter) {
- value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
- set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
+ value = reinterpret_cast<Managed *>(getter);
+ set = reinterpret_cast<Managed *>(setter);
}
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
- value.m = reinterpret_cast<Heap::Base *>(getter);
- set.m = reinterpret_cast<Heap::Base *>(setter);
+ value.setM(reinterpret_cast<Heap::Base *>(getter));
+ set.setM(reinterpret_cast<Heap::Base *>(setter));
}
Property &operator=(Value v) { value = v; return *this; }
private:
diff --git a/src/qml/jsruntime/qv4qmlextensions.cpp b/src/qml/jsruntime/qv4qmlextensions.cpp
deleted file mode 100644
index c1c4e0ec78..0000000000
--- a/src/qml/jsruntime/qv4qmlextensions.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4qmlextensions_p.h"
-#include "qv4object_p.h"
-
-using namespace QV4;
-
-void QmlExtensions::markObjects(ExecutionEngine *e)
-{
- if (valueTypeWrapperPrototype)
- valueTypeWrapperPrototype->mark(e);
-}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 0a1aa56aab..e5946d8be6 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -55,6 +55,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4mm_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -92,7 +93,7 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
static QPair<QObject *, int> extractQtSignal(const Value &value)
{
if (value.isObject()) {
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
@@ -235,8 +236,8 @@ Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
@@ -255,7 +256,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
}
ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports)
+ bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
if (hasProperty)
@@ -266,8 +267,8 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
QV4::Scope scope(engine());
QV4::ScopedString name(scope, n);
- 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;
+ 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 (hasProperty)
@@ -317,13 +318,12 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- ScopedContext ctx(scope, scope.engine->currentContext());
- return getProperty(d()->object, ctx, result);
+ return getProperty(scope.engine, d()->object, result);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QQmlData::flushPendingBinding(object, property->coreIndex);
@@ -333,16 +333,16 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::ScopedObject qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
+ QV4::ScopedObject qmlcontextobject(scope, engine->qmlContextObject());
ScopedContext global(scope, scope.engine->rootContext());
return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex));
+ QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(engine, object, property->coreIndex));
- QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect)));
+ 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();
} else {
@@ -360,31 +360,32 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine, object, *property, nptr));
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
- if (n)
- ep->captureProperty(n);
+ if (n && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(n);
} else {
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
}
}
return rv->asReturnedValue();
}
- if (captureRequired && ep && !property->isConstant())
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
}
}
@@ -435,21 +436,21 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
Scope scope(engine);
ScopedContext ctx(scope, engine->currentContext());
- setProperty(object, ctx, result, value);
+ setProperty(engine, object, result, value);
return true;
}
-void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value)
{
if (!property->isWritable() && !property->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
property->name(object) + QLatin1Char('\"');
- ctx->engine()->throwTypeError(error);
+ engine->throwTypeError(error);
return;
}
QQmlBinding *newBinding = 0;
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
@@ -460,25 +461,25 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
newBinding = new QQmlBinding(value, object, callingQmlContext);
- newBinding->setTarget(object, *property, callingQmlContext);
+ newBinding->setTarget(object, *property);
}
}
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ if (newBinding)
+ QQmlPropertyPrivate::setBinding(newBinding);
+ else
+ QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -505,16 +506,16 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, QJSValue(ctx->d()->engine, value.asReturnedValue()));
+ PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
} else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType))
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
- } else if (value.asFunctionObject()) {
+ } else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
} else if (property->propType == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
@@ -543,11 +544,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->d()->engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->d()->engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType);
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -561,7 +562,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
}
@@ -634,7 +635,7 @@ void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
engine->m_multiplyWrappedQObjects->mark(object, engine);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(object))
return QV4::Encode::null();
@@ -646,14 +647,19 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(object, ctx, property, captureRequired);
+ return getProperty(engine, object, property, captureRequired);
+}
+
+void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
+{
+ setProperty(engine, d()->object, propertyIndex, value);
}
-void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
- if (QQmlData::wasDeleted(d()->object))
+ if (QQmlData::wasDeleted(object))
return;
- QQmlData *ddata = QQmlData::get(d()->object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
if (!ddata)
return;
@@ -661,14 +667,14 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return setProperty(d()->object, ctx, property, value);
+ return setProperty(engine, object, property, value);
}
bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QObjectWrapper>());
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
- QV4::Object *o = b->asObject();
+ QV4::Object *o = b->as<Object>();
if (o) {
if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>())
return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
@@ -684,10 +690,10 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
}
-QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(that->engine());
+ const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ QQmlContextData *qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -699,7 +705,7 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
return;
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
+ QQmlContextData *qmlContext = v4->callingQmlContext();
if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -718,23 +724,23 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(engine);
+ QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(engine->id_destroy) || name->equals(engine->id_toString))
+ || name->equals(engine->id_destroy()) || name->equals(engine->id_toString()))
return QV4::Attr_Data;
else
return QV4::Object::query(m, name);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
@@ -745,10 +751,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- // #### GC
Scope scope(that->engine());
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
- *name = propName->d();
+ name->setM(propName->d());
++it->arrayIndex;
*attributes = QV4::Attr_Data;
p->value = that->get(propName);
@@ -761,10 +766,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
++it->arrayIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
- // #### GC
Scope scope(that->engine());
ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name())));
- *name = methodName->d();
+ name->setM(methodName->d());
*attributes = QV4::Attr_Data;
p->value = that->get(methodName);
return;
@@ -811,7 +815,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
@@ -826,7 +830,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
QV4::ScopedString name(scope, f->name());
- error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
+ error.setDescription(QStringLiteral("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
}
if (QQmlEngine *qmlEngine = v4->qmlEngine()) {
QQmlEnginePrivate::get(qmlEngine)->warning(error);
@@ -1028,48 +1032,31 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
QV4::Object::markObjects(that, e);
}
-namespace {
- struct QObjectDeleter : public QV4::GCDeletable
- {
- QObjectDeleter(QObject *o)
- : m_objectToDelete(o)
- {}
- ~QObjectDeleter()
- {
- QQmlData *ddata = QQmlData::get(m_objectToDelete, false);
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
- // This object is notionally destroyed now
- ddata->isQueuedForDeletion = true;
- if (lastCall)
- delete m_objectToDelete;
- else
- m_objectToDelete->deleteLater();
- }
-
- QObject *m_objectToDelete;
- };
-}
-
-void QObjectWrapper::destroy(Heap::Base *that)
+void QObjectWrapper::destroyObject(bool lastCall)
{
- Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
- QPointer<QObject> object = This->object;
- ExecutionEngine *engine = This->internalClass->engine;
- This->~Data();
- This = 0;
- if (!object)
- return;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata)
- return;
-
- if (object->parent() || ddata->indestructible)
- return;
+ Heap::QObjectWrapper *h = d();
+ if (!h->internalClass)
+ return; // destroyObject already got called
+
+ QPointer<QObject> object = h->object;
+ if (object) {
+ QQmlData *ddata = QQmlData::get(object, false);
+ if (ddata) {
+ if (!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;
+ else
+ object->deleteLater();
+ }
+ }
+ }
- QObjectDeleter *deleter = new QObjectDeleter(object);
- engine->memoryManager->registerDeletable(deleter);
+ h->internalClass = 0;
+ h->~Data();
}
@@ -1229,7 +1216,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asDateObject()) {
+ } else if (actual.as<DateObject>()) {
switch (conversionType) {
case QMetaType::QDateTime:
return 0;
@@ -1247,7 +1234,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asArrayObject()) {
+ } else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
return 3;
@@ -1276,7 +1263,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
}
}
- } else if (QV4::Object *obj = actual.asObject()) {
+ } else if (const Object *obj = actual.as<Object>()) {
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
@@ -1379,7 +1366,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (returnType == QMetaType::UnknownType) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method return type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1392,7 +1379,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method parameter type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1606,9 +1593,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
- else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+ else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@@ -1630,7 +1617,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
}
} else {
QObject *o = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
}
@@ -1754,14 +1741,14 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
return method.asReturnedValue();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
{
Scope valueScope(scope);
Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
method->d()->propertyCache = valueType->d()->propertyCache;
method->d()->index = index;
method->d()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = valueType;
+ method->d()->valueTypeWrapper = *valueType;
return method.asReturnedValue();
}
@@ -1777,7 +1764,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject()
return object->metaObject();
}
-QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
{
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
@@ -1803,7 +1790,7 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return ctx->d()->engine->newString(result)->asReturnedValue();
}
-QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
{
if (!d()->object)
return Encode::undefined();
@@ -1822,13 +1809,13 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
+ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
{
- QObjectMethod *This = static_cast<QObjectMethod*>(m);
+ const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
return This->callInternal(callData);
}
-ReturnedValue QObjectMethod::callInternal(CallData *callData)
+ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
Scope scope(engine());
ScopedContext context(scope, scope.engine->currentContext());
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 24e8b29e08..2d10006d97 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -54,7 +54,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -104,7 +104,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object.data(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const;
static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
@@ -114,26 +114,28 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
using Object::get;
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired);
- void setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired);
+ static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
+ void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
+
+ void destroyObject(bool lastCall);
protected:
static bool isEqualTo(Managed *that, Managed *o);
private:
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
- static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired = true);
+ static void setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
@@ -149,17 +151,17 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
enum { DestroyMethod = -1, ToStringMethod = -2 };
static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal = Primitive::undefinedValue());
- static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
+ static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object.data(); }
- QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
- QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
+ QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const;
+ QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const;
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
- ReturnedValue callInternal(CallData *callData);
+ ReturnedValue callInternal(CallData *callData) const;
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 8e18a5fbdd..31fee534ad 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -34,16 +34,16 @@
#include "qv4regexp_p.h"
#include "qv4engine_p.h"
#include "qv4scopedvalue_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
using namespace QV4;
RegExpCache::~RegExpCache()
{
- for (RegExpCache::Iterator it = begin(), e = end();
- it != e; ++it)
- it.value()->cache = 0;
- clear();
+ for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) {
+ if (RegExp *re = it.value().as<RegExp>())
+ re->d()->cache = 0;
+ }
}
DEFINE_MANAGED_VTABLE(RegExp);
@@ -68,19 +68,18 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
RegExpCacheKey key(pattern, ignoreCase, multiline);
RegExpCache *cache = engine->regExpCache;
- if (cache) {
- if (Heap::RegExp *result = cache->value(key))
- return result;
- }
+ if (!cache)
+ cache = engine->regExpCache = new RegExpCache;
+
+ QV4::WeakValue &cachedValue = (*cache)[key];
+ if (QV4::RegExp *result = cachedValue.as<RegExp>())
+ return result->d();
Scope scope(engine);
Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
- if (!cache)
- cache = engine->regExpCache = new RegExpCache;
-
result->d()->cache = cache;
- cache->insert(key, result->d());
+ cachedValue.set(engine, result);
return result->d();
}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 819e31e5f1..af6e346ea8 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -133,8 +133,7 @@ inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
-// ### GC
-class RegExpCache : public QHash<RegExpCacheKey, Heap::RegExp*>
+class RegExpCache : public QHash<RegExpCacheKey, WeakValue>
{
public:
~RegExpCache();
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f6e88e62b7..329e5d2c56 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -75,7 +75,7 @@ Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
}
Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->regExpPrototype())
, value(value->d())
, global(global)
{
@@ -88,7 +88,7 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *valu
// 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.asObject())
+ : Heap::Object(engine->emptyClass, engine->regExpPrototype())
{
value = 0;
global = false;
@@ -174,7 +174,7 @@ void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
Property *RegExpObject::lastIndexProperty()
{
- Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex));
+ Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
return propertyAt(0);
}
@@ -231,14 +231,14 @@ Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
void Heap::RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
- lastInput = internalClass->engine->id_empty;
+ lastInput = internalClass->engine->id_empty()->d();
lastMatchStart = 0;
lastMatchEnd = 0;
}
-ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
ScopedContext ctx(scope, scope.engine->currentContext());
ScopedValue r(scope, callData->argument(0));
@@ -286,7 +286,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
}
-ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
+ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
{
if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
if (callData->argc == 1 || callData->args[1].isUndefined())
@@ -300,7 +300,7 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
This->lastMatch.mark(e);
- This->lastInput.mark(e);
+ This->lastInput->mark(e);
FunctionObject::markObjects(that, e);
}
@@ -310,8 +310,8 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
ScopedObject o(scope);
ScopedObject ctor(scope, constructor);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(2));
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
@@ -337,7 +337,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
@@ -363,7 +363,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
@@ -372,7 +372,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
// fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject()));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype()));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
@@ -388,7 +388,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
- dd->lastInput = arg->stringValue();
+ dd->lastInput = arg->stringValue()->d();
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
@@ -425,7 +425,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
ScopedCallData callData(scope, ctx->argc());
memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value));
- Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData));
+ Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(callData));
r->d()->value = re->value();
r->d()->global = re->global();
@@ -436,7 +436,7 @@ template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -446,7 +446,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -455,13 +455,13 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
- return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue();
+ return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
}
@@ -469,7 +469,7 @@ ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index f5f255faf5..29d20614de 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -61,14 +61,14 @@ struct RegExpObject : Object {
RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
- RegExp *value;
+ Pointer<RegExp> value;
bool global;
};
struct RegExpCtor : FunctionObject {
RegExpCtor(QV4::ExecutionContext *scope);
Value lastMatch;
- StringValue lastInput;
+ Pointer<String> lastInput;
int lastMatchStart;
int lastMatchEnd;
void clearLastMatch();
@@ -117,12 +117,12 @@ struct RegExpCtor: FunctionObject
V4_OBJECT2(RegExpCtor, FunctionObject)
Value lastMatch() { return d()->lastMatch; }
- StringValue lastInput() { return d()->lastInput; }
+ Heap::String *lastInput() { return d()->lastInput; }
int lastMatchStart() { return d()->lastMatchStart; }
int lastMatchEnd() { return d()->lastMatchEnd; }
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -146,7 +146,7 @@ struct RegExpPrototype: RegExpObject
};
inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype.asObject())
+ : RegExpObject(e->emptyClass, e->objectPrototype())
{
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index b66e917b87..b8ea6d7a87 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -40,12 +40,15 @@
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4dateobject_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "private/qlocale_tools_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include "qv4qobjectwrapper_p.h"
#include <private/qv8engine_p.h>
#endif
@@ -313,14 +316,14 @@ ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right)
{
Scope scope(engine);
- ScopedFunctionObject f(scope, right.asFunctionObject());
+ ScopedFunctionObject f(scope, right.as<FunctionObject>());
if (!f)
return engine->throwTypeError();
if (f->isBoundFunction())
f = static_cast<BoundFunction *>(f.getPointer())->target();
- ScopedObject v(scope, left.asObject());
+ ScopedObject v(scope, left.as<Object>());
if (!v)
return Encode(false);
@@ -380,10 +383,10 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n
return engine->newString(qstr);
}
-ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
+ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint)
{
if (typeHint == PREFERREDTYPE_HINT) {
- if (object->asDateObject())
+ if (object->as<DateObject>())
typeHint = STRING_HINT;
else
typeHint = NUMBER_HINT;
@@ -393,18 +396,18 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- StringValue *meth1 = &engine->id_toString;
- StringValue *meth2 = &engine->id_valueOf;
+ String *meth1 = engine->id_toString();
+ String *meth2 = engine->id_valueOf();
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
Scope scope(engine);
ScopedCallData callData(scope, 0);
- callData->thisObject = object;
+ callData->thisObject = *object;
- ScopedValue conv(scope, object->get(*meth1));
- if (FunctionObject *o = conv->asFunctionObject()) {
+ ScopedValue conv(scope, object->get(meth1));
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -413,8 +416,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- conv = object->get(*meth2);
- if (FunctionObject *o = conv->asFunctionObject()) {
+ conv = object->get(meth2);
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -437,7 +440,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
Q_ASSERT(value.isString());
- return engine->newStringObject(value);
+ return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
return engine->newNumberObject(value.asDouble());
@@ -450,14 +453,14 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -467,7 +470,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -481,14 +484,14 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -498,7 +501,7 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -578,7 +581,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object,
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -912,7 +915,7 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal
return engine->throwTypeError();
ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval))
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval()))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
return o->call(callData);
@@ -934,7 +937,7 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
if (base)
callData->thisObject = base;
- FunctionObject *o = func->asFunctionObject();
+ FunctionObject *o = func->as<FunctionObject>();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
if (base)
@@ -943,13 +946,37 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
return engine->throwTypeError(msg);
}
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
return o->call(callData);
}
+ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
+ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
@@ -1037,7 +1064,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
if (scope.engine->hasException)
return Encode::undefined();
- Object *f = func->asObject();
+ Object *f = func->as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1046,7 +1073,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData)
{
- Object *f = func.asObject();
+ const Object *f = func.as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1092,24 +1119,24 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
ScopedString res(scope);
switch (value.type()) {
case Value::Undefined_Type:
- res = engine->id_undefined;
+ res = engine->id_undefined();
break;
case Value::Null_Type:
- res = engine->id_object;
+ res = engine->id_object();
break;
case Value::Boolean_Type:
- res = engine->id_boolean;
+ res = engine->id_boolean();
break;
case Value::Managed_Type:
if (value.isString())
- res = engine->id_string;
- else if (value.objectValue()->asFunctionObject())
- res = engine->id_function;
+ res = engine->id_string();
+ else if (value.objectValue()->as<FunctionObject>())
+ res = engine->id_function();
else
- res = engine->id_object; // ### implementation-defined
+ res = engine->id_object(); // ### implementation-defined
break;
default:
- res = engine->id_number;
+ res = engine->id_number();
break;
}
return res.asReturnedValue();
@@ -1202,7 +1229,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
{
Scope scope(engine);
QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
- ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject()));
+ ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1242,7 +1269,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->currentContext()->type >= Heap::ExecutionContext::Type_CallContext);
+ 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();
@@ -1327,34 +1354,16 @@ unsigned Runtime::doubleToUInt(const double &d)
return Primitive::toUInt32(d);
}
-#ifndef V4_BOOTSTRAP
-
-ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
+ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
+ return engine->qmlContext()->asReturnedValue();
}
-ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
-{
- Q_ASSERT(engine->qmlContextObject());
- Scope scope(engine);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->idObjectsArray();
-}
-
-ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
-{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
- if (!context)
- return Encode::undefined();
- return QObjectWrapper::wrap(engine, context->contextObject);
-}
+#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
+ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- return QObjectWrapper::wrap(engine, c->getScopeObject());
+ return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1365,21 +1374,29 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu
engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired);
}
QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- QObject *scopeObject = c->getScopeObject();
+ QObject *scopeObject = engine->qmlScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
QJSEngine *jsEngine = engine->jsEngine();
QQmlData::ensurePropertyCache(jsEngine, attachedObject);
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
+ return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true);
+}
+
+ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false);
+}
+
+ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false);
}
ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1390,8 +1407,34 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c
scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired);
+}
+
+ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index)
+{
+ Scope scope(engine);
+ const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
+ QQmlContextData *context = qmlContext.d()->qml->context;
+ if (!context || index >= (uint)context->idValueCount)
+ return Encode::undefined();
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (ep && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
+
+ return QObjectWrapper::wrap(engine, context->idValues[index].data());
+}
+
+void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value);
+}
+
+void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value);
}
void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
@@ -1402,13 +1445,12 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object
engine->throwTypeError(QStringLiteral("Cannot write property of null"));
return;
}
- ScopedContext ctx(scope, engine->currentContext());
- wrapper->setProperty(ctx, propertyIndex, value);
+ wrapper->setProperty(engine, propertyIndex, value);
}
ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
+ QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return context->importedScripts.value();
@@ -1428,7 +1470,7 @@ void Runtime::convertThisToObject(ExecutionEngine *engine)
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
- *t = engine->globalObject()->asReturnedValue();
+ *t = engine->globalObject->asReturnedValue();
} else {
*t = t->toObject(engine)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index f2f90bbc15..f597e4b2e3 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -34,8 +34,9 @@
#define QMLJS_RUNTIME_H
#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4context_p.h"
+#include "qv4engine_p.h"
#include "qv4math_p.h"
#include <QtCore/qnumeric.h>
@@ -90,6 +91,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// call
static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
+ static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData);
@@ -206,19 +209,23 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static unsigned doubleToUInt(const double &d);
// qml
- static ReturnedValue getQmlIdArray(NoThrowEngine *ctx);
- static ReturnedValue getQmlImportedScripts(NoThrowEngine *ctx);
- static ReturnedValue getQmlContextObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlScopeObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlSingleton(NoThrowEngine *ctx, int nameIndex);
+ static ReturnedValue getQmlContext(NoThrowEngine *engine);
+ static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine);
+ static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex);
static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex);
+ static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
+ static ReturnedValue getQmlIdObject(ExecutionEngine *engine, const Value &context, uint index);
+
+ static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
+ static void setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value);
};
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
- static ReturnedValue objectDefaultValue(Object *object, int typeHint);
+ static ReturnedValue objectDefaultValue(const Object *object, int typeHint);
static ReturnedValue toPrimitive(const Value &value, int typeHint);
static double stringToNumber(const QString &s);
@@ -243,7 +250,7 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
#ifndef V4_BOOTSTRAP
inline ReturnedValue RuntimeHelpers::toPrimitive(const Value &value, int typeHint)
{
- Object *o = value.asObject();
+ const Object *o = value.as<Object>();
if (!o)
return value.asReturnedValue();
return RuntimeHelpers::objectDefaultValue(o, typeHint);
@@ -262,7 +269,7 @@ inline ReturnedValue Runtime::uPlus(const Value &value)
if (value.isNumber())
return value.asReturnedValue();
if (value.integerCompatible())
- return Encode(value.int_32);
+ return Encode(value.int_32());
double n = value.toNumberImpl();
return Encode(n);
@@ -369,6 +376,15 @@ inline ReturnedValue Runtime::div(const Value &left, const Value &right)
{
TRACE2(left, right);
+ if (Value::integerCompatible(left, right)) {
+ int lval = left.integerValue();
+ int rval = right.integerValue();
+ if (rval != 0 && (lval % rval == 0))
+ return Encode(int(lval / rval));
+ else
+ return Encode(double(lval) / rval);
+ }
+
double lval = left.toNumber();
double rval = right.toNumber();
return Primitive::fromDouble(lval / rval).asReturnedValue();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 908248f0f0..e19aeaf882 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -85,10 +85,7 @@ struct Scope {
#ifndef QT_NO_DEBUG
size += nValues;
#endif
- Value *ptr = engine->jsStackTop;
- engine->jsStackTop = ptr + nValues;
- memset(ptr, 0, nValues*sizeof(Value));
- return ptr;
+ return engine->jsAlloca(nValues);
}
bool hasException() const {
@@ -110,7 +107,7 @@ struct ScopedValue
ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = 0;
+ ptr->setRawValue(0);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -128,9 +125,9 @@ struct ScopedValue
ScopedValue(const Scope &scope, Heap::Base *o)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = o;
+ ptr->setM(o);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
#ifndef QT_NO_DEBUG
++scope.size;
@@ -140,7 +137,7 @@ struct ScopedValue
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = m->asReturnedValue();
+ ptr->setRawValue(m->asReturnedValue());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -149,7 +146,7 @@ struct ScopedValue
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = v;
+ ptr->setRawValue(v);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -161,9 +158,9 @@ struct ScopedValue
}
ScopedValue &operator=(Heap::Base *o) {
- ptr->m = o;
+ ptr->setM(o);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
return *this;
}
@@ -174,7 +171,7 @@ struct ScopedValue
}
ScopedValue &operator=(const ReturnedValue &v) {
- ptr->val = v;
+ ptr->setRawValue(v);
return *this;
}
@@ -202,30 +199,29 @@ struct Scoped
{
enum _Convert { Convert };
- inline void setPointer(Managed *p) {
- ptr->m = p ? p->m : 0;
+ inline void setPointer(const Managed *p) {
+ ptr->setM(p ? p->m() : 0);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = 0;
+ ptr->setM(0);
#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
- // ### GC FIX casting below to be safe
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -235,7 +231,7 @@ struct Scoped
Value v;
v = o;
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -243,7 +239,7 @@ struct Scoped
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(*v.ptr));
+ setPointer(v.ptr->as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -252,7 +248,7 @@ struct Scoped
Scoped(const Scope &scope, const Value &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, v);
+ ptr->setRawValue(value_convert<T>(scope.engine, v));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -261,7 +257,7 @@ struct Scoped
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -287,7 +283,7 @@ struct Scoped
Scoped(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -295,16 +291,14 @@ struct Scoped
Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v));
+ ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
Scoped<T> &operator=(Heap::Base *o) {
- Value v;
- v = o;
- setPointer(value_cast<T>(v));
+ setPointer(Value::fromHeapObject(o).as<T>());
return *this;
}
Scoped<T> &operator=(typename T::Data *t) {
@@ -312,16 +306,16 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(const Value &v) {
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
return *this;
}
Scoped<T> &operator=(const ReturnedValue &v) {
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
return *this;
}
@@ -347,21 +341,21 @@ struct Scoped
}
bool operator!() const {
- return !ptr->m;
+ return !ptr->m();
}
operator void *() const {
- return ptr->m;
+ return ptr->m();
}
T *getPointer() {
return ptr->cast<T>();
}
- typename T::Data **getRef() {
- return reinterpret_cast<typename T::Data **>(&ptr->m);
+ Value *getRef() {
+ return ptr;
}
ReturnedValue asReturnedValue() const {
- return ptr->m ? ptr->val : Encode::undefined();
+ return ptr->m() ? ptr->rawValue() : Encode::undefined();
}
Value *ptr;
@@ -390,41 +384,14 @@ struct ScopedCallData {
inline Value &Value::operator =(const ScopedValue &v)
{
- val = v.ptr->val;
+ _val = v.ptr->val();
return *this;
}
template<typename T>
inline Value &Value::operator=(const Scoped<T> &t)
{
- val = t.ptr->val;
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(T *t)
-{
- m = t ? t->m : 0;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
-{
- m = v.ptr->m;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
-{
- val = t.val;
+ _val = t.ptr->val();
return *this;
}
@@ -453,18 +420,18 @@ struct ExecutionContextSaver
: engine(context->d()->engine)
, savedContext(scope.alloc(1))
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
+ savedContext->setTag(QV4::Value::Managed_Type);
#endif
}
ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
: engine(context->engine)
, savedContext(scope.alloc(1))
{
- savedContext->m = context;
+ savedContext->setM(context);
#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
+ savedContext->setTag(QV4::Value::Managed_Type);
#endif
}
~ExecutionContextSaver()
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 4fde0e2445..0bf4f21acb 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -32,11 +32,12 @@
****************************************************************************/
#include "qv4script_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4functionobject_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -44,6 +45,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4profiling_p.h>
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include <private/qqmlcontextwrapper_p.h>
@@ -86,8 +88,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
, qml(qml->d())
{
Q_ASSERT(scope->inUse());
@@ -97,46 +99,43 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Functio
function->compilationUnit->addref();
Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
+ Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
+ this->scope = scope->newQmlContext(qml);
+ internalClass->engine->popContext();
}
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::QmlContextWrapper *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
, qml(qml->d())
{
Q_ASSERT(scope->inUse());
Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
+ Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
+ this->scope = scope->newQmlContext(qml);
+ internalClass->engine->popContext();
}
-ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
+ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *engine = static_cast<Object *>(that)->engine();
- CHECK_STACK_LIMITS(engine);
+ const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that);
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
+ if (v4->hasException)
+ return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
- Scope scope(engine);
- QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
- if (!This->function())
+ Scope scope(v4);
+ QV4::Function *f = This->function();
+ if (!f)
return QV4::Encode::undefined();
- Scoped<CallContext> ctx(scope, This->d()->qmlContext);
- std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
- engine->pushContext(ctx);
- ScopedValue result(scope, This->function()->code(engine, This->function()->codeData));
- engine->popContext();
+ ScopedContext context(scope, v4->currentContext());
+ Scoped<CallContext> ctx(scope, context->newCallContext(This, callData));
+
+ ExecutionContextSaver ctxSaver(scope, context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f));
return result->asReturnedValue();
}
@@ -147,14 +146,12 @@ void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
if (wrapper->qml)
wrapper->qml->mark(e);
FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
}
static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
{
QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent));
+ 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);
}
@@ -163,10 +160,10 @@ Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContex
{
ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
QV4::Scope valueScope(engine);
- QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
+ QV4::Scoped<QmlContextWrapper> qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
ScopedContext global(valueScope, valueScope.engine->rootContext());
QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject));
- QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context());
+ QV4::Scoped<QmlContext> wrapperContext(valueScope, wrapper->context());
if (!signalParameters.isEmpty()) {
if (error)
@@ -214,7 +211,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -285,7 +282,7 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->engine;
+ QV4::ExecutionEngine *engine = scope->engine();
QV4::Scope valueScope(engine);
if (qml.isUndefined()) {
@@ -293,15 +290,14 @@ ReturnedValue Script::run()
ExecutionContextSaver ctxSaver(valueScope, scope);
ContextStateSaver stateSaver(valueScope, scope);
- scope->strictMode = vmFunction->isStrict();
- scope->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->compilationUnit = vmFunction->compilationUnit;
+ scope->d()->strictMode = vmFunction->isStrict();
+ scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->compilationUnit = vmFunction->compilationUnit;
- return vmFunction->code(engine, vmFunction->codeData);
+ return Q_V4_PROFILE(engine, vmFunction);
} else {
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
+ ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -376,11 +372,10 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
+ ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
return v.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 05a9e45f45..77784dfc4f 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -63,7 +63,7 @@ struct ContextStateSaver {
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
}
ContextStateSaver(Scope &scope, Heap::ExecutionContext *context)
: savedContext(scope.alloc(1))
@@ -72,12 +72,12 @@ struct ContextStateSaver {
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
- savedContext->m = context;
+ savedContext->setM(context);
}
~ContextStateSaver()
{
- Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m);
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
ctx->compilationUnit = compilationUnit;
@@ -87,11 +87,10 @@ struct ContextStateSaver {
namespace Heap {
struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml);
+ QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml);
// Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml);
- Object *qml;
- CallContext *qmlContext;
+ QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::QmlContextWrapper *qml);
+ Pointer<Object> qml;
};
}
@@ -99,21 +98,19 @@ struct QmlBindingWrapper : Heap::FunctionObject {
struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
V4_OBJECT2(QmlBindingWrapper, FunctionObject)
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- Heap::CallContext *context() const { return d()->qmlContext; }
+ Heap::QmlContext *context() const { return static_cast<Heap::QmlContext *>(d()->scope.ptr); }
static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-
-private:
};
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->d()), strictMode(false), inheritContext(false), parsed(false)
+ , 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)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
@@ -125,8 +122,7 @@ struct Q_QML_EXPORT Script {
int line;
int column;
QString sourceCode;
- // ### GC
- Heap::ExecutionContext *scope;
+ ExecutionContext *scope;
bool strictMode;
bool inheritContext;
bool parsed;
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f1f546bece..23bbcc60e1 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -175,7 +175,7 @@ template <> QUrl convertValueToElement(const Value &value)
template <> QModelIndex convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().toModelIndex();
return QModelIndex();
@@ -183,7 +183,7 @@ template <> QModelIndex convertValueToElement(const Value &value)
template <> QItemSelectionRange convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().value<QItemSelectionRange>();
return QItemSelectionRange();
@@ -231,7 +231,7 @@ public:
defineAccessorProperty(QStringLiteral("length"), method_get_length, method_set_length);
}
- QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty)
+ QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
@@ -316,9 +316,9 @@ public:
return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
if (d()->isReference) {
@@ -400,7 +400,7 @@ public:
ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject();
+ callData->thisObject = this->m_ctx->d()->engine->globalObject;
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -419,7 +419,7 @@ public:
}
QV4::Scope scope(ctx);
- if (ctx->argc() == 1 && ctx->args()[0].asFunctionObject()) {
+ if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
CompareFunctor cf(ctx, ctx->args()[0]);
std::sort(d()->container.begin(), d()->container.end(), cf);
} else {
@@ -526,8 +526,8 @@ public:
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
+ { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
static void putIndexed(Managed *that, uint index, const QV4::Value &value)
{ static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
@@ -536,7 +536,7 @@ public:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
};
@@ -544,7 +544,7 @@ public:
template <typename Container>
Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->sequencePrototype())
, container(container)
, propertyIndex(-1)
, isReference(false)
@@ -557,7 +557,7 @@ Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const
template <typename Container>
Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->sequencePrototype())
, object(object)
, propertyIndex(propertyIndex)
, isReference(true)
@@ -605,7 +605,7 @@ void SequencePrototype::init()
{
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
}
#undef REGISTER_QML_SEQUENCE_METATYPE
@@ -700,11 +700,11 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
{
*succeeded = true;
- if (!array.asArrayObject()) {
+ if (!array.as<ArrayObject>()) {
*succeeded = false;
return QVariant();
}
- QV4::Scope scope(array.asObject()->engine());
+ QV4::Scope scope(array.as<Object>()->engine());
QV4::ScopedArrayObject a(scope, array);
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
@@ -717,7 +717,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
return qMetaTypeId<SequenceType>(); \
} else
-int SequencePrototype::metaTypeForSequence(QV4::Object *object)
+int SequencePrototype::metaTypeForSequence(const QV4::Object *object)
{
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
/*else*/ {
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 9949278a89..560c3c27ca 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -48,9 +48,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4context_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ struct SequencePrototype : public QV4::Object
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
- static int metaTypeForSequence(Object *object);
+ static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
static QVariant toVariant(const Value &array, int typeHint, bool *succeeded);
};
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 31d85df13e..33b40796a4 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -37,7 +37,7 @@
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4sequenceobject_p.h>
@@ -168,11 +168,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.asFunctionObject()) {
+ } else if (v.as<FunctionObject>()) {
// XXX TODO: Implement passing function objects between the main and
// worker scripts
push(data, valueheader(WorkerUndefined));
- } else if (QV4::ArrayObject *array = v.asArrayObject()) {
+ } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
uint length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -195,11 +195,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerNumber));
push(data, v.asDouble());
- } else if (QV4::DateObject *d = v.asDateObject()) {
+ } else if (const QV4::DateObject *d = v.as<DateObject>()) {
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerDate));
- push(data, d->date().asDouble());
- } else if (RegExpObject *re = v.as<RegExpObject>()) {
+ push(data, d->date());
+ } else if (const RegExpObject *re = v.as<RegExpObject>()) {
quint32 flags = re->flags();
QString pattern = re->source();
int length = pattern.length() + 1;
@@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
+ } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
// that others can trivially plug in their elements.
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
@@ -231,10 +231,10 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
}
// No other QObject's are allowed to be sent
push(data, valueheader(WorkerUndefined));
- } else if (Object *o = v.asObject()) {
+ } else if (const Object *o = v.as<Object>()) {
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32();
+ uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
uint length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -265,7 +265,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
s = properties->getIndexed(ii);
serialize(data, s, engine);
- QV4::String *str = s->asString();
+ QV4::String *str = s->as<String>();
val = o->get(str);
if (scope.hasException())
scope.engine->catchException();
@@ -356,7 +356,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
QVariant var = qVariantFromValue(ref);
QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s, v);
+ rv->as<Object>()->defineReadonlyProperty(s, v);
agent->release();
agent->setEngine(engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index 06eaffe4c4..d5d48edee7 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -46,7 +46,7 @@
//
#include <QtCore/qbytearray.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 861c7dd28d..8496fc32e7 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -35,11 +35,7 @@
#define QV4SPARSEARRAY_H
#include "qv4global_p.h"
-#include <QtCore/qmap.h>
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
-#include "qv4property_p.h"
-#include <assert.h>
+#include <QtCore/qlist.h>
//#define Q_MAP_DEBUG
#ifdef Q_MAP_DEBUG
@@ -188,7 +184,7 @@ public:
typedef qptrdiff difference_type;
typedef int size_type;
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
void dump() const;
#endif
};
@@ -261,7 +257,7 @@ inline void SparseArray::push_back(uint index, uint len)
n->value = index;
}
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
inline void SparseArray::dump() const
{
const SparseArrayNode *it = begin();
@@ -344,4 +340,4 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey)
QT_END_NAMESPACE
-#endif // QMAP_H
+#endif
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 6d55eb2c18..24a13ddd10 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#ifndef V4_BOOTSTRAP
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
@@ -110,7 +110,7 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (!o->d()->vtable->isString)
+ if (!o->d()->vtable()->isString)
return false;
return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 1cf8f51a29..93a25d7ed5 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -188,6 +188,20 @@ public:
static uint toArrayIndex(const QString &str);
};
+template<>
+inline const String *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isString ? static_cast<const String *>(this) : 0;
+}
+
+#ifndef V4_BOOTSTRAP
+template<>
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
+{
+ return v.toString(e)->asReturnedValue();
+}
+#endif
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index e0b84f6da3..9fbafa7ded 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -36,7 +36,7 @@
#include "qv4regexp_p.h"
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4alloca_p.h"
#include <QtCore/QDateTime>
@@ -70,44 +70,45 @@ DEFINE_OBJECT_VTABLE(StringObject);
Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
{
- Q_ASSERT(vtable == QV4::StringObject::staticVTable());
- value = ic->engine->newString()->asReturnedValue();
- tmpProperty.value = Primitive::undefinedValue();
+ 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));
+ s->defineReadonlyProperty(ic->engine->id_length(), Primitive::fromInt32(0));
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val)
- : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject())
+Heap::StringObject::StringObject(ExecutionEngine *engine, const QV4::String *str)
+ : Heap::Object(engine->emptyClass, engine->stringPrototype())
{
- value = val;
- Q_ASSERT(value.isString());
- tmpProperty.value = Primitive::undefinedValue();
+ string = str->d();
Scope scope(engine);
ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
+ s->defineReadonlyProperty(engine->id_length(), Primitive::fromUInt32(length()));
}
-Property *Heap::StringObject::getIndex(uint index) const
+Heap::String *Heap::StringObject::getIndex(uint index) const
{
- QString str = value.stringValue()->toQString();
+ QString str = string->toQString();
if (index >= (uint)str.length())
return 0;
- tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
- return &tmpProperty;
+ return internalClass->engine->newString(str.mid(index, 1));
+}
+
+uint Heap::StringObject::length() const
+{
+ return string->toQString().length();
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
{
ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine();
Scope scope(v4);
- Scoped<StringObject> o(scope, m->asStringObject());
+ Scoped<StringObject> o(scope, m->as<StringObject>());
Q_ASSERT(!!o);
- if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
+ if (index < static_cast<uint>(o->d()->string->toQString().length())) {
if (v4->currentContext()->strictMode)
v4->throwTypeError();
return false;
@@ -115,20 +116,21 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
StringObject *s = static_cast<StringObject *>(m);
- uint slen = s->d()->value.stringValue()->toQString().length();
+ uint slen = s->d()->string->toQString().length();
if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
PropertyAttributes a;
- Property *pd = s->__getOwnProperty__(*index, &a);
+ Property pd;
+ s->getOwnProperty(*index, &a, &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
- p->copy(pd, a);
+ p->copy(&pd, a);
return;
}
}
@@ -146,8 +148,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
StringObject::Data *o = static_cast<StringObject::Data *>(that);
- o->value.stringValue()->mark(e);
- o->tmpProperty.value.mark(e);
+ o->string->mark(e);
Object::markObjects(that, e);
}
@@ -158,11 +159,11 @@ Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
+ReturnedValue StringCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
- ScopedValue value(scope);
+ ScopedString value(scope);
if (callData->argc)
value = callData->args[0].toString(v4);
else
@@ -170,9 +171,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
return Encode(v4->newStringObject(value));
}
-ReturnedValue StringCtor::call(Managed *m, CallData *callData)
+ReturnedValue StringCtor::call(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
@@ -187,13 +188,13 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), method_fromCharCode, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_toString); // valueOf and toString are identical
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_toString); // valueOf and toString are identical
defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1);
defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
@@ -220,8 +221,8 @@ static QString getThisString(ExecutionContext *ctx)
ScopedValue t(scope, ctx->thisObject());
if (t->isString())
return t->stringValue()->toQString();
- if (StringObject *thisString = t->asStringObject())
- return thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = t->as<StringObject>())
+ return thisString->d()->string->toQString();
if (t->isUndefined() || t->isNull()) {
scope.engine->throwTypeError();
return QString();
@@ -234,10 +235,10 @@ ReturnedValue StringPrototype::method_toString(CallContext *context)
if (context->thisObject().isString())
return context->thisObject().asReturnedValue();
- StringObject *o = context->thisObject().asStringObject();
+ StringObject *o = context->thisObject().as<StringObject>();
if (!o)
return context->engine()->throwTypeError();
- return o->d()->value.asReturnedValue();
+ return Encode(o->d()->string);
}
ReturnedValue StringPrototype::method_charAt(CallContext *context)
@@ -368,7 +369,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ rx = context->d()->engine->regExpCtor()->construct(callData);
}
if (!rx)
@@ -379,7 +380,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
- ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString));
+ ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -470,8 +471,8 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
{
Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->thisObject().asStringObject())
- string = thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = ctx->thisObject().as<StringObject>())
+ string = thisString->d()->string->toQString();
else
string = ctx->thisObject().toQString();
@@ -481,12 +482,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint allocatedMatchOffsets = 64;
uint _matchOffsets[64];
uint *matchOffsets = _matchOffsets;
- uint nMatchOffsets = 0;
ScopedValue searchValue(scope, ctx->argument(0));
Scoped<RegExpObject> regExp(scope, searchValue);
if (regExp) {
uint offset = 0;
+ uint nMatchOffsets = 0;
// We extract the pointer here to work around a compiler bug on Android.
Scoped<RegExp> re(scope, regExp->value());
@@ -519,7 +520,6 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
int idx = string.indexOf(searchString);
if (idx != -1) {
numStringMatches = 1;
- nMatchOffsets = 2;
matchOffsets[0] = idx;
matchOffsets[1] = idx + searchString.length();
}
@@ -593,7 +593,7 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
- regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ regExpValue = ctx->d()->engine->regExpCtor()->construct(callData);
if (scope.engine->hasException)
return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 459dc1322e..aa56a79bc3 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -45,12 +45,11 @@ namespace Heap {
struct StringObject : Object {
StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const Value &value);
- Value value;
+ StringObject(ExecutionEngine *engine, const QV4::String *string);
+ String *string;
- Property *getIndex(uint index) const;
- // ### get rid of tmpProperty
- mutable Property tmpProperty;
+ Heap::String *getIndex(uint index) const;
+ uint length() const;
};
struct StringCtor : FunctionObject {
@@ -63,14 +62,17 @@ struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
- Property *getIndex(uint index) const {
+ Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
}
+ uint length() const {
+ return d()->length();
+ }
static bool deleteIndexedProperty(Managed *m, uint index);
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -78,8 +80,8 @@ struct StringCtor: FunctionObject
{
V4_OBJECT2(StringCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct StringPrototype: StringObject
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 19e541dba8..f06eeb08b9 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4typedarray_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include <cmath>
@@ -201,10 +202,10 @@ Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::T
{
}
-ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArrayCtor> that(scope, static_cast<const TypedArrayCtor *>(m));
if (!callData->argc || !callData->args[0].isObject()) {
// ECMA 6 22.2.1.1
@@ -257,7 +258,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
TypedArrayWrite write =array->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*destElementSize, val);
}
}
@@ -299,7 +300,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
// ECMA 6 22.2.1.3
ScopedObject o(scope, callData->argument(0));
- uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length))->toInteger(), (double)UINT_MAX);
+ uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length()))->toInteger(), (double)UINT_MAX);
if (scope.engine->hasException)
return scope.engine->throwTypeError();
@@ -329,13 +330,13 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
return array.asReturnedValue();
}
-ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData)
+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].asObject()),
+ : Heap::Object(e->emptyClass, e->typedArrayPrototype + t),
type(operations + t),
arrayType(t)
{
@@ -347,10 +348,10 @@ void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
@@ -390,10 +391,10 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
@@ -470,7 +471,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
if (scope.engine->hasException || !o)
return scope.engine->throwTypeError();
- double len = ScopedValue(scope, o->get(scope.engine->id_length))->toNumber();
+ double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
uint l = (uint)len;
if (scope.engine->hasException || l != len)
return scope.engine->throwTypeError();
@@ -523,7 +524,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
TypedArrayWrite write = a->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*elementSize, val);
}
@@ -563,7 +564,7 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
int newLen = end - begin;
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index afd1bb97e7..8e1090dcd2 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -72,7 +72,7 @@ struct TypedArray : Object {
TypedArray(ExecutionEngine *e, Type t);
const TypedArrayOperations *type;
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
Type arrayType;
@@ -113,7 +113,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
};
@@ -121,8 +121,8 @@ struct TypedArrayCtor: FunctionObject
{
V4_OBJECT2(TypedArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 68228f06bb..4c81199a07 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -32,10 +32,11 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4runtime_p.h>
+#include <qv4string_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#endif
#include <wtf/MathExtras.h>
@@ -68,10 +69,32 @@ int Value::toUInt16() const
return (unsigned short)number;
}
+bool Value::toBoolean() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Null_Type:
+ return false;
+ case Value::Boolean_Type:
+ case Value::Integer_Type:
+ return (bool)int_32();
+ case Value::Managed_Type:
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+#else
+ if (isString())
+ return stringValue()->toQString().length() > 0;
+#endif
+ return true;
+ default: // double
+ return doubleValue() && !std::isnan(doubleValue());
+ }
+}
+
double Value::toInteger() const
{
if (integerCompatible())
- return int_32;
+ return int_32();
return Primitive::toInteger(toNumber());
}
@@ -87,10 +110,10 @@ double Value::toNumberImpl() const
#else
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
- {
- Q_ASSERT(isObject());
- Scope scope(objectValue()->engine());
- ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
+ {
+ Q_ASSERT(isObject());
+ Scope scope(objectValue()->engine());
+ ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
if (scope.engine->hasException)
return 0;
return prim->toNumber();
@@ -99,7 +122,7 @@ double Value::toNumberImpl() const
case QV4::Value::Null_Type:
case QV4::Value::Boolean_Type:
case QV4::Value::Integer_Type:
- return int_32;
+ return int_32();
default: // double
Q_UNREACHABLE();
}
@@ -148,7 +171,7 @@ QString Value::toQStringNoThrow() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -184,7 +207,7 @@ QString Value::toQString() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -197,14 +220,14 @@ QString Value::toQString() const
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
- if (val == other.val)
+ if (_val == other._val)
return true;
if (isString() && other.isString())
return stringValue()->isEqualTo(other.stringValue());
if (isInteger() && other.isDouble())
- return int_32 ? (double(int_32) == other.doubleValue()) : (other.val == 0);
+ return int_32() ? (double(int_32()) == other.doubleValue()) : (other._val == 0);
if (isDouble() && other.isInteger())
- return other.int_32 ? (doubleValue() == double(other.int_32)) : (val == 0);
+ return other.int_32() ? (doubleValue() == double(other.int_32())) : (_val == 0);
return false;
}
@@ -281,4 +304,35 @@ Heap::Object *Value::toObject(ExecutionEngine *e) const
return RuntimeHelpers::convertToObject(e, *this);
}
+uint Value::asArrayLength(bool *ok) const
+{
+ *ok = true;
+ if (isInteger()) {
+ if (int_32() >= 0) {
+ return (uint)int_32();
+ } else {
+ *ok = false;
+ return UINT_MAX;
+ }
+ }
+ if (isNumber()) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+ }
+ if (isString())
+ return stringValue()->toUInt(ok);
+
+ uint idx = toUInt32();
+ double d = toNumber();
+ if (d != idx) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
deleted file mode 100644
index f3026900d6..0000000000
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4VALUE_INL_H
-#define QV4VALUE_INL_H
-
-#include <cmath> // this HAS to come
-
-#include "qv4value_p.h"
-
-#include "qv4string_p.h"
-#include "qv4managed_p.h"
-#include "qv4engine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-inline bool Value::isString() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isString;
-}
-inline bool Value::isObject() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isObject;
-}
-
-inline bool Value::isPrimitive() const
-{
- return !isObject();
-}
-
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
-inline void Value::mark(ExecutionEngine *e) const
-{
- if (!val)
- return;
- Managed *m = asManaged();
- if (m)
- m->mark(e);
-}
-
-inline Primitive Primitive::nullValue()
-{
- Primitive v;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(_Null_Type) << Tag_Shift;
-#else
- v.tag = _Null_Type;
- v.int_32 = 0;
-#endif
- return v;
-}
-
-inline Primitive Primitive::fromBoolean(bool b)
-{
- Primitive v;
- v.tag = _Boolean_Type;
- v.int_32 = (bool)b;
- return v;
-}
-
-inline Primitive Primitive::fromDouble(double d)
-{
- Primitive v;
- v.setDouble(d);
- return v;
-}
-
-inline Primitive Primitive::fromInt32(int i)
-{
- Primitive v;
- v.tag = _Integer_Type;
- v.int_32 = i;
- return v;
-}
-
-inline Primitive Primitive::fromUInt32(uint i)
-{
- Primitive v;
- if (i < INT_MAX) {
- v.tag = _Integer_Type;
- v.int_32 = (int)i;
- } else {
- v.setDouble(i);
- }
- return v;
-}
-
-inline double Value::toNumber() const
-{
- if (isInteger())
- return int_32;
- if (isDouble())
- return doubleValue();
- return toNumberImpl();
-}
-
-inline int Value::toInt32() const
-{
- if (isInteger())
- return int_32;
- double d = isNumber() ? doubleValue() : toNumberImpl();
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Primitive::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- return (unsigned int)toInt32();
-}
-
-
-inline bool Value::toBoolean() const
-{
- switch (type()) {
- case Value::Undefined_Type:
- case Value::Null_Type:
- return false;
- case Value::Boolean_Type:
- case Value::Integer_Type:
- return (bool)int_32;
- case Value::Managed_Type:
-#ifdef V4_BOOTSTRAP
- Q_UNIMPLEMENTED();
-#else
- if (isString())
- return stringValue()->toQString().length() > 0;
-#endif
- return true;
- default: // double
- return doubleValue() && !std::isnan(doubleValue());
- }
-}
-
-#ifndef V4_BOOTSTRAP
-inline uint Value::asArrayIndex() const
-{
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- if (!isNumber())
- return UINT_MAX;
- if (isInteger())
- return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
-#else
- if (isInteger() && int_32 >= 0)
- return (uint)int_32;
- if (!isDouble())
- return UINT_MAX;
-#endif
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d)
- return UINT_MAX;
- return idx;
-}
-
-inline uint Value::asArrayLength(bool *ok) const
-{
- *ok = true;
- if (isInteger()) {
- if (int_32 >= 0) {
- return (uint)int_32;
- } else {
- *ok = false;
- return UINT_MAX;
- }
- }
- if (isNumber()) {
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
- }
- if (isString())
- return stringValue()->toUInt(ok);
-
- uint idx = toUInt32();
- double d = toNumber();
- if (d != idx) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
-}
-
-inline Object *Value::asObject() const
-{
- return isObject() ? objectValue() : 0;
-}
-
-inline FunctionObject *Value::asFunctionObject() const
-{
- return isObject() ? managed()->asFunctionObject() : 0;
-}
-
-inline NumberObject *Value::asNumberObject() const
-{
- return isObject() ? managed()->asNumberObject() : 0;
-}
-
-inline StringObject *Value::asStringObject() const
-{
- return isObject() ? managed()->asStringObject() : 0;
-}
-
-inline DateObject *Value::asDateObject() const
-{
- return isObject() ? managed()->asDateObject() : 0;
-}
-
-inline ArrayObject *Value::asArrayObject() const
-{
- return isObject() ? managed()->asArrayObject() : 0;
-}
-
-inline ErrorObject *Value::asErrorObject() const
-{
- return isObject() ? managed()->asErrorObject() : 0;
-}
-
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
-#ifndef V4_BOOTSTRAP
-
-template<>
-inline String *value_cast(const Value &v) {
- return v.asString();
-}
-
-template<>
-inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
-{
- return v.toString(e)->asReturnedValue();
-}
-
-#endif
-
-#endif
-
-} // namespace QV4
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 628950784a..6305e6dfbb 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -37,6 +37,7 @@
#include <QtCore/QString>
#include "qv4global_p.h"
+#include <private/qv4heap_p.h>
/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects
are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */
@@ -50,56 +51,12 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-typedef uint Bool;
-
namespace Heap {
-
-struct Q_QML_EXPORT Base {
- union {
- const ManagedVTable *vtable;
- quintptr mm_data;
- };
-
- inline ReturnedValue asReturnedValue() const;
- inline void mark(QV4::ExecutionEngine *engine);
-
- enum {
- MarkBit = 0x1,
- NotInUse = 0x2,
- PointerMask = ~0x3
- };
-
- ManagedVTable *gcGetVtable() const {
- return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
- }
- inline bool isMarked() const {
- return mm_data & MarkBit;
- }
- inline void setMarkBit() {
- mm_data |= MarkBit;
- }
- inline void clearMarkBit() {
- mm_data &= ~MarkBit;
- }
-
- inline bool inUse() const {
- return !(mm_data & NotInUse);
- }
-
- Base *nextFree() {
- return reinterpret_cast<Base *>(mm_data & PointerMask);
- }
- void setNextFree(Base *m) {
- mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
- }
-
- void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Heap::Base *m) { return m; }
- void operator delete(void *, Heap::Base *) {}
-};
-
+ struct Base;
}
+typedef uint Bool;
+
struct Q_QML_PRIVATE_EXPORT Value
{
/*
@@ -124,30 +81,38 @@ struct Q_QML_PRIVATE_EXPORT Value
Bit 15-17 is then used to encode other immediates.
*/
+ quint64 _val;
+
+ 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()); }
- union {
- quint64 val;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#else
- double dbl;
-#endif
- struct {
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- union {
- uint uint_32;
- int int_32;
-#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#endif
- };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
+ static inline int valueOffset() { return 0; }
+ static inline int tagOffset() { return 4; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
+ Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
+#else // !Q_LITTLE_ENDIAN
+ static inline int valueOffset() { return 4; }
+ static inline int tagOffset() { return 0; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; }
#endif
- };
- };
+
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); }
+#else // !QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); }
+#endif
+
+ Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; }
+ Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); }
+ Q_ALWAYS_INLINE uint uint_32() const { return value(); }
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
enum Masks {
@@ -220,127 +185,127 @@ struct Q_QML_PRIVATE_EXPORT Value
#endif
inline unsigned type() const {
- return tag & Type_Mask;
+ return tag() & Type_Mask;
}
// used internally in property
- inline bool isEmpty() const { return tag == Empty_Type; }
+ inline bool isEmpty() const { return tag() == Empty_Type; }
- inline bool isUndefined() const { return tag == Undefined_Type; }
- inline bool isNull() const { return tag == _Null_Type; }
- inline bool isBoolean() const { return tag == _Boolean_Type; }
+ inline bool isUndefined() const { return tag() == Undefined_Type; }
+ inline bool isNull() const { return tag() == _Null_Type; }
+ inline bool isBoolean() const { return tag ()== _Boolean_Type; }
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
- inline bool isDouble() const { return (val >> IsDouble_Shift); }
- inline bool isNumber() const { return (val >> IsNumber_Shift); }
- inline bool isManaged() const { return !(val >> IsManaged_Shift); }
- inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
- inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; }
+ inline bool isDouble() const { return (_val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (_val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(_val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; }
static inline bool integerCompatible(Value a, Value b) {
return a.integerCompatible() && b.integerCompatible();
}
static inline bool bothDouble(Value a, Value b) {
return a.isDouble() && b.isDouble();
}
- double doubleValue() const {
- Q_ASSERT(isDouble());
- union {
- quint64 i;
- double d;
- } v;
- v.i = val ^ NaNEncodeMask;
- return v.d;
- }
- void setDouble(double d) {
- union {
- quint64 i;
- double d;
- } v;
- v.d = d;
- val = v.i ^ NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
- inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+ inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; }
#else
- inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isManaged() const { return tag == Managed_Type; }
- inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ inline bool isInteger() const { return tag() == _Integer_Type; }
+ inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag() == _Integer_Type || (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag() == Managed_Type; }
+ inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; }
+ inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
}
static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ return ((a.tag() | b.tag()) & NotDouble_Mask) != NotDouble_Mask;
}
- double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
- void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
- inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+ inline bool isNaN() const { return (tag() & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
+ Q_ALWAYS_INLINE double doubleValue() const {
+ Q_ASSERT(isDouble());
+ double d;
+ quint64 v = _val;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ v ^= NaNEncodeMask;
+#endif
+ memcpy(&d, &v, 8);
+ return d;
+ }
+ Q_ALWAYS_INLINE void setDouble(double d) {
+ memcpy(&_val, &d, 8);
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ _val ^= NaNEncodeMask;
+#endif
+ Q_ASSERT(isDouble());
+ }
inline bool isString() const;
inline bool isObject() const;
inline bool isInt32() {
- if (tag == _Integer_Type)
+ if (tag() == _Integer_Type)
return true;
if (isDouble()) {
double d = doubleValue();
int i = (int)d;
if (i == d) {
- int_32 = i;
- tag = _Integer_Type;
+ setInt_32(i);
+ setTag(_Integer_Type);
return true;
}
}
return false;
}
double asDouble() const {
- if (tag == _Integer_Type)
- return int_32;
+ if (tag() == _Integer_Type)
+ return int_32();
return doubleValue();
}
bool booleanValue() const {
- return int_32;
+ return int_32();
}
int integerValue() const {
- return int_32;
+ return int_32();
}
- String *stringValue() const {
- return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE String *stringValue() const {
+ return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
- Object *objectValue() const {
- return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Object *objectValue() const {
+ return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
- Managed *managed() const {
- return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Managed *managed() const {
+ return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
}
- Heap::Base *heapObject() const {
- return m;
+ Q_ALWAYS_INLINE Heap::Base *heapObject() const {
+ return m();
}
- quint64 rawValue() const {
- return val;
+ Q_ALWAYS_INLINE quint64 &rawValueRef() {
+ return _val;
+ }
+ Q_ALWAYS_INLINE quint64 rawValue() const {
+ return _val;
}
+ Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
static inline Value fromHeapObject(Heap::Base *m)
{
Value v;
- v.m = m;
+ v.setRawValue(0);
+ v.setM(m);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- v.tag = Managed_Type;
+ v.setTag(Managed_Type);
#endif
return v;
}
- static inline Value fromManaged(Managed *m);
-
int toUInt16() const;
inline int toInt32() const;
inline unsigned int toUInt32() const;
- inline bool toBoolean() const;
+ bool toBoolean() const;
double toInteger() const;
inline double toNumber() const;
double toNumberImpl() const;
@@ -353,21 +318,32 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool tryIntegerConversion() {
bool b = integerCompatible();
if (b)
- tag = _Integer_Type;
+ setTag(_Integer_Type);
return b;
}
- inline String *asString() const;
- inline Managed *asManaged() const;
- inline Object *asObject() const;
- inline FunctionObject *asFunctionObject() const;
- inline NumberObject *asNumberObject() const;
- inline StringObject *asStringObject() const;
- inline DateObject *asDateObject() const;
- inline ArrayObject *asArrayObject() const;
- inline ErrorObject *asErrorObject() const;
+ template <typename T>
+ const T *as() const {
+ if (!m() || !isManaged())
+ return 0;
+
+ Q_ASSERT(m()->vtable());
+#if !defined(QT_NO_QOBJECT_CHECK)
+ static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
+#endif
+ const VTable *vt = m()->vtable();
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<const T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
+ }
+ template <typename T>
+ T *as() {
+ return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
+ }
- template<typename T> inline T *as() const;
template<typename T> inline T *cast() {
return static_cast<T *>(managed());
}
@@ -376,26 +352,32 @@ struct Q_QML_PRIVATE_EXPORT Value
}
inline uint asArrayIndex() const;
- inline uint asArrayLength(bool *ok) const;
+#ifndef V4_BOOTSTRAP
+ uint asArrayLength(bool *ok) const;
+#endif
- ReturnedValue asReturnedValue() const { return val; }
- static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
+ ReturnedValue asReturnedValue() const { return _val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
// Section 9.12
bool sameValue(Value other) const;
- inline void mark(ExecutionEngine *e) const;
+ inline void mark(ExecutionEngine *e);
Value &operator =(const ScopedValue &v);
- Value &operator=(ReturnedValue v) { val = v; return *this; }
+ Value &operator=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
- val = Value::fromManaged(m).val;
+ if (!m) {
+ setTagValue(Undefined_Type, 0);
+ } else {
+ _val = reinterpret_cast<Value *>(m)->_val;
+ }
return *this;
}
Value &operator=(Heap::Base *o) {
- m = o;
+ setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ setTag(Managed_Type);
#endif
return *this;
}
@@ -403,17 +385,68 @@ struct Q_QML_PRIVATE_EXPORT Value
template<typename T>
Value &operator=(const Scoped<T> &t);
Value &operator=(const Value &v) {
- val = v.val;
+ _val = v._val;
return *this;
}
};
-inline Managed *Value::asManaged() const
+inline bool Value::isString() const
+{
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isString;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isObject;
+}
+
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
+
+inline double Value::toNumber() const
+{
+ if (isInteger())
+ return int_32();
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+
+#ifndef V4_BOOTSTRAP
+inline uint Value::asArrayIndex() const
{
- if (isManaged())
- return managed();
- return 0;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32() >= 0 ? (uint)int_32() : UINT_MAX;
+#else
+ if (isInteger() && int_32() >= 0)
+ return (uint)int_32();
+ if (!isDouble())
+ return UINT_MAX;
+#endif
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
+ return UINT_MAX;
+ return idx;
}
+#endif
+
+inline
+ReturnedValue Heap::Base::asReturnedValue() const
+{
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
+}
+
+
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
@@ -437,10 +470,11 @@ inline Primitive Primitive::undefinedValue()
{
Primitive v;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(Undefined_Type) << Tag_Shift;
+ v.setRawValue(quint64(Undefined_Type) << Tag_Shift);
#else
- v.tag = Undefined_Type;
- v.int_32 = 0;
+ v.setRawValue(0);
+ v.setTag(Undefined_Type);
+ v.setValue(0);
#endif
return v;
}
@@ -448,39 +482,54 @@ inline Primitive Primitive::undefinedValue()
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.tag = Value::Empty_Type;
- v.uint_32 = 0;
+ v.setTagValue(Value::Empty_Type, 0);
return v;
}
-template <typename T>
-struct TypedValue : public Value
+inline Primitive Primitive::nullValue()
{
- template<typename X>
- TypedValue &operator =(X *x) {
- m = x;
+ Primitive v;
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ v.setRawValue(quint64(_Null_Type) << Tag_Shift);
+#else
+ v.setTagValue(_Null_Type, 0);
#endif
- return *this;
- }
- TypedValue &operator =(T *t);
- TypedValue &operator =(const Scoped<T> &v);
-// TypedValue &operator =(const ManagedRef<T> &v);
-
- TypedValue &operator =(const TypedValue<T> &t);
+ return v;
+}
- bool operator!() const { return !managed(); }
+inline Primitive Primitive::fromBoolean(bool b)
+{
+ Primitive v;
+ v.setTagValue(_Boolean_Type, b);
+ return v;
+}
- operator T *() { return static_cast<T *>(managed()); }
- T *operator->() { return static_cast<T *>(managed()); }
- const T *operator->() const { return static_cast<T *>(managed()); }
- T *getPointer() const { return static_cast<T *>(managed()); }
+inline Primitive Primitive::fromDouble(double d)
+{
+ Primitive v;
+ v.setDouble(d);
+ return v;
+}
- void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
-};
-typedef TypedValue<String> StringValue;
+inline Primitive Primitive::fromInt32(int i)
+{
+ Primitive v;
+ v.setTagValue(_Integer_Type, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32(i);
+ return v;
+}
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.setTagValue(_Integer_Type, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32((int)i);
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
struct Encode {
static ReturnedValue undefined() {
@@ -496,7 +545,7 @@ struct Encode {
Encode(double d) {
Value v;
v.setDouble(d);
- val = v.val;
+ val = v.rawValue();
}
Encode(int i) {
val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
@@ -507,7 +556,7 @@ struct Encode {
} else {
Value v;
v.setDouble(i);
- val = v.val;
+ val = v.rawValue();
}
}
Encode(ReturnedValue v) {
@@ -527,21 +576,29 @@ private:
Encode(void *);
};
-inline
-ReturnedValue Heap::Base::asReturnedValue() const
+template<typename T>
+ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
+
+inline int Value::toInt32() const
{
- return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
-}
+ if (isInteger())
+ return int_32();
+ double d = isNumber() ? doubleValue() : toNumberImpl();
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
-template<typename T>
-T *value_cast(const Value &v)
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Primitive::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
{
- return v.as<T>();
+ return (unsigned int)toInt32();
}
-template<typename T>
-ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
}
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 966f83acef..f9e26efe71 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -44,7 +44,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
- : Heap::Object(engine->emptyClass, engine->variantPrototype.asObject())
+ : Heap::Object(engine->emptyClass, engine->variantPrototype())
{
data = value;
if (isScarce())
@@ -96,8 +96,8 @@ void VariantPrototype::init()
{
defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0);
defineDefaultProperty(QStringLiteral("destroy"), method_destroy, 0);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
- defineDefaultProperty(engine()->id_toString, method_toString, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
+ defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
@@ -129,7 +129,7 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
return Encode::undefined();
QString result = o->d()->data.toString();
if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
+ result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
return Encode(ctx->d()->engine->newString(result));
}
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 2b48412c4d..b19f12bb98 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -49,7 +49,7 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qvariant.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 390bbf5ee3..0edd7378a7 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -37,13 +37,14 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4string_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -512,6 +513,28 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
+ MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
+ Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(StoreContextObjectProperty)
+ Runtime::setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadIdObject)
+ STOREVALUE(instr.result, Runtime::getQmlIdObject(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(LoadIdObject)
+
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
@@ -565,6 +588,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
+ MOTH_BEGIN_INSTR(CallScopeObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(CallContextObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallContextObjectProperty)
+
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
@@ -858,28 +901,20 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
engine->currentContext()->lineNumber = instr.lineNumber;
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
- MOTH_END_INSTR(Debug)
+ MOTH_END_INSTR(Line)
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
MOTH_END_INSTR(LoadThis)
- MOTH_BEGIN_INSTR(LoadQmlIdArray)
- VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadQmlIdArray)
+ MOTH_BEGIN_INSTR(LoadQmlContext)
+ VALUE(instr.result) = Runtime::getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- MOTH_BEGIN_INSTR(LoadQmlContextObject)
- VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadContextObject)
-
- MOTH_BEGIN_INSTR(LoadQmlScopeObject)
- VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadScopeObject)
-
MOTH_BEGIN_INSTR(LoadQmlSingleton)
VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
MOTH_END_INSTR(LoadQmlSingleton)
diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri
new file mode 100644
index 0000000000..04b7566ccc
--- /dev/null
+++ b/src/qml/memory/memory.pri
@@ -0,0 +1,14 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$OUT_PWD
+
+!qmldevtools_build {
+SOURCES += \
+ $$PWD/qv4mm.cpp \
+
+HEADERS += \
+ $$PWD/qv4mm_p.h
+
+}
+
+HEADERS += \
+ $$PWD/qv4heap_p.h
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
new file mode 100644
index 0000000000..a93e4191b0
--- /dev/null
+++ b/src/qml/memory/qv4heap_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4HEAP_P_H
+#define QV4HEAP_P_H
+
+#include <QtCore/QString>
+#include <private/qv4global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct VTable
+{
+ const VTable * const parent;
+ uint isExecutionContext : 1;
+ uint isString : 1;
+ uint isObject : 1;
+ uint isFunctionObject : 1;
+ uint isErrorObject : 1;
+ uint isArrayData : 1;
+ uint unused : 18;
+ uint type : 8;
+ const char *className;
+ void (*destroy)(Heap::Base *);
+ void (*markObjects)(Heap::Base *, ExecutionEngine *e);
+ bool (*isEqualTo)(Managed *m, Managed *other);
+};
+
+namespace Heap {
+
+struct Q_QML_EXPORT Base {
+ quintptr mm_data; // vtable and markbit
+
+ inline ReturnedValue asReturnedValue() const;
+ inline void mark(QV4::ExecutionEngine *engine);
+
+ enum {
+ MarkBit = 0x1,
+ NotInUse = 0x2,
+ PointerMask = ~0x3
+ };
+
+ void setVtable(const VTable *v) {
+ Q_ASSERT(!(mm_data & MarkBit));
+ mm_data = reinterpret_cast<quintptr>(v);
+ }
+ VTable *vtable() const {
+ return reinterpret_cast<VTable *>(mm_data & PointerMask);
+ }
+ inline bool isMarked() const {
+ return mm_data & MarkBit;
+ }
+ inline void setMarkBit() {
+ mm_data |= MarkBit;
+ }
+ inline void clearMarkBit() {
+ mm_data &= ~MarkBit;
+ }
+
+ inline bool inUse() const {
+ return !(mm_data & NotInUse);
+ }
+
+ Base *nextFree() {
+ return reinterpret_cast<Base *>(mm_data & PointerMask);
+ }
+ void setNextFree(Base *m) {
+ mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
+ }
+
+ void *operator new(size_t, Managed *m) { return m; }
+ void *operator new(size_t, Heap::Base *m) { return m; }
+ void operator delete(void *, Heap::Base *) {}
+};
+
+template <typename T>
+struct Pointer {
+ Pointer() {}
+ Pointer(T *t) : ptr(t) {}
+
+ T *operator->() const { return ptr; }
+ operator T *() const { return ptr; }
+
+ Pointer &operator =(T *t) { ptr = t; return *this; }
+
+ template <typename Type>
+ Type *cast() { return static_cast<Type *>(ptr); }
+
+ T *ptr;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 64491e1376..38b4e1eaf1 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -111,8 +111,6 @@ struct MemoryManager::Data
LargeItem *largeItems;
std::size_t totalLargeItemsAllocated;
- GCDeletable *deletable;
-
// statistics:
#ifdef DETAILED_MM_STATS
QVector<unsigned> allocSizeCounters;
@@ -129,7 +127,6 @@ struct MemoryManager::Data
, unmanagedHeapSizeGCLimit(64 * 1024)
, largeItems(0)
, totalLargeItemsAllocated(0)
- , deletable(0)
{
memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
@@ -189,15 +186,15 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->gcGetVtable()->isString) {
+ if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) {
std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize();
Q_ASSERT(*unmanagedHeapSize >= heapBytes);
// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes";
*unmanagedHeapSize -= heapBytes;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
memset(m, 0, header->itemSize);
#ifdef V4_USE_VALGRIND
@@ -307,7 +304,6 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
m_d->heapChunks.append(allocation);
- std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
header->itemSize = int(size);
@@ -353,8 +349,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -377,11 +373,9 @@ void MemoryManager::mark()
for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
if (!(*it).isManaged())
continue;
- if ((*it).managed()->d()->gcGetVtable() != QObjectWrapper::staticVTable())
+ if ((*it).managed()->d()->vtable() != QObjectWrapper::staticVTable())
continue;
QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
- if (!qobjectWrapper)
- continue;
QObject *qobject = qobjectWrapper->object();
if (!qobject)
continue;
@@ -408,13 +402,20 @@ void MemoryManager::mark()
void MemoryManager::sweep(bool lastSweep)
{
- if (m_weakValues) {
- for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (Managed *m = (*it).asManaged()) {
- if (!m->markBit())
- (*it) = Primitive::undefinedValue();
- }
+ for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
+ if (!(*it).isManaged())
+ continue;
+ Managed *m = (*it).as<Managed>();
+ if (m->markBit())
+ continue;
+ // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed
+ // signal before we start sweeping the heap
+ if ((*it).managed()->d()->vtable() == QObjectWrapper::staticVTable()) {
+ QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
+ qobjectWrapper->destroyObject(lastSweep);
}
+
+ (*it) = Primitive::undefinedValue();
}
if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
@@ -473,8 +474,8 @@ void MemoryManager::sweep(bool lastSweep)
i = i->next;
continue;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
*last = i->next;
free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
@@ -482,15 +483,6 @@ void MemoryManager::sweep(bool lastSweep)
i = *last;
}
- GCDeletable *deletable = m_d->deletable;
- m_d->deletable = 0;
- while (deletable) {
- GCDeletable *next = deletable->next;
- deletable->lastCall = lastSweep;
- delete deletable;
- deletable = next;
- }
-
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
Heap::ExecutionContext *ctx = engine()->current;
@@ -554,7 +546,7 @@ void MemoryManager::runGC()
size_t MemoryManager::getUsedMem() const
{
size_t usedMem = 0;
- for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
+ for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
@@ -590,10 +582,10 @@ void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta)
MemoryManager::~MemoryManager()
{
delete m_persistentValues;
- delete m_weakValues;
- m_weakValues = 0;
sweep(/*lastSweep*/true);
+
+ delete m_weakValues;
#ifdef V4_USE_VALGRIND
VALGRIND_DESTROY_MEMPOOL(this);
#endif
@@ -618,12 +610,6 @@ void MemoryManager::dumpStats() const
#endif // DETAILED_MM_STATS
}
-void MemoryManager::registerDeletable(GCDeletable *d)
-{
- d->next = m_d->deletable;
- m_d->deletable = d;
-}
-
#ifdef DETAILED_MM_STATS
void MemoryManager::willAllocate(std::size_t size)
{
@@ -641,7 +627,7 @@ void MemoryManager::collectFromJSStack() const
Value *v = m_d->engine->jsStackBase;
Value *top = m_d->engine->jsStackTop;
while (v < top) {
- Managed *m = v->asManaged();
+ 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);
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 7f6d2edba3..c01866ff11 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -34,9 +34,9 @@
#ifndef QV4GC_H
#define QV4GC_H
-#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
+#include <private/qv4global_p.h>
+#include <private/qv4value_p.h>
+#include <private/qv4scopedvalue_p.h>
//#define DETAILED_MM_STATS
@@ -87,7 +87,7 @@ public:
{
size = align(size);
Heap::Base *o = allocData(size, unmanagedSize);
- o->vtable = ManagedType::staticVTable();
+ o->setVtable(ManagedType::staticVTable());
return static_cast<typename ManagedType::Data *>(o);
}
@@ -162,8 +162,6 @@ public:
void dumpStats() const;
- void registerDeletable(GCDeletable *d);
-
size_t getUsedMem() const;
size_t getAllocatedMem() const;
size_t getLargeItemsMem() const;
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 16927251c7..c7ac5919bd 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -104,28 +104,6 @@ public:
template <typename _Tp> _Tp *New() { return new (this->allocate(sizeof(_Tp))) _Tp(); }
- template <typename PoolContentType, typename Visitor>
- void visitManagedPool(Visitor &visitor)
- {
- for (int i = 0; i <= _blockCount; ++i) {
- char *p = _blocks[i];
- char *end = p + BLOCK_SIZE;
- if (i == _blockCount) {
- Q_ASSERT(_ptr <= end);
- end = _ptr;
- }
-
- Q_ASSERT(p <= end);
-
- const qptrdiff increment = (sizeof(PoolContentType) + 7) & ~7;
-
- while (p + increment <= end) {
- visitor(reinterpret_cast<PoolContentType*>(p));
- p += increment;
- }
- }
- }
-
private:
void *allocate_helper(size_t size)
{
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 6e06fb42ef..d75262bf0b 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -8,6 +8,9 @@ win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
win32:!wince*:!winrt:LIBS += -lshell32
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT.
+gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
+
MODULE_PLUGIN_TYPES = \
qmltooling
@@ -33,6 +36,7 @@ HEADERS += qtqmlglobal.h \
#modules
include(util/util.pri)
+include(memory/memory.pri)
include(parser/parser.pri)
include(compiler/compiler.pri)
include(jsapi/jsapi.pri)
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index 4b109107f9..51697b0aff 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qpodvector_p.h \
$$PWD/qhashedstring_p.h \
$$PWD/qqmlrefcount_p.h \
- $$PWD/qqmlpool_p.h \
$$PWD/qfieldlist_p.h \
$$PWD/qhashfield_p.h \
$$PWD/qqmlthread_p.h \
@@ -20,7 +19,6 @@ HEADERS += \
SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qhashedstring.cpp \
- $$PWD/qqmlpool.cpp \
$$PWD/qqmlthread.cpp \
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
diff --git a/src/qml/qml/ftw/qqmlpool.cpp b/src/qml/qml/ftw/qqmlpool.cpp
deleted file mode 100644
index b86dcba107..0000000000
--- a/src/qml/qml/ftw/qqmlpool.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlpool_p.h"
-#include <stdlib.h>
-
-#ifdef Q_OS_QNX
-#include <malloc.h>
-#endif
-
-// #define POOL_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-void QQmlPool::newpage()
-{
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Allocating page");
-#endif
-
- Page *page = (Page *)malloc(sizeof(Page));
- page->header.next = _page;
- page->header.free = page->memory;
- _page = page;
-}
-
-void QQmlPool::clear()
-{
-#ifdef POOL_DEBUG
- int count = 0;
-#endif
-
- Class *c = _classList;
- while (c) {
- Class *n = c->_next;
- c->_destroy(c);
-#ifdef POOL_DEBUG
- ++count;
-#endif
- c = n;
- }
-
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Destroyed %d objects", count);
-#endif
-
- Page *p = _page;
- while (p) {
- Page *n = p->header.next;
- free(p);
- p = n;
- }
-
- _classList = 0;
- _page = 0;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qqmlpool_p.h b/src/qml/qml/ftw/qqmlpool_p.h
deleted file mode 100644
index 4956cd81d8..0000000000
--- a/src/qml/qml/ftw/qqmlpool_p.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLPOOL_P_H
-#define QQMLPOOL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qv4global_p.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qurl.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlPool
-{
-public:
- // The class has a destructor that needs to be called
- class Class {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- Class *_next;
- void (*_destroy)(Class *);
- };
-
- // The class is plain old data and no destructor needs to
- // be called
- class POD {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- };
-
- inline QQmlPool();
- inline ~QQmlPool();
-
- void clear();
-
- template<typename T>
- inline T *New();
- template<typename T>
- inline T *NewRaw();
- template<typename T>
- inline T *NewRawArray(int length);
-
- inline QString *NewString(const QString &);
- inline QByteArray *NewByteArray(const QByteArray &);
- inline QUrl *NewUrl(const QUrl &);
-
- template<typename T>
- struct List {
- List() : m_length(0), m_data(0) {}
- List(const List &o) : m_length(o.m_length), m_data(o.m_data) {}
- List &operator=(const List &o) {
- m_length = o.m_length;
- m_data = o.m_data;
- return *this;
- }
-
- int count() const {
- return m_length;
- }
- int length() const {
- return m_length;
- }
- const T &at(int index) const {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- T &operator[](int index) {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- const T *data() const { return m_data; }
- private:
- friend class QQmlPool;
- List(T *d, int l) : m_length(l), m_data(d) {}
- int m_length;
- T *m_data;
- };
-
- template<typename T>
- inline List<T> NewRawList(int length);
-
-private:
- struct StringClass : public QString, public Class {
- };
- struct ByteArrayClass : public QByteArray, public Class {
- };
- struct UrlClass : public QUrl, public Class {
- };
-
- inline void *allocate(int size);
- void newpage();
-
- template<typename T>
- inline void initialize(POD *);
- template<typename T>
- inline void initialize(Class *);
- template<typename T>
- static void destroy(Class *c);
-
- struct Page {
- struct Header {
- Page *next;
- char *free;
- } header;
-
- static const int pageSize = 4 * 4096 - sizeof(Header);
-
- char memory[pageSize];
- };
-
- Page *_page;
- Class *_classList;
-};
-
-QQmlPool::QQmlPool()
-: _page(0), _classList(0)
-{
-}
-
-QQmlPool::~QQmlPool()
-{
- clear();
-}
-
-template<typename T>
-T *QQmlPool::New()
-{
- T *rv = new (allocate(sizeof(T))) T;
- initialize<T>(rv);
- rv->_pool = this;
- return rv;
-}
-
-template<typename T>
-T *QQmlPool::NewRaw()
-{
- return (T*)allocate(sizeof(T));
-}
-
-template<typename T>
-T *QQmlPool::NewRawArray(int length)
-{
- return (T*)allocate(length * sizeof(T));
-}
-
-template<typename T>
-QQmlPool::List<T> QQmlPool::NewRawList(int length)
-{
- return List<T>(NewRawArray<T>(length), length);
-}
-
-QString *QQmlPool::NewString(const QString &s)
-{
- QString *rv = New<StringClass>();
- *rv = s;
- return rv;
-}
-
-QByteArray *QQmlPool::NewByteArray(const QByteArray &s)
-{
- QByteArray *rv = New<ByteArrayClass>();
- *rv = s;
- return rv;
-}
-
-QUrl *QQmlPool::NewUrl(const QUrl &s)
-{
- QUrl *rv = New<UrlClass>();
- *rv = s;
- return rv;
-}
-
-void *QQmlPool::allocate(int size)
-{
- if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize))
- newpage();
-
- void *rv = _page->header.free;
- _page->header.free += size + ((8 - size) & 7); // ensure 8 byte alignment;
- return rv;
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::POD *)
-{
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::Class *c)
-{
- c->_next = _classList;
- c->_destroy = &destroy<T>;
- _classList = c;
-}
-
-template<typename T>
-void QQmlPool::destroy(Class *c)
-{
- static_cast<T *>(c)->~T();
-}
-
-QQmlPool *QQmlPool::Class::pool() const
-{
- return _pool;
-}
-
-QQmlPool *QQmlPool::POD::pool() const
-{
- return _pool;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLPOOL_P_H
-
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 59ed77b580..ba2ca43990 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -72,13 +72,16 @@ template<class T>
class QQmlRefPointer
{
public:
+ enum Mode {
+ AddRef,
+ Adopt
+ };
inline QQmlRefPointer();
- inline QQmlRefPointer(T *);
+ inline QQmlRefPointer(T *, Mode m = AddRef);
inline QQmlRefPointer(const QQmlRefPointer<T> &);
inline ~QQmlRefPointer();
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
- inline QQmlRefPointer<T> &operator=(T *);
inline bool isNull() const { return !o; }
@@ -87,7 +90,7 @@ public:
inline operator T*() const { return o; }
inline T* data() const { return o; }
- inline QQmlRefPointer<T> &take(T *);
+ inline QQmlRefPointer<T> &adopt(T *);
private:
T *o;
@@ -133,10 +136,11 @@ QQmlRefPointer<T>::QQmlRefPointer()
}
template<class T>
-QQmlRefPointer<T>::QQmlRefPointer(T *o)
+QQmlRefPointer<T>::QQmlRefPointer(T *o, Mode m)
: o(o)
{
- if (o) o->addref();
+ if (m == AddRef && o)
+ o->addref();
}
template<class T>
@@ -161,21 +165,12 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
return *this;
}
-template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(T *other)
-{
- if (other) other->addref();
- if (o) o->release();
- o = other;
- return *this;
-}
-
/*!
Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
of the callers reference of other.
*/
template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::take(T *other)
+QQmlRefPointer<T> &QQmlRefPointer<T>::adopt(T *other)
{
if (o) o->release();
o = other;
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 4addcd9e58..62f6f76a7e 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -377,4 +377,31 @@ void QQmlThread::internalPostMethodToMain(Message *message)
d->unlock();
}
+void QQmlThread::waitForNextMessage()
+{
+ Q_ASSERT(!isThisThread());
+ d->lock();
+ Q_ASSERT(d->m_mainThreadWaiting == false);
+
+ d->m_mainThreadWaiting = true;
+
+ if (d->mainSync || !d->threadList.isEmpty()) {
+ if (d->mainSync) {
+ QQmlThread::Message *message = d->mainSync;
+ unlock();
+ message->call(this);
+ delete message;
+ lock();
+ d->mainSync = 0;
+ wakeOne();
+ } else {
+ d->wait();
+ }
+ }
+
+ d->m_mainThreadWaiting = false;
+ d->unlock();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 86d7d2cf19..73658536ac 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -108,6 +108,8 @@ public:
template<typename T, typename T2, class V, class V2, class O>
inline void postMethodToMain(void (O::*Member)(V, V2), const T &, const T2 &);
+ void waitForNextMessage();
+
protected:
virtual void startupThread();
virtual void shutdownThread();
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index e733bcec05..4d84cc82ae 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -23,7 +23,6 @@ SOURCES += \
$$PWD/qqmlvaluetype.cpp \
$$PWD/qqmlaccessors.cpp \
$$PWD/qqmlxmlhttprequest.cpp \
- $$PWD/qqmlwatcher.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
$$PWD/qqmlnotifier.cpp \
@@ -35,7 +34,6 @@ SOURCES += \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
$$PWD/qqmllocale.cpp \
- $$PWD/qqmlabstractexpression.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -92,7 +90,6 @@ HEADERS += \
$$PWD/qqmlvaluetype_p.h \
$$PWD/qqmlaccessors_p.h \
$$PWD/qqmlxmlhttprequest_p.h \
- $$PWD/qqmlwatcher_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
$$PWD/qqmlnotifier_p.h \
@@ -107,7 +104,6 @@ HEADERS += \
$$PWD/qqmlscriptstring_p.h \
$$PWD/qqmllocale_p.h \
$$PWD/qqmlcomponentattached_p.h \
- $$PWD/qqmlabstractexpression_p.h \
$$PWD/qqmljavascriptexpression_p.h \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 40c8f451b4..4e0763e95a 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -39,24 +39,19 @@
QT_BEGIN_NAMESPACE
-extern QQmlAbstractBinding::VTable QQmlBinding_vtable;
-extern QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable;
-
-QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = {
- &QQmlBinding_vtable,
- &QQmlValueTypeProxyBinding_vtable
-};
-
-QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt)
- : m_nextBindingPtr(bt)
+QQmlAbstractBinding::QQmlAbstractBinding()
+ : m_targetIndex(-1)
{
+ Q_ASSERT(!isAddedToObject());
}
QQmlAbstractBinding::~QQmlAbstractBinding()
{
- Q_ASSERT(isAddedToObject() == false);
- Q_ASSERT(nextBinding() == 0);
- Q_ASSERT(*m_mePtr == 0);
+ Q_ASSERT(!ref);
+ Q_ASSERT(!isAddedToObject());
+
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
}
/*!
@@ -72,40 +67,45 @@ void QQmlAbstractBinding::addToObject()
Q_ASSERT(!nextBinding());
Q_ASSERT(isAddedToObject() == false);
- QObject *obj = object();
+ QObject *obj = targetObject();
Q_ASSERT(obj);
QQmlData *data = QQmlData::get(obj, true);
int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
// Value type
// Find the value type proxy (if there is one)
QQmlValueTypeProxyBinding *proxy = 0;
if (data->hasBindingBit(coreIndex)) {
QQmlAbstractBinding *b = data->bindings;
- while (b && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
+ Q_ASSERT(b && b->isValueTypeProxy());
proxy = static_cast<QQmlValueTypeProxyBinding *>(b);
}
if (!proxy) {
proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
- Q_ASSERT(proxy->propertyIndex() == coreIndex);
- Q_ASSERT(proxy->object() == obj);
+ Q_ASSERT(proxy->targetPropertyIndex() == coreIndex);
+ Q_ASSERT(proxy->targetObject() == obj);
proxy->addToObject();
}
- setNextBinding(proxy->m_bindings);
+ setNextBinding(proxy->m_bindings.data());
proxy->m_bindings = this;
} else {
setNextBinding(data->bindings);
+ if (data->bindings) {
+ data->bindings->ref.deref();
+ Q_ASSERT(data->bindings->ref.refCount > 0);
+ }
data->bindings = this;
+ ref.ref();
data->setBindingBit(obj, coreIndex);
}
@@ -118,95 +118,81 @@ Remove the binding from the object.
*/
void QQmlAbstractBinding::removeFromObject()
{
- if (isAddedToObject()) {
- QObject *obj = object();
- QQmlData *data = QQmlData::get(obj, false);
- Q_ASSERT(data);
-
- int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
-
- // Find the value type binding
- QQmlAbstractBinding *vtbinding = data->bindings;
- while (vtbinding->propertyIndex() != coreIndex) {
- vtbinding = vtbinding->nextBinding();
- Q_ASSERT(vtbinding);
- }
- Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
-
- QQmlValueTypeProxyBinding *vtproxybinding =
- static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-
- QQmlAbstractBinding *binding = vtproxybinding->m_bindings;
- if (binding == this) {
- vtproxybinding->m_bindings = nextBinding();
- } else {
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- // Value type - we don't remove the proxy from the object. It will sit their happily
- // doing nothing until it is removed by a write, a binding change or it is reused
- // to hold more sub-bindings.
+ if (!isAddedToObject())
+ return;
- } else {
+ setAddedToObject(false);
- if (data->bindings == this) {
- data->bindings = nextBinding();
- } else {
- QQmlAbstractBinding *binding = data->bindings;
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- data->clearBindingBit(coreIndex);
- }
+ QObject *obj = targetObject();
+ QQmlData *data = QQmlData::get(obj, false);
+ Q_ASSERT(data);
- setNextBinding(0);
- setAddedToObject(false);
- }
-}
+ QQmlAbstractBinding::Ptr next;
+ next = nextBinding();
+ setNextBinding(0);
-void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
-{
- qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
-}
+ int coreIndex;
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
+ // Find the value type binding
+ QQmlAbstractBinding *vtbinding = data->bindings;
+ while (vtbinding->targetPropertyIndex() != coreIndex) {
+ vtbinding = vtbinding->nextBinding();
+ Q_ASSERT(vtbinding);
+ }
+ Q_ASSERT(vtbinding->isValueTypeProxy());
-static void bindingDummyDeleter(QQmlAbstractBinding *)
-{
-}
+ QQmlValueTypeProxyBinding *vtproxybinding =
+ static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer()
-{
- if (m_mePtr.value().isNull())
- m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter);
+ QQmlAbstractBinding *binding = vtproxybinding->m_bindings.data();
+ if (binding == this) {
+ vtproxybinding->m_bindings = next;
+ } else {
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
+ }
- return m_mePtr.value().toWeakRef();
-}
+ // Value type - we don't remove the proxy from the object. It will sit their happily
+ // doing nothing until it is removed by a write, a binding change or it is reused
+ // to hold more sub-bindings.
+ return;
+ }
-void QQmlAbstractBinding::clear()
-{
- if (!m_mePtr.isNull()) {
- **m_mePtr = 0;
- m_mePtr = 0;
+ if (data->bindings == this) {
+ if (next.data())
+ next->ref.ref();
+ data->bindings = next.data();
+ if (!ref.deref())
+ delete this;
+ } else {
+ QQmlAbstractBinding *binding = data->bindings;
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
}
+
+ data->clearBindingBit(coreIndex);
}
-void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int)
+void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
{
- qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding.");
+ qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
}
-QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *)
+QString QQmlAbstractBinding::expression() const
{
return QLatin1String("<Unknown>");
}
+bool QQmlAbstractBinding::isValueTypeProxy() const
+{
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index b5d8181ca5..dd14301aa9 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -46,6 +46,7 @@
//
#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <private/qtqmlglobal_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qpointervaluepair_p.h>
@@ -56,162 +57,83 @@ class QQmlObjectCreator;
class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
{
+protected:
+ QQmlAbstractBinding();
public:
- enum DestroyMode {
-
- // The binding should disconnect itself upon destroy
- DisconnectBinding,
-
- // The binding doesn't need to disconnect itself, but it can if it wants to.
- //
- // This is used in QQmlData::destroyed() - at the point at which the bindings are
- // destroyed, the notifiers are already disconnected, so no need to disconnect each
- // binding again.
- //
- // Bindings can use this flag to speed up destruction, especially for v4 bindings
- // disconnecting a single binding might be slow.
- KeepBindingConnected
- };
-
- struct VTable {
- void (*destroy)(QQmlAbstractBinding *, DestroyMode destroyMode);
- QString (*expression)(const QQmlAbstractBinding *);
- int (*propertyIndex)(const QQmlAbstractBinding *);
- QObject *(*object)(const QQmlAbstractBinding *);
- void (*setEnabled)(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- void (*update)(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void (*retargetBinding)(QQmlAbstractBinding *, QObject *, int);
- };
-
- typedef QWeakPointer<QQmlAbstractBinding> Pointer;
+ virtual ~QQmlAbstractBinding();
- enum BindingType { Binding = 0, ValueTypeProxy = 1 };
- inline BindingType bindingType() const;
+ typedef QExplicitlySharedDataPointer<QQmlAbstractBinding> Ptr;
- // Destroy the binding. Use this instead of calling delete.
- // Bindings are free to implement their own memory management, so the delete operator is
- // not necessarily safe. The default implementation clears the binding, removes it from
- // the object and calls delete.
- void destroy(DestroyMode destroyMode = DisconnectBinding)
- { vtable()->destroy(this, destroyMode); }
+ virtual QString expression() const;
- QString expression() const { return vtable()->expression(this); }
+ virtual bool isValueTypeProxy() const;
// Should return the encoded property index for the binding. Should return this value
// even if the binding is not enabled or added to an object.
// Encoding is: coreIndex | (valueTypeIndex << 16)
- int propertyIndex() const { return vtable()->propertyIndex(this); }
+ int targetPropertyIndex() const { return m_targetIndex; }
// Should return the object for the binding. Should return this object even if the
// binding is not enabled or added to the object.
- QObject *object() const { return vtable()->object(this); }
-
- void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); }
- void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f) { vtable()->setEnabled(this, e, f); }
+ QObject *targetObject() const { return m_target.data(); }
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
- void update(QQmlPropertyPrivate::WriteFlags f) { vtable()->update(this, f); }
+ virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();
- static inline Pointer getPointer(QQmlAbstractBinding *p);
static void printBindingLoopError(QQmlProperty &prop);
- // Default implementation for some VTable functions
- template<typename T>
- static void default_destroy(QQmlAbstractBinding *, DestroyMode);
- static QString default_expression(const QQmlAbstractBinding *);
- static void default_retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
-protected:
- QQmlAbstractBinding(BindingType);
- ~QQmlAbstractBinding();
- void clear();
+ inline QQmlAbstractBinding *nextBinding() const;
- // Called by QQmlPropertyPrivate to "move" a binding to a different property.
- // This is only used for alias properties. The default implementation qFatal()'s
- // to ensure that the method is never called for binding types that don't support it.
- void retargetBinding(QObject *o, int i) { vtable()->retargetBinding(this, o, i); }
-private:
- Pointer weakPointer();
+ struct RefCount {
+ RefCount() : refCount(0) {}
+ int refCount;
+ void ref() { ++refCount; }
+ int deref() { return --refCount; }
+ operator int() const { return refCount; }
+ };
+ RefCount ref;
+protected:
friend class QQmlData;
- friend class QQmlComponentPrivate;
friend class QQmlValueTypeProxyBinding;
- friend class QQmlPropertyPrivate;
- friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
- friend class QV4Bindings;
friend class QQmlObjectCreator;
- typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
- // To save memory, we also store the rarely used weakPointer() instance in here
- // We also use the flag bits:
- // m_mePtr.flag1: added to object
- QPointerValuePair<QQmlAbstractBinding*, SharedPointer> m_mePtr;
-
inline void setAddedToObject(bool v);
inline bool isAddedToObject() const;
- inline QQmlAbstractBinding *nextBinding() const;
inline void setNextBinding(QQmlAbstractBinding *);
+ int m_targetIndex;
+ QFlagPointer<QObject> m_target;
// Pointer to the next binding in the linked list of bindings.
- // Being a pointer, the address is always aligned to at least 4 bytes, which means the last two
- // bits of the pointer are free to be used for something else. They are used to store the binding
- // type. The binding type serves as an index into the static vTables array, which is used instead
- // of a compiler-generated vTable. Instead of virtual functions, pointers to static functions in
- // the vTables array are used for dispatching.
- // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces
- // the binding object size by sizeof(void*).
- qintptr m_nextBindingPtr;
-
- static VTable *vTables[];
- inline const VTable *vtable() const { return vTables[bindingType()]; }
+ QFlagPointer<QQmlAbstractBinding> m_nextBinding;
};
-QQmlAbstractBinding::Pointer
-QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p)
-{
- return p ? p->weakPointer() : Pointer();
-}
-
void QQmlAbstractBinding::setAddedToObject(bool v)
{
- m_mePtr.setFlagValue(v);
+ m_nextBinding.setFlagValue(v);
}
bool QQmlAbstractBinding::isAddedToObject() const
{
- return m_mePtr.flag();
+ return m_nextBinding.flag();
}
QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
{
- return (QQmlAbstractBinding *)(m_nextBindingPtr & ~0x3);
+ return m_nextBinding.data();
}
void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b)
{
- m_nextBindingPtr = qintptr(b) | (m_nextBindingPtr & 0x3);
-}
-
-QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const
-{
- return (BindingType)(m_nextBindingPtr & 0x3);
-}
-
-template<typename T>
-void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode)
-{
- // Assume the binding disconnects itself in the destructor, which for example QQmlBinding
- // does in the destructor of its base class, QQmlJavaScriptExpression
- Q_UNUSED(mode);
-
- This->removeFromObject();
- This->clear();
- delete static_cast<T *>(This);
+ if (b)
+ b->ref.ref();
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
+ m_nextBinding = b;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractexpression.cpp b/src/qml/qml/qqmlabstractexpression.cpp
deleted file mode 100644
index c55c86952c..0000000000
--- a/src/qml/qml/qqmlabstractexpression.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlabstractexpression_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlAbstractExpression::QQmlAbstractExpression()
-: m_prevExpression(0), m_nextExpression(0)
-{
-}
-
-QQmlAbstractExpression::~QQmlAbstractExpression()
-{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- }
-
- if (m_context.isT2())
- m_context.asT2()->_s = 0;
-}
-
-QQmlContextData *QQmlAbstractExpression::context() const
-{
- if (m_context.isT1()) return m_context.asT1();
- else return m_context.asT2()->_c;
-}
-
-void QQmlAbstractExpression::setContext(QQmlContextData *context)
-{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- m_prevExpression = 0;
- m_nextExpression = 0;
- }
-
- if (m_context.isT1()) m_context = context;
- else m_context.asT2()->_c = context;
-
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
-}
-
-void QQmlAbstractExpression::refresh()
-{
-}
-
-bool QQmlAbstractExpression::isValid() const
-{
- return context() != 0;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h
deleted file mode 100644
index 82ba010434..0000000000
--- a/src/qml/qml/qqmlabstractexpression_p.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLABSTRACTEXPRESSION_P_H
-#define QQMLABSTRACTEXPRESSION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qqmlcontext_p.h>
-#include <private/qfieldlist_p.h>
-#include <private/qflagpointer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression
-{
-public:
- QQmlAbstractExpression();
- virtual ~QQmlAbstractExpression();
-
- bool isValid() const;
-
- QQmlContextData *context() const;
- void setContext(QQmlContextData *);
-
- virtual void refresh();
-
- class DeleteWatcher {
- public:
- inline DeleteWatcher(QQmlAbstractExpression *);
- inline ~DeleteWatcher();
- inline bool wasDeleted() const;
- private:
- friend class QQmlAbstractExpression;
- QQmlContextData *_c;
- QQmlAbstractExpression **_w;
- QQmlAbstractExpression *_s;
- };
-
-private:
- friend class QQmlContext;
- friend class QQmlContextData;
- friend class QQmlContextPrivate;
-
- QBiPointer<QQmlContextData, DeleteWatcher> m_context;
- QQmlAbstractExpression **m_prevExpression;
- QQmlAbstractExpression *m_nextExpression;
-};
-
-QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e)
-: _c(0), _w(0), _s(e)
-{
- if (e->m_context.isT1()) {
- _w = &_s;
- _c = e->m_context.asT1();
- e->m_context = this;
- } else {
- // Another watcher is already registered
- _w = &e->m_context.asT2()->_s;
- }
-}
-
-QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher()
-{
- Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2()));
- if (*_w && _s->m_context.asT2() == this)
- _s->m_context = _c;
-}
-
-bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const
-{
- return *_w == 0;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLABSTRACTEXPRESSION_P_H
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index f223d099e4..3613c17242 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -43,43 +43,28 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlBinding>,
- QQmlBinding::expression,
- QQmlBinding::propertyIndex,
- QQmlBinding::object,
- QQmlBinding::setEnabled,
- QQmlBinding::update,
- QQmlBinding::retargetBinding
-};
-
-QQmlBinding::Identifier QQmlBinding::Invalid = -1;
-
-static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = {
- QQmlBinding::expressionIdentifier,
- QQmlBinding::expressionChanged
-};
-
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(context(), obj, str, QString(), 0));
+ createQmlBinding(context(), obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
if (ctxt && !ctxt->isValid())
return;
@@ -100,51 +85,52 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
}
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
setScopeObject(obj ? obj : scriptPrivate->scope);
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
if (runtimeFunction) {
- v4function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
+ m_function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
- v4function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber));
+ createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
}
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0));
+ createQmlBinding(ctxt, obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
QQmlContextData *ctxt,
const QString &url, quint16 lineNumber, quint16 columnNumber)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
Q_UNUSED(columnNumber);
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber));
+ createQmlBinding(ctxt, obj, str, url, lineNumber);
}
QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- v4function.set(functionPtr.asObject()->engine(), functionPtr);
+ m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr);
}
QQmlBinding::~QQmlBinding()
@@ -162,90 +148,243 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
return;
// Check that the target has not been deleted
- if (QQmlData::wasDeleted(object()))
+ if (QQmlData::wasDeleted(targetObject()))
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedFunctionObject f(scope, v4function.value());
+ QV4::ScopedFunctionObject f(scope, m_function.value());
Q_ASSERT(f);
- if (!updatingFlag()) {
- QQmlBindingProfiler prof(ep->profiler, f);
- setUpdatingFlag(true);
+ if (updatingFlag()) {
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ QQmlAbstractBinding::printBindingLoopError(p);
+ return;
+ }
+
+ QQmlBindingProfiler prof(ep->profiler, f);
+ setUpdatingFlag(true);
- QQmlAbstractExpression::DeleteWatcher watcher(this);
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
- if (m_core.propType == qMetaTypeId<QQmlBinding *>()) {
+ QQmlPropertyData pd = getPropertyData();
- int idx = m_core.coreIndex;
- Q_ASSERT(idx != -1);
+ if (pd.propType == qMetaTypeId<QQmlBinding *>()) {
- QQmlBinding *t = this;
- int status = -1;
- void *a[] = { &t, 0, &status, &flags };
- QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a);
+ int idx = pd.coreIndex;
+ Q_ASSERT(idx != -1);
- } else {
- ep->referenceScarceResources();
+ QQmlBinding *t = this;
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(*m_target, QMetaObject::WriteProperty, idx, a);
- bool isUndefined = false;
+ } else {
+ ep->referenceScarceResources();
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ bool isUndefined = false;
- bool needsErrorLocationData = false;
- if (!watcher.wasDeleted() && !hasError())
- needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(),
- this, result, isUndefined, flags);
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
- if (!watcher.wasDeleted()) {
+ bool error = false;
+ if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
+ error = !write(pd, result, isUndefined, flags);
- if (needsErrorLocationData)
- delayedError()->setErrorLocation(f->sourceLocation());
+ if (!watcher.wasDeleted()) {
- if (hasError()) {
- if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
- } else {
- clearError();
- }
+ if (error) {
+ delayedError()->setErrorLocation(f->sourceLocation());
+ delayedError()->setErrorObject(m_target.data());
+ }
+ if (hasError()) {
+ if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
+ } else {
+ clearError();
}
- ep->dereferenceScarceResources();
}
- if (!watcher.wasDeleted())
- setUpdatingFlag(false);
- } else {
- QQmlProperty p = property();
- QQmlAbstractBinding::printBindingLoopError(p);
+ ep->dereferenceScarceResources();
}
+
+ if (!watcher.wasDeleted())
+ setUpdatingFlag(false);
+}
+
+// Returns true if successful, false if an error description was set on expression
+bool QQmlBinding::write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags)
+{
+ Q_ASSERT(m_target.data());
+ Q_ASSERT(core.coreIndex != -1);
+
+ QQmlEngine *engine = context()->engine;
+ QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
+
+#define QUICK_STORE(cpptype, conversion) \
+ { \
+ cpptype o = (conversion); \
+ int status = -1; \
+ void *argv[] = { &o, 0, &status, &flags }; \
+ QMetaObject::metacall(m_target.data(), QMetaObject::WriteProperty, core.coreIndex, argv); \
+ return true; \
+ } \
+
+
+ if (!isUndefined && !core.isValueTypeVirtual()) {
+ switch (core.propType) {
+ case QMetaType::Int:
+ if (result.isInteger())
+ QUICK_STORE(int, result.integerValue())
+ else if (result.isNumber())
+ QUICK_STORE(int, result.doubleValue())
+ break;
+ case QMetaType::Double:
+ if (result.isNumber())
+ QUICK_STORE(double, result.asDouble())
+ break;
+ case QMetaType::Float:
+ if (result.isNumber())
+ QUICK_STORE(float, result.asDouble())
+ break;
+ case QMetaType::QString:
+ if (result.isString())
+ QUICK_STORE(QString, result.toQStringNoThrow())
+ break;
+ default:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == core.propType) {
+ return vtw->write(m_target.data(), core.coreIndex);
+ }
+ }
+ break;
+ }
+ }
+#undef QUICK_STORE
+
+ int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
+
+ QVariant value;
+ bool isVarProperty = core.isVarProperty();
+
+ if (isUndefined) {
+ } else if (core.isQList()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
+ } else if (result.isNull() && core.isQObject()) {
+ value = QVariant::fromValue((QObject *)0);
+ } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
+ value = QQmlPropertyPrivate::resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context());
+ } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, type);
+ }
+
+ if (hasError()) {
+ return false;
+ } else if (isVarProperty) {
+ const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
+ if (f && f->isBinding()) {
+ // we explicitly disallow this case to avoid confusion. Users can still store one
+ // in an array in a var property if they need to, but the common case is user error.
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_target.data());
+ Q_ASSERT(vmemo);
+ vmemo->setVMEProperty(core.coreIndex, result);
+ } else if (isUndefined && core.isResettable()) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
+ } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
+ if (f && f->isBinding()) {
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
+ context(), flags);
+ } else if (isUndefined) {
+ QString errorStr = QLatin1String("Unable to assign [undefined] to ");
+ if (!QMetaType::typeName(type))
+ errorStr += QLatin1String("[unknown property type]");
+ else
+ errorStr += QLatin1String(QMetaType::typeName(type));
+ delayedError()->setErrorDescription(errorStr);
+ return false;
+ } else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) {
+ if (f->isBinding())
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ else
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
+ return false;
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+
+ if (watcher.wasDeleted())
+ return true;
+
+ const char *valueType = 0;
+ const char *propertyType = 0;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ if (QObject *o = *(QObject *const *)value.constData()) {
+ valueType = o->metaObject()->className();
+
+ QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ if (!propertyMetaObject.isNull())
+ propertyType = propertyMetaObject.className();
+ }
+ } else if (value.userType() != QVariant::Invalid) {
+ if (value.userType() == QMetaType::VoidStar)
+ valueType = "null";
+ else
+ valueType = QMetaType::typeName(value.userType());
+ }
+
+ if (!valueType)
+ valueType = "undefined";
+ if (!propertyType)
+ propertyType = QMetaType::typeName(type);
+ if (!propertyType)
+ propertyType = "[unknown property type]";
+
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(propertyType));
+ return false;
+ }
+
+ return true;
}
QVariant QQmlBinding::evaluate()
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::ScopedValue f(scope, v4function.value());
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ QV4::Scope scope(ep->v4engine());
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
ep->dereferenceScarceResources();
return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
-QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBinding::expressionIdentifier()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(This->context()->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedValue f(scope, This->v4function.value());
- QV4::Function *function = f->asFunctionObject()->function();
+ QV4::ScopedValue f(scope, m_function.value());
+ QV4::Function *function = f->as<QV4::FunctionObject>()->function();
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
@@ -254,10 +393,9 @@ QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber);
}
-void QQmlBinding::expressionChanged(QQmlJavaScriptExpression *e)
+void QQmlBinding::expressionChanged()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
- This->update();
+ update();
}
void QQmlBinding::refresh()
@@ -265,36 +403,6 @@ void QQmlBinding::refresh()
update();
}
-QString QQmlBinding::expression(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->expression();
-}
-
-int QQmlBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->propertyIndex();
-}
-
-QObject *QQmlBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->object();
-}
-
-void QQmlBinding::setEnabled(QQmlAbstractBinding *This, bool e, QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->setEnabled(e, f);
-}
-
-void QQmlBinding::update(QQmlAbstractBinding *This , QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->update(f);
-}
-
-void QQmlBinding::retargetBinding(QQmlAbstractBinding *This, QObject *o, int i)
-{
- static_cast<QQmlBinding *>(This)->retargetBinding(o, i);
-}
-
void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
setEnabledFlag(e);
@@ -307,44 +415,92 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
QString QQmlBinding::expression() const
{
QV4::Scope scope(QQmlEnginePrivate::get(context()->engine)->v4engine());
- QV4::ScopedValue v(scope, v4function.value());
+ QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
}
-QObject *QQmlBinding::object() const
+void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->target;
- else return *m_coreObject;
+ setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
}
-int QQmlBinding::propertyIndex() const
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->targetProperty;
- else return m_core.encodedIndex();
-}
+ m_target = object;
-void QQmlBinding::retargetBinding(QObject *t, int i)
-{
- m_coreObject.value().target = t;
- m_coreObject.value().targetProperty = i;
-}
+ if (!object) {
+ m_targetIndex = -1;
+ return;
+ }
-void QQmlBinding::setTarget(const QQmlProperty &prop)
-{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core,
- QQmlPropertyPrivate::get(prop)->context);
-}
+ QQmlPropertyData pd = core;
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, QQmlContextData *ctxt)
-{
- m_coreObject = object;
- m_core = core;
- m_ctxt = ctxt;
+ while (pd.isAlias()) {
+ int coreIndex = pd.coreIndex;
+ int valueTypeIndex = pd.getValueTypeCoreIndex();
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+
+ int aValueTypeIndex;
+ if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ if (valueTypeIndex == -1)
+ valueTypeIndex = aValueTypeIndex;
+
+ QQmlData *data = QQmlData::get(object, false);
+ if (!data || !data->propertyCache) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ m_target = object;
+ pd = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ pd.setFlags(pd.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ pd.valueTypePropType = vtProp.userType();
+ pd.valueTypeCoreIndex = valueTypeIndex;
+ }
+ }
+ m_targetIndex = pd.encodedIndex();
+
+ QQmlData *data = QQmlData::get(*m_target, true);
+ if (!data->propertyCache) {
+ data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache->addref();
+ }
}
-QQmlProperty QQmlBinding::property() const
+QQmlPropertyData QQmlBinding::getPropertyData() const
{
- return QQmlPropertyPrivate::restore(object(), m_core, *m_ctxt);
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex);
+
+ QQmlData *data = QQmlData::get(*m_target, false);
+ Q_ASSERT(data && data->propertyCache);
+
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ QQmlPropertyData d = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ d.setFlags(d.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ d.valueTypePropType = vtProp.userType();
+ d.valueTypeCoreIndex = valueTypeIndex;
+ }
+ return d;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 1e440b2e86..a435847819 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -57,16 +57,15 @@
#include <private/qpointervaluepair_p.h>
#include <private/qqmlabstractbinding_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
class QQmlContext;
class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression,
- public QQmlAbstractExpression,
public QQmlAbstractBinding
{
+ friend class QQmlAbstractBinding;
public:
QQmlBinding(const QString &, QObject *, QQmlContext *);
QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *);
@@ -74,84 +73,62 @@ public:
QQmlBinding(const QString &, QObject *, QQmlContextData *,
const QString &url, quint16 lineNumber, quint16 columnNumber);
QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *);
+ ~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *);
- QQmlProperty property() const;
+ void setTarget(QObject *, const QQmlPropertyData &);
void setNotifyOnValueChanged(bool);
- // Inherited from QQmlAbstractExpression
+ // Inherited from QQmlJavaScriptExpression
virtual void refresh();
- // "Inherited" from QQmlAbstractBinding
- static QString expression(const QQmlAbstractBinding *);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static void retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
- void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
- void update(QQmlPropertyPrivate::WriteFlags flags);
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
-
- QString expression() const;
- QObject *object() const;
- int propertyIndex() const;
- void retargetBinding(QObject *, int);
+ // Inherited from QQmlAbstractBinding
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
+ virtual QString expression() const;
+ void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
typedef int Identifier;
- static Identifier Invalid;
+ enum {
+ Invalid = -1
+ };
QVariant evaluate();
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
-
-protected:
- friend class QQmlAbstractBinding;
- ~QQmlBinding();
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
private:
- QV4::PersistentValue v4function;
-
inline bool updatingFlag() const;
inline void setUpdatingFlag(bool);
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
+ QQmlPropertyData getPropertyData() const;
- struct Retarget {
- QObject *target;
- int targetProperty;
- };
+ bool write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags);
- QPointerValuePair<QObject, Retarget> m_coreObject;
- QQmlPropertyData m_core;
- // We store some flag bits in the following flag pointers.
- // m_ctxt:flag1 - updatingFlag
- // m_ctxt:flag2 - enabledFlag
- QFlagPointer<QQmlContextData> m_ctxt;
};
bool QQmlBinding::updatingFlag() const
{
- return m_ctxt.flag();
+ return m_target.flag();
}
void QQmlBinding::setUpdatingFlag(bool v)
{
- m_ctxt.setFlagValue(v);
+ m_target.setFlagValue(v);
}
bool QQmlBinding::enabledFlag() const
{
- return m_ctxt.flag2();
+ return m_target.flag2();
}
void QQmlBinding::setEnabledFlag(bool v)
{
- m_ctxt.setFlag2Value(v);
+ m_target.setFlag2Value(v);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 766e657c59..3d1a9f8a88 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -43,11 +43,12 @@
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
#include <private/qqmlprofiler_p.h>
-#include <private/qv4debugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlcompiler_p.h>
#include "qqmlinfo.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qdebug.h>
@@ -55,59 +56,68 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = {
- QQmlBoundSignalExpression::expressionIdentifier,
- QQmlBoundSignalExpression::expressionChanged
-};
-
-QQmlBoundSignalExpression::ExtraData::ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column)
- : m_handlerName(handlerName),
- m_parameterString(parameterString),
- m_expression(expression),
- m_sourceLocation(fileName, line, column)
-{
-}
-
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, const QString &expression,
const QString &fileName, quint16 line, quint16 column,
const QString &handlerName,
const QString &parameterString)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(new ExtraData(handlerName, parameterString, expression, fileName, line, column))
+ m_target(target)
{
- setExpressionFunctionValid(false);
- setInvalidParameterName(false);
-
init(ctxt, scope);
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
+ QV4::ExecutionEngine *v4 = ep->v4engine();
+
+ QString function;
+
+ // Add some leading whitespace to account for the binding's column offset.
+ // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
+ function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
+ function += QStringLiteral("(function ");
+ function += handlerName;
+ function += QLatin1Char('(');
+
+ if (parameterString.isEmpty()) {
+ QString error;
+ //TODO: look at using the property cache here (as in the compiler)
+ // for further optimization
+ QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
+ function += QQmlPropertyCache::signalParameterStringForJS(v4, signal.parameterNames(), &error);
+
+ if (!error.isEmpty()) {
+ qmlInfo(scopeObject()) << error;
+ return;
+ }
+ } else
+ function += parameterString;
+
+ function += QStringLiteral(") { ");
+ function += expression;
+ function += QStringLiteral(" })");
+
+ m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
+
+ if (m_function.isNullOrUndefined())
+ return; // could not evaluate function. Not valid.
+
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::Value &function)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_function(function.asObject()->engine(), function),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
+ m_function.set(function.as<QV4::Object>()->engine(), function);
init(ctxt, scope);
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
// It's important to call init first, because m_index gets remapped in case of cloned signals.
init(ctxt, scope);
@@ -117,9 +127,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- } else
- setInvalidParameterName(false);
+ m_function.clear();
+ }
}
void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
@@ -134,34 +143,30 @@ void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
{
- delete m_extra.data();
}
-QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBoundSignalExpression::expressionIdentifier()
{
- QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e);
- QQmlSourceLocation loc = This->sourceLocation();
+ QQmlSourceLocation loc = sourceLocation();
return loc.sourceFile + QLatin1Char(':') + QString::number(loc.line);
}
-void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *)
+void QQmlBoundSignalExpression::expressionChanged()
{
// bound signals do not notify on change.
}
QQmlSourceLocation QQmlBoundSignalExpression::sourceLocation() const
{
- if (expressionFunctionValid()) {
- QV4::Function *f = function();
- Q_ASSERT(f);
+ QV4::Function *f = function();
+ if (f) {
QQmlSourceLocation loc;
loc.sourceFile = f->sourceFile();
loc.line = f->compiledFunction->location.line;
loc.column = f->compiledFunction->location.column;
return loc;
}
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_sourceLocation;
+ return QQmlSourceLocation();
}
QString QQmlBoundSignalExpression::expression() const
@@ -171,10 +176,8 @@ QString QQmlBoundSignalExpression::expression() const
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
- } else {
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_expression;
}
+ return QString();
}
QV4::Function *QQmlBoundSignalExpression::function() const
@@ -194,108 +197,79 @@ void QQmlBoundSignalExpression::evaluate(void **a)
{
Q_ASSERT (context() && engine());
- if (invalidParameterName())
+ if (!expressionFunctionValid())
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- {
- if (!expressionFunctionValid()) {
- Q_ASSERT(!m_extra.isNull());
- QString expression;
-
- // Add some leading whitespace to account for the binding's column offset.
- // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
- expression.fill(QChar(QChar::Space), qMax(m_extra->m_sourceLocation.column, (quint16)2) - 2);
- expression += QStringLiteral("(function ");
- expression += m_extra->m_handlerName;
- expression += QLatin1Char('(');
-
- if (m_extra->m_parameterString.isEmpty()) {
- QString error;
- //TODO: look at using the property cache here (as in the compiler)
- // for further optimization
- QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
- expression += QQmlPropertyCache::signalParameterStringForJS(scope.engine, signal.parameterNames(), &error);
-
- if (!error.isEmpty()) {
- qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- ep->dereferenceScarceResources();
- return;
- }
- } else
- expression += m_extra->m_parameterString;
-
- expression += QStringLiteral(") { ");
- expression += m_extra->m_expression;
- expression += QStringLiteral(" })");
-
- m_extra->m_expression.clear();
- m_extra->m_handlerName.clear();
- m_extra->m_parameterString.clear();
-
- m_function.set(scope.engine, evalFunction(context(), scopeObject(), expression,
- m_extra->m_sourceLocation.sourceFile, m_extra->m_sourceLocation.line, &m_extra->m_v8qmlscope));
-
- if (m_function.isNullOrUndefined()) {
- ep->dereferenceScarceResources();
- return; // could not evaluate function. Not valid.
- }
-
- setExpressionFunctionValid(true);
- }
- QVarLengthArray<int, 9> dummy;
- //TODO: lookup via signal index rather than method index as an optimization
- int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
- int argCount = argsTypes ? *argsTypes : 0;
-
- QV4::ScopedValue f(scope, m_function.value());
- QV4::ScopedCallData callData(scope, argCount);
- for (int ii = 0; ii < argCount; ++ii) {
- int type = argsTypes[ii + 1];
- //### ideally we would use metaTypeToJS, however it currently gives different results
- // for several cases (such as QVariant type and QObject-derived types)
- //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
- if (type == QMetaType::QVariant) {
- callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
- } else if (type == QMetaType::Int) {
- //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
- callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
- } else if (ep->isQObject(type)) {
- if (!*reinterpret_cast<void* const *>(a[ii + 1]))
- callData->args[ii] = QV4::Primitive::nullValue();
- else
- callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
- } else {
- callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
- }
+ QVarLengthArray<int, 9> dummy;
+ //TODO: lookup via signal index rather than method index as an optimization
+ int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
+ int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
+ int argCount = argsTypes ? *argsTypes : 0;
+
+ QV4::ScopedCallData callData(scope, argCount);
+ for (int ii = 0; ii < argCount; ++ii) {
+ int type = argsTypes[ii + 1];
+ //### ideally we would use metaTypeToJS, however it currently gives different results
+ // for several cases (such as QVariant type and QObject-derived types)
+ //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
+ if (type == QMetaType::QVariant) {
+ callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
+ } else if (type == QMetaType::Int) {
+ //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
+ callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
+ } else if (type == qMetaTypeId<QQmlV4Handle>()) {
+ callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
+ } else if (ep->isQObject(type)) {
+ if (!*reinterpret_cast<void* const *>(a[ii + 1]))
+ callData->args[ii] = QV4::Primitive::nullValue();
+ else
+ callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
+ } else {
+ callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
}
-
- QQmlJavaScriptExpression::evaluate(context(), f, callData, 0);
}
+
+ QQmlJavaScriptExpression::evaluate(callData, 0);
+
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
////////////////////////////////////////////////////////////////////////
-QQmlAbstractBoundSignal::QQmlAbstractBoundSignal()
-: m_prevSignal(0), m_nextSignal(0)
+
+/*! \internal
+ \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
+ This is different from QMetaMethod::methodIndex().
+*/
+QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
+ QQmlEngine *engine)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
+ m_prevSignal(0), m_nextSignal(0),
+ m_expression(0)
{
+ addToObject(owner);
+
+ /*
+ If this is a cloned method, connect to the 'original'. For example,
+ for the signal 'void aSignal(int parameter = 0)', if the method
+ index refers to 'aSignal()', get the index of 'aSignal(int)'.
+ This ensures that 'parameter' will be available from QML.
+ */
+ signal = QQmlPropertyCache::originalClone(target, signal);
+ QQmlNotifierEndpoint::connect(target, signal, engine);
}
-QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
+QQmlBoundSignal::~QQmlBoundSignal()
{
removeFromObject();
}
-void QQmlAbstractBoundSignal::addToObject(QObject *obj)
+void QQmlBoundSignal::addToObject(QObject *obj)
{
Q_ASSERT(!m_prevSignal);
Q_ASSERT(obj);
@@ -308,7 +282,7 @@ void QQmlAbstractBoundSignal::addToObject(QObject *obj)
data->signalHandlers = this;
}
-void QQmlAbstractBoundSignal::removeFromObject()
+void QQmlBoundSignal::removeFromObject()
{
if (m_prevSignal) {
*m_prevSignal = m_nextSignal;
@@ -318,40 +292,6 @@ void QQmlAbstractBoundSignal::removeFromObject()
}
}
-/*! \internal
- \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
- This is different from QMetaMethod::methodIndex().
-*/
-QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
- QQmlEngine *engine)
-: m_expression(0), m_index(signal), m_isEvaluating(false)
-{
- addToObject(owner);
- setCallback(QQmlNotifierEndpoint::QQmlBoundSignal);
-
- /*
- If this is a cloned method, connect to the 'original'. For example,
- for the signal 'void aSignal(int parameter = 0)', if the method
- index refers to 'aSignal()', get the index of 'aSignal(int)'.
- This ensures that 'parameter' will be available from QML.
- */
- m_index = QQmlPropertyCache::originalClone(target, m_index);
- QQmlNotifierEndpoint::connect(target, m_index, engine);
-}
-
-QQmlBoundSignal::~QQmlBoundSignal()
-{
- m_expression = 0;
-}
-
-/*!
- Returns the signal index in the range returned by QObjectPrivate::signalIndex().
- This is different from QMetaMethod::methodIndex().
-*/
-int QQmlBoundSignal::index() const
-{
- return m_index;
-}
/*!
Returns the signal expression.
@@ -362,45 +302,29 @@ QQmlBoundSignalExpression *QQmlBoundSignal::expression() const
}
/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
+ Sets the signal expression to \a e.
- The QQmlBoundSignal instance adds a reference to \a e. The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
+ The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference).
*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e)
+void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
{
- QQmlBoundSignalExpressionPointer rv = m_expression;
- m_expression = e;
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
-}
-
-/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
-
- The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference). The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
-*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
-{
- QQmlBoundSignalExpressionPointer rv = m_expression;
m_expression.take(e);
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
+ if (m_expression)
+ m_expression->setNotifyOnValueChanged(false);
}
void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
{
QQmlBoundSignal *s = static_cast<QQmlBoundSignal*>(e);
+
if (!s->m_expression)
return;
- if (QQmlDebugService::isDebuggingEnabled())
- QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature()));
-
- s->m_isEvaluating = true;
+ QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
+ if (service)
+ service->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(
+ s->m_expression->target()->metaObject(),
+ s->signalIndex()).methodSignature()));
QQmlEngine *engine;
if (s->m_expression && (engine = s->m_expression->engine())) {
@@ -410,8 +334,6 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));
}
}
-
- s->m_isEvaluating = false;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 8d677ea039..3742317484 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -47,7 +47,6 @@
#include <QtCore/qmetaobject.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
#include <private/qqmlnotifier_p.h>
@@ -58,7 +57,7 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression, public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount
{
public:
QQmlBoundSignalExpression(QObject *target, int index,
@@ -73,9 +72,9 @@ public:
QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction);
- // "inherited" from QQmlJavaScriptExpression.
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // inherited from QQmlJavaScriptExpression.
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
// evaluation of a bound signal expression doesn't return any value
void evaluate(void **a);
@@ -92,80 +91,35 @@ private:
void init(QQmlContextData *ctxt, QObject *scope);
- bool expressionFunctionValid() const { return m_extra.flag(); }
- void setExpressionFunctionValid(bool v) { m_extra.setFlagValue(v); }
-
- bool invalidParameterName() const { return m_extra.flag2(); }
- void setInvalidParameterName(bool v) { m_extra.setFlag2Value(v); }
+ bool expressionFunctionValid() const { return !m_function.isNullOrUndefined(); }
int m_index;
- QV4::PersistentValue m_function;
-
QObject *m_target;
-
- // only needed when !expressionFunctionValid()
- struct ExtraData {
- ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column);
- QString m_handlerName;
- QString m_parameterString;
- QString m_expression;
- QQmlSourceLocation m_sourceLocation;
- QV4::PersistentValue m_v8qmlscope;
- };
-
- // We store some flag bits in the following flag pointers.
- // flag - expressionFunctionValid
- // flag2 - invalidParameterName
- QFlagPointer<ExtraData> m_extra;
};
-class Q_QML_PRIVATE_EXPORT QQmlAbstractBoundSignal
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlNotifierEndpoint
{
public:
- QQmlAbstractBoundSignal();
- virtual ~QQmlAbstractBoundSignal();
-
- virtual int index() const = 0;
- virtual QQmlBoundSignalExpression *expression() const = 0;
- virtual QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *) = 0;
- virtual QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *) = 0;
- virtual bool isEvaluating() const = 0;
+ QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
+ ~QQmlBoundSignal();
void removeFromObject();
-protected:
- void addToObject(QObject *owner);
+
+ QQmlBoundSignalExpression *expression() const;
+ void takeExpression(QQmlBoundSignalExpression *);
private:
- friend class QQmlData;
+ friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlPropertyPrivate;
+ friend class QQmlData;
friend class QQmlEngineDebugService;
- QQmlAbstractBoundSignal **m_prevSignal;
- QQmlAbstractBoundSignal *m_nextSignal;
-};
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal,
- public QQmlNotifierEndpoint
-{
-public:
- QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
- virtual ~QQmlBoundSignal();
-
- int index() const;
-
- QQmlBoundSignalExpression *expression() const;
- QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *);
- QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *);
+ void addToObject(QObject *owner);
- bool isEvaluating() const { return m_isEvaluating; }
-
-private:
- friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
+ QQmlBoundSignal **m_prevSignal;
+ QQmlBoundSignal *m_nextSignal;
QQmlBoundSignalExpressionPointer m_expression;
- int m_index;
- bool m_isEvaluating;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9210610cec..d62aada9c6 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -43,7 +43,8 @@
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
#include "qqmlglobal_p.h"
-#include <private/qqmlenginedebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
@@ -53,6 +54,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4objectiterator_p.h>
#include <QStack>
#include <QStringList>
@@ -61,23 +63,6 @@
#include <qqmlinfo.h>
#include "qqmlmemoryprofiler_p.h"
-#define INITIALPROPERTIES_SOURCE \
- "(function(object, values) {"\
- "try {"\
- "for (var property in values) {" \
- "try {"\
- "var properties = property.split(\".\");"\
- "var o = object;"\
- "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
- "o = o[properties[ii]];"\
- "}"\
- "o[properties[properties.length - 1]] = values[property];"\
- "} catch(e) {}"\
- "}"\
- "} catch(e) {}"\
- "})"
-
-
namespace {
QThreadStorage<int> creationDepth;
}
@@ -98,7 +83,6 @@ V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
\class QQmlComponent
\since 5.0
\inmodule QtQml
- \mainclass
\brief The QQmlComponent class encapsulates a QML component definition
@@ -896,10 +880,11 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- if (enginePriv->isDebugging && rv) {
+ QQmlEngineDebugService *service = QQmlDebugConnector::service<QQmlEngineDebugService>();
+ if (service && rv) {
if (!context->isInternal)
context->asQQmlContextPrivate()->instances.append(rv);
- QQmlEngineDebugService::instance()->objectCreated(engine, rv);
+ service->objectCreated(engine, rv);
}
return rv;
@@ -1194,6 +1179,46 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
\sa incubateObject()
*/
+
+static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v)
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedObject object(scope);
+ QV4::ScopedObject valueMap(scope, v);
+ QV4::ObjectIterator it(scope, valueMap, QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain);
+ QV4::ScopedString name(scope);
+ QV4::ScopedValue val(scope);
+ if (engine->hasException)
+ return;
+
+ while (1) {
+ name = it.nextPropertyNameAsString(val);
+ if (!name)
+ break;
+ object = o;
+ const QStringList properties = name->toQString().split(QLatin1Char('.'));
+ for (int i = 0; i < properties.length() - 1; ++i) {
+ name = engine->newString(properties.at(i));
+ object = object->get(name);
+ if (engine->hasException || !object) {
+ break;
+ }
+ }
+ if (engine->hasException || !object) {
+ engine->hasException = false;
+ continue;
+ }
+ name = engine->newString(properties.last());
+ object->put(name, val);
+ if (engine->hasException) {
+ engine->hasException = false;
+ continue;
+ }
+ }
+
+ engine->hasException = false;
+}
+
/*!
\internal
*/
@@ -1216,7 +1241,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
- if (!v->asObject() || v->asArrayObject()) {
+ if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1239,16 +1264,8 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
Q_ASSERT(object->isObject());
- if (!valuemap->isUndefined()) {
- QV4::ScopedObject qmlglobal(scope, args->qmlGlobal());
- QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal));
- Q_ASSERT(f->asFunctionObject());
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = object;
- callData->args[1] = valuemap;
- f->asFunctionObject()->call(callData);
- }
+ if (!valuemap->isUndefined())
+ setInitialProperties(v4, object, valuemap);
d->completeCreate();
@@ -1256,10 +1273,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QQmlData::get(rv)->explicitIndestructibleSet = false;
QQmlData::get(rv)->indestructible = false;
- if (!rv)
- args->setReturnValue(QV4::Encode::null());
- else
- args->setReturnValue(object->asReturnedValue());
+ args->setReturnValue(object->asReturnedValue());
}
/*!
@@ -1342,7 +1356,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
if (v->isNull()) {
- } else if (!v->asObject() || v->asArrayObject()) {
+ } else if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1383,25 +1397,17 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate)
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4engine);
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
- Q_ASSERT(object->asObject());
-
- if (!valuemap.isUndefined()) {
- QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal);
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine,
- QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj));
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4engine->globalObject();
- callData->args[0] = object;
- callData->args[1] = valuemap;
- f->call(callData);
- }
+ Q_ASSERT(object->as<QV4::Object>());
+
+ if (!valuemap.isUndefined())
+ setInitialProperties(v4engine, object, valuemap);
}
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
@@ -1491,13 +1497,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
if (!d()->valuemap.isUndefined()) {
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
-
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
- callData->args[1] = d()->valuemap;
- f->call(callData);
+ QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
+ setInitialProperties(v4, obj, d()->valuemap);
}
}
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index 8c866c585a..121c83db5c 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -63,8 +63,8 @@ class Q_QML_EXPORT QQmlComponent : public QObject
Q_PROPERTY(QUrl url READ url CONSTANT)
public:
- Q_ENUMS(CompilationMode)
enum CompilationMode { PreferSynchronous, Asynchronous };
+ Q_ENUM(CompilationMode)
QQmlComponent(QObject *parent = 0);
QQmlComponent(QQmlEngine *, QObject *parent=0);
@@ -74,8 +74,8 @@ public:
QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = 0);
virtual ~QQmlComponent();
- Q_ENUMS(Status)
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
bool isNull() const;
@@ -125,7 +125,6 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlComponent::Status)
QML_DECLARE_TYPE(QQmlComponent)
QML_DECLARE_TYPEINFO(QQmlComponent, QML_HAS_ATTACHED_PROPERTIES)
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index adc6e173d2..15ec88dd52 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -82,7 +82,7 @@ public:
QObject *beginCreate(QQmlContextData *);
void completeCreate();
- void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate);
+ void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate);
QQmlTypeData *typeData;
virtual void typeDataReady(QQmlTypeData *);
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index fb51bad3a7..b056731e96 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -57,7 +57,6 @@ QQmlContextPrivate::QQmlContextPrivate()
/*!
\class QQmlContext
\brief The QQmlContext class defines a context within a QML engine.
- \mainclass
\inmodule QtQml
Contexts allow data to be exposed to the QML components instantiated by the
@@ -585,9 +584,9 @@ void QQmlContextData::clearContext()
{
emitDestruction();
- QQmlAbstractExpression *expression = expressions;
+ QQmlJavaScriptExpression *expression = expressions;
while (expression) {
- QQmlAbstractExpression *nextExpression = expression->m_nextExpression;
+ QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
expression->m_prevExpression = 0;
expression->m_nextExpression = 0;
@@ -652,9 +651,9 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership)
}
}
-void QQmlContextData::refreshExpressionsRecursive(QQmlAbstractExpression *expression)
+void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
{
- QQmlAbstractExpression::DeleteWatcher w(expression);
+ QQmlJavaScriptExpression::DeleteWatcher w(expression);
if (expression->m_nextExpression)
refreshExpressionsRecursive(expression->m_nextExpression);
@@ -808,7 +807,7 @@ QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
{
if (propertyNameCache.isEmpty()) {
propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QHash<int, int>::ConstIterator it = objectIndexToId.begin(), end = objectIndexToId.end();
+ for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend();
it != end; ++it) {
const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index c714846147..e69a2f8f69 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -72,6 +72,7 @@ public:
void setContextProperty(const QString &, QObject *);
void setContextProperty(const QString &, const QVariant &);
+ // ### Qt 6: no need for a mutable object, this should become a const QObject pointer
QString nameForObject(QObject *) const;
QUrl resolvedUrl(const QUrl &);
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f5fd7d0a5c..95254d4baa 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -69,7 +69,7 @@ class QQmlExpression;
class QQmlEngine;
class QQmlExpression;
class QQmlExpressionPrivate;
-class QQmlAbstractExpression;
+class QQmlJavaScriptExpression;
class QQmlContextData;
class QQmlContextPrivate : public QObjectPrivate
@@ -171,7 +171,7 @@ public:
QQmlContextData **prevChild;
// Expressions that use this context
- QQmlAbstractExpression *expressions;
+ QQmlJavaScriptExpression *expressions;
// Doubly-linked list of objects that are owned by this context
QQmlData *contextObjects;
@@ -212,7 +212,7 @@ public:
private:
void refreshExpressionsRecursive(bool isGlobal);
- void refreshExpressionsRecursive(QQmlAbstractExpression *);
+ void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
~QQmlContextData() {}
};
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 5844eab54f..23084fb202 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -38,13 +38,14 @@
#include <private/qqmlcontext_p.h>
#include <private/qv4engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4function_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qjsvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +61,6 @@ Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlCon
, isNullWrapper(false)
, context(context)
, scopeObject(scopeObject)
- , idObjectsWrapper(Q_NULLPTR)
{
}
@@ -93,49 +93,30 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
return w.asReturnedValue();
}
-QQmlContextData *QmlContextWrapper::callingContext(ExecutionEngine *v4)
-{
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, v4->qmlContextObject());
-
- return !!c ? c->getContext() : 0;
-}
-
QQmlContextData *QmlContextWrapper::getContext(const Value &value)
{
if (!value.isObject())
return 0;
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
Scope scope(v4);
QV4::Scoped<QmlContextWrapper> c(scope, value);
return c ? c->getContext() : 0;
}
-void QmlContextWrapper::takeContextOwnership(const Value &qmlglobal)
-{
- Q_ASSERT(qmlglobal.isObject());
-
- QV4::ExecutionEngine *v4 = qmlglobal.asObject()->engine();
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal);
- Q_ASSERT(c);
- c->d()->ownsContext = true;
-}
-
-ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlContextWrapper>());
- QmlContextWrapper *resource = static_cast<QmlContextWrapper *>(m);
+ const QmlContextWrapper *resource = static_cast<const QmlContextWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
// In V8 the JS global object would come _before_ the QML global object,
// so simulate that here.
bool hasProp;
- QV4::ScopedValue result(scope, v4->globalObject()->get(name, &hasProp));
+ QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = hasProp;
@@ -145,7 +126,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
if (resource->d()->isNullWrapper)
return Object::get(m, name, hasProperty);
- if (QV4::QmlContextWrapper::callingContext(v4) != resource->d()->context)
+ if (v4->callingQmlContext() != resource->d()->context)
return Object::get(m, name, hasProperty);
result = Object::get(m, name, &hasProp);
@@ -209,7 +190,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
if (propertyIdx < context->idValueCount) {
- ep->captureProperty(&context->idValues[propertyIdx].bindings);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
if (hasProperty)
*hasProperty = true;
return QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]);
@@ -217,8 +199,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
QQmlContextPrivate *cp = context->asQQmlContextPrivate();
- ep->captureProperty(context->asQQmlContext(), -1,
- propertyIdx + cp->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
const QVariant &value = cp->propertyValues.at(propertyIdx);
if (hasProperty)
@@ -278,10 +260,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scoped<QmlContextWrapper> wrapper(scope, resource);
- PropertyAttributes attrs;
- Property *pd = wrapper->__getOwnProperty__(name, &attrs);
- if (pd) {
- wrapper->putValue(pd, attrs, value);
+ uint member = wrapper->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ wrapper->putValue(wrapper->propertyAt(member), wrapper->internalClass()->propertyData[member], value);
return;
}
@@ -342,14 +323,6 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
Object::put(m, name, value);
}
-void QmlContextWrapper::markObjects(Heap::Base *m, ExecutionEngine *engine)
-{
- QmlContextWrapper::Data *This = static_cast<QmlContextWrapper::Data *>(m);
- if (This->idObjectsWrapper)
- This->idObjectsWrapper->mark(engine);
- Object::markObjects(m, engine);
-}
-
void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const CompiledData::Function *compiledFunction)
{
// Let the caller check and avoid the function call :)
@@ -358,13 +331,13 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (!ep)
return;
- QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
+ QQmlPropertyCapture *capture = ep->propertyCapture;
if (!capture)
return;
QV4::Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject());
- QQmlContextData *qmlContext = contextWrapper->getContext();
+ QV4::Scoped<QmlContext> context(scope, engine->qmlContext());
+ QQmlContextData *qmlContext = context->qmlContext();
const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
@@ -382,7 +355,7 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
}
- QObject *scopeObject = contextWrapper->getScopeObject();
+ QObject *scopeObject = context->qmlScope();
const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
for (int i = 0; i < scopePropertyDependencyCount; ++i) {
@@ -393,15 +366,6 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
}
-ReturnedValue QmlContextWrapper::idObjectsArray()
-{
- if (!d()->idObjectsWrapper) {
- ExecutionEngine *v4 = engine();
- d()->idObjectsWrapper = v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this);
- }
- return d()->idObjectsWrapper->asReturnedValue();
-}
-
ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String *name)
{
if (!d()->context->imports)
@@ -423,46 +387,4 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String
return QJSValuePrivate::convertedToValue(engine(), siinfo->scriptApi(e));
}
-DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
-
-Heap::QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper)
- : Heap::Object(engine)
- , contextWrapper(contextWrapper->d())
-{
-}
-
-ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
-{
- Scope scope(static_cast<QV4::QQmlIdObjectsArray*>(m)->engine());
- Scoped<QQmlIdObjectsArray> This(scope, static_cast<QV4::QQmlIdObjectsArray*>(m));
- Scoped<QmlContextWrapper> contextWrapper(scope, This->d()->contextWrapper);
- QQmlContextData *context = contextWrapper->getContext();
- if (!context) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
- if (index >= (uint)context->idValueCount) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
-
- if (hasProperty)
- *hasProperty = true;
-
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
- if (ep)
- ep->captureProperty(&context->idValues[index].bindings);
-
- return QObjectWrapper::wrap(This->engine(), context->idValues[index].data());
-}
-
-void QQmlIdObjectsArray::markObjects(Heap::Base *that, ExecutionEngine *engine)
-{
- QQmlIdObjectsArray::Data *This = static_cast<QQmlIdObjectsArray::Data *>(that);
- This->contextWrapper->mark(engine);
- Object::markObjects(that, engine);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 52d8677103..7b5d3216df 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qv4functionobject_p.h>
@@ -65,8 +65,6 @@ struct QmlContextWrapper;
namespace Heap {
-struct QQmlIdObjectsArray;
-
struct QmlContextWrapper : Object {
QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
~QmlContextWrapper();
@@ -76,12 +74,6 @@ struct QmlContextWrapper : Object {
QQmlGuardedContextData context;
QPointer<QObject> scopeObject;
- QQmlIdObjectsArray *idObjectsWrapper;
-};
-
-struct QQmlIdObjectsArray : Object {
- QQmlIdObjectsArray(QV4::ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper);
- QmlContextWrapper *contextWrapper;
};
}
@@ -94,8 +86,9 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
static ReturnedValue qmlScope(ExecutionEngine *e, QQmlContextData *ctxt, QObject *scope);
static ReturnedValue urlScope(ExecutionEngine *v4, const QUrl &);
- static QQmlContextData *callingContext(ExecutionEngine *v4);
- static void takeContextOwnership(const Value &qmlglobal);
+ void takeContextOwnership() {
+ d()->ownsContext = true;
+ }
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return d()->context; }
@@ -103,24 +96,12 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
void setReadOnly(bool b) { d()->readOnly = b; }
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
- static void markObjects(Heap::Base *m, ExecutionEngine *engine);
static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
- ReturnedValue idObjectsArray();
ReturnedValue qmlSingletonWrapper(ExecutionEngine *e, String *name);
-
-};
-
-struct QQmlIdObjectsArray : public Object
-{
- V4_OBJECT2(QQmlIdObjectsArray, Object)
-
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void markObjects(Heap::Base *that, ExecutionEngine *engine);
-
};
}
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 04c42b638d..3d2a76693a 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -48,8 +48,9 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
+#include <qjsengine.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,7 @@ class QQmlEngine;
class QQmlGuardImpl;
class QQmlCompiledData;
class QQmlAbstractBinding;
-class QQmlAbstractBoundSignal;
+class QQmlBoundSignal;
class QQmlContext;
class QQmlPropertyCache;
class QQmlContextData;
@@ -72,15 +73,7 @@ class QQmlNotifierEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
{
public:
- QQmlData()
- : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
- hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
- bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
- lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
- propertyCache(0), guards(0), extendedData(0) {
- init();
- }
+ QQmlData();
static inline void init() {
static bool initialized = false;
@@ -158,7 +151,7 @@ public:
QQmlContextData *outerContext;
QQmlAbstractBinding *bindings;
- QQmlAbstractBoundSignal *signalHandlers;
+ QQmlBoundSignal *signalHandlers;
// Linked list for QQmlContext::contextObjects
QQmlData *nextContextObject;
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 7f6310d58e..57b50733ea 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -146,7 +146,7 @@ bool QQmlDirParser::parse(const QString &source)
if (invalidLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("invalid qmldir directive contains too many tokens"));
+ QStringLiteral("invalid qmldir directive contains too many tokens"));
continue;
} else if (sectionCount == 0) {
continue; // no sections, no party.
@@ -154,17 +154,17 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("module")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
if (!_typeNamespace.isEmpty()) {
reportError(lineNumber, 0,
- QString::fromLatin1("only one module identifier directive may be defined in a qmldir file"));
+ QStringLiteral("only one module identifier directive may be defined in a qmldir file"));
continue;
}
if (!firstLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive must be the first directive in a qmldir file"));
+ QStringLiteral("module identifier directive must be the first directive in a qmldir file"));
continue;
}
@@ -173,7 +173,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("plugin")) {
if (sectionCount < 2 || sectionCount > 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -185,7 +185,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
Component entry(sections[1], sections[2], -1, -1);
@@ -194,7 +194,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("singleton")) {
if (sectionCount < 3 || sectionCount > 4) {
reportError(lineNumber, 0,
- QString::fromLatin1("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
} else if (sectionCount == 3) {
// handle qmldir directory listing case where singleton is defined in the following pattern:
@@ -218,7 +218,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("typeinfo")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
#ifdef QT_CREATOR
@@ -228,13 +228,13 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("designersupported")) {
if (sectionCount != 1)
- reportError(lineNumber, 0, QString::fromLatin1("designersupported does not expect any argument"));
+ reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
else
_designerSupported = true;
} else if (sections[0] == QLatin1String("depends")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -268,7 +268,7 @@ bool QQmlDirParser::parse(const QString &source)
}
} else {
reportError(lineNumber, 0,
- QString::fromLatin1("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
+ QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
}
firstLine = false;
@@ -304,7 +304,9 @@ QList<QQmlError> QQmlDirParser::errors(const QString &uri) const
{
QUrl url(uri);
QList<QQmlError> errors;
- for (int i = 0; i < _errors.size(); ++i) {
+ const int numErrors = _errors.size();
+ errors.reserve(numErrors);
+ for (int i = 0; i < numErrors; ++i) {
const QQmlJS::DiagnosticMessage &msg = _errors.at(i);
QQmlError e;
QString description = msg.message;
@@ -362,14 +364,14 @@ bool QQmlDirParser::designerSupported() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
return debug << qPrintable(output);
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index ffc890a2cf..9c5e48ae32 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -42,7 +42,6 @@
#include "qqmlexpression.h"
#include "qqmlcomponent.h"
#include "qqmlvme_p.h"
-#include <private/qqmlenginedebugservice_p.h>
#include "qqmlstringconverters_p.h"
#include "qqmlxmlhttprequest_p.h"
#include "qqmlscriptstring.h"
@@ -54,11 +53,7 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
-#include <private/qqmldebugserver_p.h>
-#include <private/qqmlprofilerservice_p.h>
-#include <private/qv4debugservice_p.h>
-#include <private/qdebugmessageservice_p.h>
-#include <private/qqmlenginecontrolservice_p.h>
+#include <private/qqmldebugconnector_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
@@ -225,7 +220,6 @@ void QQmlEnginePrivate::activateDesignerMode()
/*!
\class QQmlImageProviderBase
\brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
- \mainclass
\inmodule QtQml
Image providers must be registered with the QML engine. The only information the QML
@@ -247,6 +241,10 @@ void QQmlEnginePrivate::activateDesignerMode()
The QQuickImageProvider::requestPixmap() method will be called for all image requests.
\value Texture The Image Provider provides QSGTextureProvider based images.
The QQuickImageProvider::requestTexture() method will be called for all image requests.
+ \value ImageResponse The Image provider provides QQuickTextureFactory based images.
+ Should only be used in QQuickAsyncImageProvider or its subclasses.
+ The QQuickAsyncImageProvider::requestImageResponse() method will be called for all image requests.
+ Since Qt 5.6
\omitvalue Invalid
*/
@@ -594,7 +592,7 @@ the same object as is returned from the Qt.include() call.
// Qt.include() is implemented in qv4include.cpp
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
-: propertyCapture(0), rootContext(0), isDebugging(false),
+: propertyCapture(0), rootContext(0),
profiler(0), outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
@@ -607,8 +605,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
QQmlEnginePrivate::~QQmlEnginePrivate()
{
- typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator TypePropertyCacheIt;
- typedef QHash<int, QQmlCompiledData *>::Iterator CompositeTypesIt;
+ typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt;
+ typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt;
if (inProgressCreations)
qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
@@ -627,9 +625,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter)
+ for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter)
(*iter)->release();
- for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) {
+ for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
// since unregisterInternalCompositeType() will not be called in this
@@ -666,6 +664,17 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
}
}
+QQmlData::QQmlData()
+ : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
+ hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
+ hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
+ bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
+ lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
+ propertyCache(0), guards(0), extendedData(0)
+{
+ init();
+}
+
void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
{
QQmlData *ddata = static_cast<QQmlData *>(d);
@@ -799,7 +808,7 @@ void QQmlData::markAsDeleted(QObject *o)
QQmlData::setQueuedForDeletion(o);
QObjectPrivate *p = QObjectPrivate::get(o);
- for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
+ for (QList<QObject *>::const_iterator it = p->children.constBegin(), end = p->children.constEnd(); it != end; ++it) {
QQmlData::markAsDeleted(*it);
}
}
@@ -824,14 +833,12 @@ void QQmlData::flushPendingBindingImpl(int coreIndex)
// Find the binding
QQmlAbstractBinding *b = bindings;
- while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- if (b && b->propertyIndex() == coreIndex) {
- b->clear();
+ if (b && b->targetPropertyIndex() == coreIndex)
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
- }
}
bool QQmlEnginePrivate::baseModulesUninitialized = true;
@@ -861,15 +868,9 @@ void QQmlEnginePrivate::init()
rootContext = new QQmlContext(q,true);
- if (QCoreApplication::instance()->thread() == q->thread() &&
- QQmlEngineDebugService::isDebuggingEnabled()) {
- isDebugging = true;
- QQmlEngineDebugService::instance();
- QV4DebugService::instance();
- QQmlProfilerService::instance();
- QDebugMessageService::instance();
- QQmlEngineControlService::instance();
- QQmlDebugServer::instance()->addEngine(q);
+ if (QCoreApplication::instance()->thread() == q->thread() && QQmlDebugConnector::instance()) {
+ QQmlDebugConnector::instance()->open();
+ QQmlDebugConnector::instance()->addEngine(q);
}
}
@@ -886,7 +887,6 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
\since 5.0
\inmodule QtQml
\brief The QQmlEngine class provides an environment for instantiating QML components.
- \mainclass
Each QML component is instantiated in a QQmlContext.
QQmlContext's are essential for passing data to QML
@@ -947,8 +947,9 @@ QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
QQmlEngine::~QQmlEngine()
{
Q_D(QQmlEngine);
- if (d->isDebugging)
- QQmlDebugServer::instance()->removeEngine(this);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+ if (server)
+ server->removeEngine(this);
d->typeLoader.invalidate();
@@ -1492,51 +1493,6 @@ Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *o
#endif // QT_DEPRECATED_SINCE(5, 1)
-QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- if (!QQmlEnginePrivate::qml_debugging_enabled
- && printWarning) {
- qDebug("QML debugging is enabled. Only use this in a safe environment.");
- }
- QQmlEnginePrivate::qml_debugging_enabled = true;
-#else
- Q_UNUSED(printWarning);
-#endif
-}
-
-/*!
- * \enum QQmlDebuggingEnabler::StartMode
- *
- * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
- * client is connecting, in order to set breakpoints in or profile startup code.
- *
- * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
- * \value WaitForClient If a QML engine starts while the debug services are connecting,
- * interrupt it until they are done.
- */
-
-/*!
- * Enables debugging for QML engines created after calling this function. The debug server will
- * listen on \a port at \a hostName and block the QML engine until it receives a connection if
- * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
- * specified it will listen on all available interfaces. You can only start one debug server at a
- * time. A debug server may have already been started if the -qmljsdebugger= command line argument
- * was given. This method returns \c true if a new debug server was successfully started, or
- * \c false otherwise.
- */
-bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- return QQmlDebugServer::enable(port, port, mode == WaitForClient, hostName);
-#else
- Q_UNUSED(port);
- Q_UNUSED(block);
- Q_UNUSED(hostName);
- return false;
-#endif
-}
-
class QQmlDataExtended {
public:
QQmlDataExtended();
@@ -1678,12 +1634,11 @@ void QQmlData::destroyed(QObject *object)
QQmlAbstractBinding *binding = bindings;
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
+ if (bindings && !bindings->ref.deref())
+ delete bindings;
if (compiledData) {
compiledData->release();
@@ -1696,9 +1651,9 @@ void QQmlData::destroyed(QObject *object)
deferredData = 0;
}
- QQmlAbstractBoundSignal *signalHandler = signalHandlers;
+ QQmlBoundSignal *signalHandler = signalHandlers;
while (signalHandler) {
- if (signalHandler->isEvaluating()) {
+ if (signalHandler->isNotifying()) {
// The object is being deleted during signal handler evaluation.
// This will cause a crash due to invalid memory access when the
// evaluation has completed.
@@ -1710,7 +1665,7 @@ void QQmlData::destroyed(QObject *object)
if (location.sourceFile.isEmpty())
location.sourceFile = QStringLiteral("<Unknown File>");
locationString.append(location.sourceFile);
- locationString.append(QString::fromLatin1(":%0: ").arg(location.line));
+ locationString.append(QStringLiteral(":%0: ").arg(location.line));
QString source = expr->expression();
if (source.size() > 100) {
source.truncate(96);
@@ -1727,7 +1682,7 @@ void QQmlData::destroyed(QObject *object)
"%s", object, qPrintable(locationString));
}
- QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
+ QQmlBoundSignal *next = signalHandler->m_nextSignal;
signalHandler->m_prevSignal = 0;
signalHandler->m_nextSignal = 0;
delete signalHandler;
@@ -2140,8 +2095,7 @@ QString QQmlEngine::offlineStoragePath() const
return d->offlineStoragePath;
}
-QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
- QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion)
{
QList<QQmlType *> types;
@@ -2203,10 +2157,10 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
// Properties override:
// * other elements of the same name
+#if 0
bool overloadError = false;
QString overloadName;
-#if 0
for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
!overloadError && iter != raw->stringCache.end();
++iter) {
@@ -2223,7 +2177,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
overloadError = true;
}
}
-#endif
if (overloadError) {
if (hasCopied) raw->release();
@@ -2231,6 +2184,7 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
return 0;
}
+#endif
if (!hasCopied) raw->addref();
typePropertyCache.insert(qMakePair(type, minorVersion), raw);
@@ -2281,8 +2235,8 @@ bool QQmlEnginePrivate::isList(int t) const
int QQmlEnginePrivate::listType(int t) const
{
Locker locker(this);
- QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
- if (iter != m_qmlLists.end())
+ QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t);
+ if (iter != m_qmlLists.cend())
return *iter;
else
return QQmlMetaType::listType(t);
@@ -2291,8 +2245,8 @@ int QQmlEnginePrivate::listType(int t) const
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2303,8 +2257,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2315,8 +2269,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2328,8 +2282,8 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index df673c1fd5..61a884279d 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -52,7 +52,9 @@ public:
Image,
Pixmap,
Texture,
- Invalid
+ Invalid,
+ ImageResponse
+ // ### Qt6: reorder these, and give Invalid a fixed large value
};
enum Flag {
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index f1fbad3cf8..26ee3bd655 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -85,7 +85,6 @@ class QQmlImportDatabase;
class QNetworkReply;
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
-class QQmlAbstractBinding;
class QQmlTypeNameCache;
class QQmlComponentAttached;
class QQmlCleanup;
@@ -95,6 +94,7 @@ class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
class QQmlProfiler;
+class QQmlPropertyCapture;
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -123,21 +123,11 @@ public:
// is just qmlClearTypeRegistrations (which can't be called while an engine exists)
static bool baseModulesUninitialized;
- class PropertyCapture {
- public:
- inline virtual ~PropertyCapture() {}
- virtual void captureProperty(QQmlNotifier *) = 0;
- virtual void captureProperty(QObject *, int, int) = 0;
- };
-
- PropertyCapture *propertyCapture;
- inline void captureProperty(QQmlNotifier *);
- inline void captureProperty(QObject *, int, int);
+ QQmlPropertyCapture *propertyCapture;
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
QQmlContext *rootContext;
- bool isDebugging;
QQmlProfiler *profiler;
void enableProfiler();
@@ -208,7 +198,7 @@ public:
inline static void deleteInEngineThread(QQmlEngine *, T *);
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+ inline QQmlPropertyCache *cache(QQmlType *, int);
using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
@@ -262,7 +252,7 @@ public:
private:
// Must be called locked
- QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
+ QQmlPropertyCache *createCache(QQmlType *, int);
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
@@ -346,7 +336,7 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion)
{
Q_ASSERT(type);
@@ -355,7 +345,7 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQ
Locker locker(this);
QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
- if (!rv) rv = createCache(type, minorVersion, error);
+ if (!rv) rv = createCache(type, minorVersion);
return rv;
}
@@ -414,18 +404,6 @@ QQmlEnginePrivate *QQmlEnginePrivate::get(QV4::ExecutionEngine *e)
return get(qmlEngine);
}
-void QQmlEnginePrivate::captureProperty(QQmlNotifier *n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(n);
-}
-
-void QQmlEnginePrivate::captureProperty(QObject *o, int c, int n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(o, c, n);
-}
-
void QQmlEnginePrivate::setDebugChangesCache(const QHash<QUrl, QByteArray> &changes)
{
Locker locker(this);
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 35e0bc8c64..332b99ee8f 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -45,13 +45,8 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
- QQmlExpressionPrivate::expressionIdentifier,
- QQmlExpressionPrivate::expressionChanged
-};
-
QQmlExpressionPrivate::QQmlExpressionPrivate()
-: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
+: QQmlJavaScriptExpression(),
expressionFunctionValid(true),
line(0), column(0)
{
@@ -65,7 +60,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
{
expression = expr;
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
expressionFunctionValid = false;
}
@@ -74,9 +69,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu
{
expressionFunctionValid = true;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
+ m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
}
@@ -246,18 +241,12 @@ void QQmlExpression::setExpression(const QString &expression)
// Must be called with a valid handle scope
QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
{
- Q_Q(QQmlExpression);
-
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine();
-
if (!expressionFunctionValid) {
- function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope));
+ createQmlBinding(context(), scopeObject(), expression, url, line);
expressionFunctionValid = true;
}
- QV4::Scope scope(v4);
- QV4::ScopedValue f(scope, function.value());
- return evaluate(context(), f, isUndefined);
+ return evaluate(isUndefined);
}
QVariant QQmlExpressionPrivate::value(bool *isUndefined)
@@ -432,22 +421,15 @@ QQmlError QQmlExpression::error() const
calling QQmlExpression::evaluate()) before this signal will be emitted.
*/
-void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e)
-{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- This->expressionChanged();
-}
-
void QQmlExpressionPrivate::expressionChanged()
{
Q_Q(QQmlExpression);
emit q->valueChanged();
}
-QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlExpressionPrivate::expressionIdentifier()
{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- return QLatin1Char('"') + This->expression + QLatin1Char('"');
+ return QLatin1Char('"') + expression + QLatin1Char('"');
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index d8da387878..2303539194 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -52,7 +52,6 @@
#include <private/qflagpointer_p.h>
#include <private/qdeletewatcher_p.h>
#include <private/qpointervaluepair_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
@@ -60,8 +59,7 @@ QT_BEGIN_NAMESPACE
class QQmlExpression;
class QString;
class QQmlExpressionPrivate : public QObjectPrivate,
- public QQmlJavaScriptExpression,
- public QQmlAbstractExpression
+ public QQmlJavaScriptExpression
{
Q_DECLARE_PUBLIC(QQmlExpression)
public:
@@ -82,16 +80,12 @@ public:
bool expressionFunctionValid:1;
- // "Inherited" from QQmlJavaScriptExpression
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // Inherited from QQmlJavaScriptExpression
+ virtual QString expressionIdentifier();
virtual void expressionChanged();
QString expression;
- QV4::PersistentValue qmlscope;
- QV4::PersistentValue function;
-
QString url; // This is a QString for a reason. QUrls are slooooooow...
quint16 line;
quint16 column;
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index d904242f93..0a2f4079c2 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -359,7 +359,7 @@ QObject *QQmlGuiProvider::inputMethod()
{
// We don't have any input method code by default
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No inputMethod available"));
+ o->setObjectName(QStringLiteral("No inputMethod available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
@@ -368,7 +368,7 @@ QObject *QQmlGuiProvider::inputMethod()
QObject *QQmlGuiProvider::styleHints()
{
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No styleHints available"));
+ o->setObjectName(QStringLiteral("No styleHints available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index ff48a10d95..b17bb0455d 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -169,6 +169,7 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
} // namespace
+#ifndef QT_NO_LIBRARY
struct RegisteredPlugin {
QString uri;
QPluginLoader* loader;
@@ -193,6 +194,7 @@ void qmlClearEnginePlugins()
}
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
+#endif
class QQmlImportNamespace
{
@@ -292,9 +294,10 @@ public:
const QString &uri, const QString &url,
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
-
+#ifndef QT_NO_LIBRARY
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
const QString &qmldirPath, QList<QQmlError> *errors);
+#endif
};
/*!
@@ -382,7 +385,7 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
// We need to exclude the entry for the current baseUrl. This can happen for example
// when handling qmldir files on the remote dir case and the current type is marked as
// singleton.
-bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString baseUrl)
+bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString &baseUrl)
{
if (importUrl.isEmpty())
return false;
@@ -398,7 +401,7 @@ bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QSt
return true;
}
-void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, QUrl baseUrl)
+void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, const QUrl &baseUrl)
{
typedef QQmlDirComponents::const_iterator ConstIterator;
@@ -826,6 +829,7 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
}
+#ifndef QT_NO_LIBRARY
/*!
Get all static plugins that are QML plugins and has a meta data URI that begins with \a uri.
Note that if e.g uri == "a", and different plugins have meta data "a", "a.2.1", "a.b.c", all
@@ -869,6 +873,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
return true;
}
+#endif
/*!
Import an extension defined by a qmldir file.
@@ -995,6 +1000,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
#else
+ Q_UNUSED(qmldirFilePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(vmin);
+ Q_UNUSED(database);
+ Q_UNUSED(qmldir);
+ Q_UNUSED(errors);
return false;
#endif // QT_NO_LIBRARY
return true;
@@ -1931,6 +1943,12 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
return true;
#else
+ Q_UNUSED(instance);
+ Q_UNUSED(basePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
@@ -2011,6 +2029,11 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
return true;
#else
+ Q_UNUSED(filePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 02bd1c4b83..5f30eac066 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -35,7 +35,7 @@
#include <private/qqmlexpression_p.h>
#include <private/qqmlcontextwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
@@ -83,13 +83,22 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
}
-QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v)
-: m_vtable(v)
+QQmlJavaScriptExpression::QQmlJavaScriptExpression()
+ : m_error(0),
+ m_context(0),
+ m_prevExpression(0),
+ m_nextExpression(0)
{
}
QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ }
+
clearGuards();
if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
m_scopeObject.asT2()->_s = 0;
@@ -106,40 +115,62 @@ void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
clearGuards();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function, bool *isUndefined)
+void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(context->engine);
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ m_prevExpression = 0;
+ m_nextExpression = 0;
+ }
+
+ m_context = context;
+
+ if (context) {
+ m_nextExpression = context->expressions;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = &context->expressions;
+ context->expressions = this;
+ }
+}
+
+void QQmlJavaScriptExpression::refresh()
+{
+}
+
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
+{
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine);
QV4::Scope scope(v4);
QV4::ScopedCallData callData(scope);
- return evaluate(context, function, callData, isUndefined);
+ return evaluate(callData, isUndefined);
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function,
- QV4::CallData *callData,
- bool *isUndefined)
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
{
- Q_ASSERT(context && context->engine);
+ Q_ASSERT(m_context && m_context->engine);
- if (function.isUndefined()) {
+ QV4::Value *f = m_function.valueRef();
+ if (!f || f->isUndefined()) {
if (isUndefined)
*isUndefined = true;
return QV4::Encode::undefined();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
DeleteWatcher watcher(this);
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- GuardCapture capture(context->engine, this, &watcher);
+ QQmlPropertyCapture capture(m_context->engine, this, &watcher);
- QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
- ep->propertyCapture = notifyOnValueChanged()?&capture:0;
+ QQmlPropertyCapture *lastPropertyCapture = ep->propertyCapture;
+ ep->propertyCapture = notifyOnValueChanged() ? &capture : 0;
if (notifyOnValueChanged())
@@ -148,14 +179,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
- callData->thisObject = v4->globalObject();
+ callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
if (value->isObject())
callData->thisObject = value;
}
- result = function.asFunctionObject()->call(callData);
+ result = f->as<QV4::FunctionObject>()->call(callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
scope.engine->catchException(); // ignore exception
@@ -178,7 +209,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
capture.errorString = 0;
}
- while (Guard *g = capture.guards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
g->Delete();
ep->propertyCapture = lastPropertyCapture;
@@ -186,7 +217,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
return result->asReturnedValue();
}
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
+void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
{
if (watcher->wasDeleted())
return;
@@ -196,13 +227,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
while (!guards.isEmpty() && !guards.first()->isConnected(n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(n);
}
@@ -213,7 +244,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
\a n is in the signal index range (see QObjectPrivate::signalIndex()).
*/
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
+void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
{
if (watcher->wasDeleted())
return;
@@ -223,7 +254,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
if (!errorString) {
errorString = new QStringList;
QString preamble = QLatin1String("QQmlExpression: Expression ") +
- expression->m_vtable->expressionIdentifier(expression) +
+ expression->expressionIdentifier() +
QLatin1String(" depends on non-NOTIFYable properties:");
errorString->append(preamble);
}
@@ -242,13 +273,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(o, n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(o, n, engine);
}
@@ -258,31 +289,31 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
void QQmlJavaScriptExpression::clearError()
{
- if (m_vtable.hasValue()) {
- m_vtable.value().clearError();
- m_vtable.value().removeError();
- }
+ if (m_error)
+ delete m_error;
+ m_error = 0;
}
QQmlError QQmlJavaScriptExpression::error(QQmlEngine *engine) const
{
Q_UNUSED(engine);
- if (m_vtable.hasValue())
- return m_vtable.constValue()->error();
+ if (m_error)
+ return m_error->error();
else
return QQmlError();
}
QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
{
- return &m_vtable.value();
+ if (!m_error)
+ m_error = new QQmlDelayedError;
+ return m_error;
}
QV4::ReturnedValue
QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -308,14 +339,11 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
ep->warning(error);
return QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
return result->asReturnedValue();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -339,17 +367,15 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
error.setUrl(QUrl::fromLocalFile(filename));
error.setObject(qmlScope);
ep->warning(error);
- return QV4::Encode::undefined();
+ result = QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
- return result->asReturnedValue();
+ m_function.set(v4, result);
}
void QQmlJavaScriptExpression::clearGuards()
{
- while (Guard *g = activeGuards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst())
g->Delete();
}
@@ -358,7 +384,7 @@ void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **)
QQmlJavaScriptExpression *expression =
static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
- expression->m_vtable->expressionChanged(expression);
+ expression->expressionChanged();
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 989d5a0b0d..dfcf8b2d68 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -89,23 +89,17 @@ private:
QQmlDelayedError **prevError;
};
-class QQmlJavaScriptExpression
+class Q_QML_PRIVATE_EXPORT QQmlJavaScriptExpression
{
public:
- // Although this looks crazy, we implement our own "vtable" here, rather than relying on
- // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage
- // location that is use for the vtable to also store the rarely used delayed error.
- // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
- // memory for every expression.
- struct VTable {
- QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
- void (*expressionChanged)(QQmlJavaScriptExpression *);
- };
+ QQmlJavaScriptExpression();
+ virtual ~QQmlJavaScriptExpression();
- QQmlJavaScriptExpression(VTable *vtable);
+ virtual QString expressionIdentifier() = 0;
+ virtual void expressionChanged() = 0;
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, bool *isUndefined);
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, QV4::CallData *callData, bool *isUndefined);
+ QV4::ReturnedValue evaluate(bool *isUndefined);
+ QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
inline bool notifyOnValueChanged() const;
@@ -115,6 +109,13 @@ public:
inline QObject *scopeObject() const;
inline void setScopeObject(QObject *v);
+ bool isValid() const { return context() != 0; }
+
+ QQmlContextData *context() const { return m_context; }
+ void setContext(QQmlContextData *context);
+
+ virtual void refresh();
+
class DeleteWatcher {
public:
inline DeleteWatcher(QQmlJavaScriptExpression *);
@@ -136,46 +137,50 @@ public:
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
const QString &code, const QString &filename,
- quint16 line,
- QV4::PersistentValue *qmlscope = 0);
- // doesn't require rewriting the expression
- static QV4::ReturnedValue qmlBinding(QQmlContextData *ctxt, QObject *scope,
- const QString &code,
- const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope = 0);
+ quint16 line);
protected:
- ~QQmlJavaScriptExpression();
+ void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
private:
- typedef QQmlJavaScriptExpressionGuard Guard;
+ friend class QQmlContextData;
+ friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
- struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
- GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, DeleteWatcher *w)
- : engine(engine), expression(e), watcher(w), errorString(0) { }
-
- ~GuardCapture() {
- Q_ASSERT(guards.isEmpty());
- Q_ASSERT(errorString == 0);
- }
-
- virtual void captureProperty(QQmlNotifier *);
- virtual void captureProperty(QObject *, int, int);
-
- QQmlEngine *engine;
- QQmlJavaScriptExpression *expression;
- DeleteWatcher *watcher;
- QFieldList<Guard, &Guard::next> guards;
- QStringList *errorString;
- };
-
- QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
+ QQmlDelayedError *m_error;
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
- QForwardFieldList<Guard, &Guard::next> activeGuards;
+ QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
+
+ QQmlContextData *m_context;
+ QQmlJavaScriptExpression **m_prevExpression;
+ QQmlJavaScriptExpression *m_nextExpression;
+
+protected:
+ QV4::PersistentValue m_function;
+};
+
+class QQmlPropertyCapture
+{
+public:
+ QQmlPropertyCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, QQmlJavaScriptExpression::DeleteWatcher *w)
+ : engine(engine), expression(e), watcher(w), errorString(0) { }
+
+ ~QQmlPropertyCapture() {
+ Q_ASSERT(guards.isEmpty());
+ Q_ASSERT(errorString == 0);
+ }
+
+ void captureProperty(QQmlNotifier *);
+ void captureProperty(QObject *, int, int);
+
+ QQmlEngine *engine;
+ QQmlJavaScriptExpression *expression;
+ QQmlJavaScriptExpression::DeleteWatcher *watcher;
+ QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
+ QStringList *errorString;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -222,18 +227,18 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v)
bool QQmlJavaScriptExpression::hasError() const
{
- return m_vtable.hasValue() && m_vtable.constValue()->isValid();
+ return m_error && m_error->isValid();
}
bool QQmlJavaScriptExpression::hasDelayedError() const
{
- return m_vtable.hasValue();
+ return m_error;
}
QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
-: expression(e), next(0)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard),
+ expression(e), next(0)
{
- setCallback(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard);
}
QQmlJavaScriptExpressionGuard *
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index bcb1e72f0b..d09f4df54c 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -92,13 +92,13 @@ QVariant QmlListWrapper::toVariant() const
}
-ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
- if (name->equals(v4->id_length) && !w->d()->object.isNull()) {
+ if (name->equals(v4->id_length()) && !w->d()->object.isNull()) {
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
return Primitive::fromUInt32(count).asReturnedValue();
}
@@ -110,12 +110,12 @@ ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
return Object::get(m, name, hasProperty);
}
-ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_UNUSED(hasProperty);
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
@@ -138,9 +138,9 @@ void QmlListWrapper::put(Managed *m, String *name, const Value &value)
Q_UNUSED(value);
}
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
Q_ASSERT(m->as<QmlListWrapper>());
QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 3590bcb1c9..ff006d4302 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -50,7 +50,7 @@
#include <QtQml/qqmllist.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -81,10 +81,10 @@ struct Q_QML_EXPORT QmlListWrapper : Object
QVariant toVariant() const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
}
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 62b5b76ede..7f49798da6 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -65,13 +65,13 @@ static bool isLocaleObject(const QV4::Value &val)
void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
}
QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -81,7 +81,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleString(ctx);
@@ -125,7 +125,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleTimeString(ctx);
@@ -170,7 +170,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *dateObj = ctx->thisObject().asDateObject();
+ QV4::DateObject *dateObj = ctx->thisObject().as<DateObject>();
if (!dateObj)
return QV4::DatePrototype::method_toLocaleDateString(ctx);
@@ -347,9 +347,9 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c
void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
- engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
+ engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
}
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -815,15 +815,15 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
{
- engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
+ engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
}
QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
{
- if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].asStringObject()))
+ if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as<StringObject>()))
return QV4::StringPrototype::method_localeCompare(ctx);
- if (!ctx->thisObject().isString() && !ctx->thisObject().asStringObject())
+ if (!ctx->thisObject().isString() && !ctx->thisObject().as<StringObject>())
return QV4::StringPrototype::method_localeCompare(ctx);
QString thisString = ctx->thisObject().toQStringNoThrow();
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index d4436482cf..cb9fe9bbef 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -74,10 +74,6 @@ private:
class Q_AUTOTEST_EXPORT QQmlLocale
{
Q_GADGET
- Q_ENUMS(MeasurementSystem)
- Q_ENUMS(FormatType)
- Q_ENUMS(CurrencySymbolFormat)
- Q_ENUMS(DayOfWeek)
public:
~QQmlLocale();
@@ -88,16 +84,19 @@ public:
ImperialUSSystem = QLocale::ImperialUSSystem,
ImperialUKSystem = QLocale::ImperialUKSystem
};
+ Q_ENUM(MeasurementSystem)
enum FormatType {
LongFormat = QLocale::LongFormat,
ShortFormat = QLocale::ShortFormat,
NarrowFormat = QLocale::NarrowFormat
};
+ Q_ENUM(FormatType)
enum CurrencySymbolFormat {
CurrencyIsoCode = QLocale::CurrencyIsoCode,
CurrencySymbol = QLocale::CurrencySymbol,
CurrencyDisplayName = QLocale::CurrencyDisplayName
};
+ Q_ENUM(CurrencySymbolFormat)
// Qt defines Sunday as 7, but JS Date assigns Sunday 0
enum DayOfWeek {
Sunday = 0,
@@ -108,6 +107,7 @@ public:
Friday = Qt::Friday,
Saturday = Qt::Saturday
};
+ Q_ENUM(DayOfWeek)
static QV4::ReturnedValue locale(QV4::ExecutionEngine *engine, const QString &localeName);
static QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale);
@@ -137,7 +137,7 @@ struct QQmlLocaleData : public QV4::Object
V4_NEEDS_DESTROY
static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QV4::Object *o = ctx->thisObject().asObject();
+ QV4::Object *o = ctx->thisObject().as<Object>();
QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0;
if (!thisObject) {
ctx->engine()->throwTypeError();
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/qml/qqmlmemoryprofiler.cpp
index cdd60e2dec..531666340b 100644
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ b/src/qml/qml/qqmlmemoryprofiler.cpp
@@ -63,11 +63,13 @@ static qmlmemprofile_pop_location *memprofile_pop_location;
static qmlmemprofile_save *memprofile_save;
static qmlmemprofile_is_enabled *memprofile_is_enabled;
+#ifndef QT_NO_LIBRARY
extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol);
+#endif
static bool openLibrary()
{
-#ifdef Q_OS_LINUX
+#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY)
if (state == Unloaded) {
memprofile_stats = (qmlmemprofile_stats *) qt_linux_find_symbol_sys("qmlmemprofile_stats");
memprofile_clear = (qmlmemprofile_clear *) qt_linux_find_symbol_sys("qmlmemprofile_clear");
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index cb8c2bd3b5..fbb21f4562 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -258,7 +258,7 @@ QObject *QQmlType::SingletonInstanceInfo::qobjectApi(QQmlEngine *e) const
return qobjectApis.value(e);
}
-void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, QJSValue v)
+void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, const QJSValue &v)
{
scriptApis.insert(e, v);
}
@@ -1110,7 +1110,9 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
data->uriToModule.clear();
QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types
+#ifndef QT_NO_LIBRARY
qmlClearEnginePlugins();
+#endif
}
int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
@@ -1440,8 +1442,8 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
- iter != data->uriToModule.end(); ++iter) {
+ for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.cbegin();
+ iter != data->uriToModule.cend(); ++iter) {
if ((*iter)->module() == uri)
return true;
}
@@ -1718,7 +1720,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
- while (it != data->nameToType.end() && it.key() == name) {
+ while (it != data->nameToType.cend() && it.key() == name) {
// XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor))
return (*it);
@@ -1752,7 +1754,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
- while (it != data->metaObjectToType.end() && it.key() == metaObject) {
+ while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
QQmlType *t = *it;
if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor))
return t;
@@ -1823,8 +1825,9 @@ QList<QString> QQmlMetaType::qmlTypeNames()
QQmlMetaTypeData *data = metaTypeData();
QList<QString> names;
- QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
- while (it != data->nameToType.end()) {
+ names.reserve(data->nameToType.count());
+ QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin();
+ while (it != data->nameToType.cend()) {
names += (*it)->qmlTypeName();
++it;
}
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index e5ac20d314..61a6567f1d 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -191,7 +191,7 @@ public:
void setQObjectApi(QQmlEngine *, QObject *);
QObject *qobjectApi(QQmlEngine *) const;
- void setScriptApi(QQmlEngine *, QJSValue);
+ void setScriptApi(QQmlEngine *, const QJSValue &);
QJSValue scriptApi(QQmlEngine *) const;
void init(QQmlEngine *);
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 2742bfc84b..90902c089d 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -63,9 +63,6 @@ class QQmlNotifierEndpoint
QQmlNotifierEndpoint *next;
QQmlNotifierEndpoint **prev;
public:
- inline QQmlNotifierEndpoint();
- inline ~QQmlNotifierEndpoint();
-
// QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
// To add another callback, extend this enum and add the callback to the top
// of qqmlnotifier.cpp. Four bits are reserved for the callback, so there can
@@ -77,7 +74,8 @@ public:
QQmlVMEMetaObjectEndpoint = 3
};
- inline void setCallback(Callback c) { callback = c; }
+ inline QQmlNotifierEndpoint(Callback callback);
+ inline ~QQmlNotifierEndpoint();
inline bool isConnected();
inline bool isConnected(QObject *source, int sourceSignal);
@@ -90,6 +88,8 @@ public:
inline bool isNotifying() const;
inline void cancelNotify();
+ inline int signalIndex() const { return sourceSignal; }
+
private:
friend class QQmlData;
friend class QQmlNotifier;
@@ -135,8 +135,8 @@ void QQmlNotifier::notify()
if (endpoints) emitNotify(endpoints, args);
}
-QQmlNotifierEndpoint::QQmlNotifierEndpoint()
-: next(0), prev(0), senderPtr(0), callback(None), sourceSignal(-1)
+QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback)
+: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1)
{
}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3c2f3690b9..0b977f2551 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -62,14 +62,6 @@ struct ActiveOCRestorer
};
}
-static void removeBindingOnProperty(QObject *o, int index)
-{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
-}
-
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
: phase(Startup)
, compiledData(compiledData)
@@ -137,11 +129,6 @@ QQmlObjectCreator::~QQmlObjectCreator()
{
QQmlObjectCreatorRecursionWatcher watcher(this);
}
- for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
- if (b)
- b->m_mePtr = 0;
- }
for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
if (ps)
@@ -660,15 +647,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
// ### this is best done through type-compile-time binding skip lists.
if (_valueTypeProperty) {
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex);
- if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
- QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
- binding->destroy();
+ if (binding && !binding->isValueTypeProxy()) {
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex);
} else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
- static_cast<QQmlValueTypeProxyBinding *>(binding);
+ QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
@@ -731,7 +715,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
// ### resolve this at compile time
if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject);
- ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : QQmlBinding::Invalid;
+ ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
ss.d.data()->lineNumber = binding->location.line;
ss.d.data()->columnNumber = binding->location.column;
ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String;
@@ -800,7 +784,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
- removeBindingOnProperty(_bindingTarget, property->coreIndex);
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex);
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
@@ -828,18 +812,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_valueTypeProperty)
targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
- sharedState->allCreatedBindings.push(qmlBinding);
- qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top();
+ sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context);
+ qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
if (targetCorePropertyData.isAlias()) {
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget,
- targetCorePropertyData.coreIndex,
- targetCorePropertyData.getValueTypeCoreIndex(),
- qmlBinding);
- if (old) { old->destroy(); }
+ QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -1011,7 +989,7 @@ QV4::Heap::ExecutionContext *QQmlObjectCreator::currentQmlContext()
{
if (!_qmlBindingWrapper->objectValue()) {
QV4::Scope valueScope(v4);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
+ QV4::Scoped<QV4::QmlContextWrapper> qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
QV4::ScopedContext global(valueScope, v4->rootContext());
*_qmlBindingWrapper = v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope);
}
@@ -1124,7 +1102,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QBitArray bindingsToSkip;
if (customParser) {
- QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.find(index);
+ QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
if (customParserBindings != compiledData->customParserBindings.constEnd()) {
customParser->imports = compiledData->importCache;
@@ -1183,13 +1161,14 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
while (!sharedState->allCreatedBindings.isEmpty()) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
- if (!b)
+ QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.pop();
+ Q_ASSERT(b);
+ // skip, if b is not added to an object
+ if (!b->isAddedToObject())
continue;
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
+ QQmlData *data = QQmlData::get(b->targetObject());
Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
+ data->clearPendingBindingBit(b->targetPropertyIndex());
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
@@ -1299,7 +1278,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QBitArray bindingSkipList = bindingsToSkip;
{
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex);
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex);
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
if (bindingSkipList.isEmpty())
bindingSkipList.resize(deferredBindings->count());
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 60fefe494f..c88c15b525 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -55,7 +55,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
{
QQmlContextData *rootContext;
QQmlContextData *creationContext;
- QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
+ QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index fc24b15fd2..c6d2d44ee1 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -277,8 +277,8 @@ void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- if (iter == d->type->d->names.end())
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ if (iter == d->type->d->names.cend())
return QVariant();
return d->getData(*iter);
@@ -286,8 +286,8 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- Q_ASSERT(iter != d->type->d->names.end());
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ Q_ASSERT(iter != d->type->d->names.cend());
return d->getData(*iter);
}
@@ -299,10 +299,10 @@ QVariant &QQmlOpenMetaObject::operator[](int id)
bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
int id = -1;
- if (iter == d->type->d->names.end()) {
+ if (iter == d->type->d->names.cend()) {
id = createProperty(name.constData(), "") - d->type->d->propertyOffset;
} else {
id = *iter;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 800f650075..c1120b4542 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -55,6 +55,7 @@
#include <private/qmetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
+#include <cmath>
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<qreal>)
@@ -699,8 +700,7 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex());
+ return binding(that.d->object, that.d->core.encodedIndex());
}
/*!
@@ -716,65 +716,96 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
\a flags is passed through to the binding and is used for the initial update (when
the binding sets the initial value, it will use these flags for the write).
*/
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *newBinding,
- WriteFlags flags)
+void
+QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *newBinding)
{
+ if (!newBinding) {
+ removeBinding(that);
+ return;
+ }
+
if (!that.d || !that.isProperty() || !that.d->object) {
- if (newBinding)
- newBinding->destroy();
- return 0;
+ if (!newBinding->ref)
+ delete newBinding;
+ return;
}
+ setBinding(newBinding);
+}
+
+static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
+{
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- if (newBinding) {
- // In the case that the new binding is provided, we must target the property it
- // is associated with. If we don't do this, retargetBinding() can fail.
- QObject *object = newBinding->object();
- int pi = newBinding->propertyIndex();
+ QQmlData *data = QQmlData::get(object, false);
- int core;
- int vt = QQmlPropertyData::decodeValueTypePropertyIndex(pi, &core);
+ if (!data || !data->hasBindingBit(coreIndex))
+ return;
- return setBinding(object, core, vt, newBinding, flags);
- } else {
- return setBinding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex(),
- newBinding, flags);
- }
+ QQmlAbstractBinding::Ptr oldBinding;
+ oldBinding = data->bindings;
+
+ while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex)
+ oldBinding = oldBinding->nextBinding();
+
+ if (!oldBinding)
+ return;
+
+ if (valueTypeIndex != -1 && oldBinding->isValueTypeProxy())
+ oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
+
+ if (!oldBinding)
+ return;
+
+ if (!(flags & QQmlPropertyPrivate::DontEnable))
+ oldBinding->setEnabled(false, 0);
+ oldBinding->removeFromObject();
+}
+
+void QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b)
+{
+ removeBinding(b->targetObject(), b->targetPropertyIndex());
+}
+
+void QQmlPropertyPrivate::removeBinding(QObject *o, int index)
+{
+ Q_ASSERT(o);
+
+ QObject *target;
+ int targetIndex;
+ findAliasTarget(o, index, &target, &targetIndex);
+ removeOldBinding(target, targetIndex);
+}
+
+void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
+{
+ if (!that.d || !that.isProperty() || !that.d->object)
+ return;
+
+ removeBinding(that.d->object, that.d->core.encodedIndex());
}
QQmlAbstractBinding *
-QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
+QQmlPropertyPrivate::binding(QObject *object, int index)
{
QQmlData *data = QQmlData::get(object);
if (!data)
return 0;
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+ findAliasTarget(object, index, &object, &index);
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1)
- return 0;
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return binding(aObject, aCoreIndex, aValueTypeIndex);
- }
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
if (!data->hasBindingBit(coreIndex))
return 0;
QQmlAbstractBinding *binding = data->bindings;
- while (binding && binding->propertyIndex() != coreIndex)
+ while (binding && binding->targetPropertyIndex() != coreIndex)
binding = binding->nextBinding();
if (binding && valueTypeIndex != -1) {
- if (binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) {
+ if (binding->isValueTypeProxy()) {
int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex);
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
}
@@ -786,11 +817,11 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
QObject **targetObject, int *targetBindingIndex)
{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
-
QQmlData *data = QQmlData::get(object, false);
if (data) {
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
+
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
@@ -817,119 +848,30 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
*targetBindingIndex = bindingIndex;
}
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding, WriteFlags flags)
-{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
-
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
-
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBinding(aObject, aCoreIndex, aValueTypeIndex, newBinding, flags);
- }
- }
-
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
-
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
- }
-
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding) {
- binding->removeFromObject();
- binding->setEnabled(false, 0);
- }
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
-
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
-
- newBinding->addToObject();
- newBinding->setEnabled(true, flags);
- }
-
- return binding;
-}
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding)
+void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags)
{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
-
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
-
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
+ Q_ASSERT(binding);
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBindingNoEnable(aObject, aCoreIndex, aValueTypeIndex, newBinding);
- }
- }
+ QObject *object = binding->targetObject();
+ int index = binding->targetPropertyIndex();
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
-
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
+#ifndef QT_NO_DEBUG
+ int coreIndex;
+ QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ QQmlData *data = QQmlData::get(object, true);
+ if (data->propertyCache) {
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData && !propertyData->isAlias());
}
+#endif
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding)
- binding->removeFromObject();
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
-
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
+ removeOldBinding(object, index, flags);
- newBinding->addToObject();
- }
+ binding->addToObject();
+ if (!(flags & DontEnable))
+ binding->setEnabled(true, writeFlags);
- return binding;
}
/*!
@@ -946,9 +888,9 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
if (!data)
return 0;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
if (signalHandler)
@@ -959,48 +901,41 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- A reference to \a expr will be added by QML. Ownership of the return value
- reference is assumed by the caller.
+ A reference to \a expr will be added by QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
- QQmlBoundSignalExpression *expr)
+void QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *expr)
{
if (expr)
expr->addref();
- return QQmlPropertyPrivate::takeSignalExpression(that, expr);
+ QQmlPropertyPrivate::takeSignalExpression(that, expr);
}
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- Ownership of \a expr transfers to QML. Ownership of the return value
- reference is assumed by the caller.
+ Ownership of \a expr transfers to QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
+void QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *expr)
{
if (!(that.type() & QQmlProperty::SignalProperty)) {
if (expr)
expr->release();
- return 0;
+ return;
}
QQmlData *data = QQmlData::get(that.d->object, 0 != expr);
if (!data)
- return 0;
+ return;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
- if (signalHandler)
- return signalHandler->takeExpression(expr);
+ if (signalHandler) {
+ signalHandler->takeExpression(expr);
+ return;
+ }
if (expr) {
int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
@@ -1008,7 +943,6 @@ QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
expr->context()->engine);
signal->takeExpression(expr);
}
- return 0;
}
/*!
@@ -1125,7 +1059,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
}
// helper function to allow assignment / binding to QList<QUrl> properties.
-static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
+QVariant QQmlPropertyPrivate::resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
{
QList<QUrl> urls;
if (value.userType() == qMetaTypeId<QUrl>()) {
@@ -1138,16 +1072,22 @@ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *cont
urls = value.value<QList<QUrl> >();
} else if (value.userType() == qMetaTypeId<QStringList>()) {
QStringList urlStrings = value.value<QStringList>();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} else if (value.userType() == qMetaTypeId<QList<QString> >()) {
QList<QString> urlStrings = value.value<QList<QString> >();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} // note: QList<QByteArray> is not currently supported.
QList<QUrl> resolvedUrls;
- for (int i = 0; i < urls.size(); ++i) {
+ const int urlsSize = urls.size();
+ resolvedUrls.reserve(urlsSize);
+ for (int i = 0; i < urlsSize; ++i) {
QUrl u = urls.at(i);
if (context && u.isRelative() && !u.isEmpty())
u = context->resolvedUrl(u);
@@ -1210,12 +1150,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
QQmlContextData *context, WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & DontRemoveBinding) && object) {
- QQmlAbstractBinding *binding = setBinding(object, core.coreIndex,
- core.getValueTypeCoreIndex(),
- 0, flags);
- if (binding) binding->destroy();
- }
+ if (!(flags & DontRemoveBinding) && object)
+ removeBinding(object, core.encodedIndex());
bool rv = false;
if (core.isValueTypeVirtual()) {
@@ -1255,7 +1191,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
// Enum values come through the script engine as doubles
if (value.userType() == QVariant::Double) {
double integral;
- double fractional = modf(value.toDouble(), &integral);
+ double fractional = std::modf(value.toDouble(), &integral);
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
@@ -1475,166 +1411,6 @@ bool QQmlPropertyPrivate::write(QObject *object,
return true;
}
-// Returns true if successful, false if an error description was set on expression
-bool QQmlPropertyPrivate::writeBinding(QObject *object,
- const QQmlPropertyData &core,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags)
-{
- Q_ASSERT(object);
- Q_ASSERT(core.coreIndex != -1);
-
- QQmlEngine *engine = context->engine;
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
-
-#define QUICK_STORE(cpptype, conversion) \
- { \
- cpptype o = (conversion); \
- int status = -1; \
- void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(object, QMetaObject::WriteProperty, core.coreIndex, argv); \
- return true; \
- } \
-
-
- if (!isUndefined && !core.isValueTypeVirtual()) {
- switch (core.propType) {
- case QMetaType::Int:
- if (result.isInteger())
- QUICK_STORE(int, result.integerValue())
- else if (result.isNumber())
- QUICK_STORE(int, result.doubleValue())
- break;
- case QMetaType::Double:
- if (result.isNumber())
- QUICK_STORE(double, result.asDouble())
- break;
- case QMetaType::Float:
- if (result.isNumber())
- QUICK_STORE(float, result.asDouble())
- break;
- case QMetaType::QString:
- if (result.isString())
- QUICK_STORE(QString, result.toQStringNoThrow())
- break;
- default:
- if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == core.propType) {
- return vtw->write(object, core.coreIndex);
- }
- }
- break;
- }
- }
-#undef QUICK_STORE
-
- int type = core.isValueTypeVirtual()?core.valueTypePropType:core.propType;
-
- QQmlJavaScriptExpression::DeleteWatcher watcher(expression);
-
- QVariant value;
- bool isVarProperty = core.isVarProperty();
-
- if (isUndefined) {
- } else if (core.isQList()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
- } else if (result.isNull() && core.isQObject()) {
- value = QVariant::fromValue((QObject *)0);
- } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
- value = resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
- } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, type);
- }
-
- if (expression->hasError()) {
- return false;
- } else if (isVarProperty) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- // we explicitly disallow this case to avoid confusion. Users can still store one
- // in an array in a var property if they need to, but the common case is user error.
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmemo);
- vmemo->setVMEProperty(core.coreIndex, result);
- } else if (isUndefined && core.isResettable()) {
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args);
- } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- writeValueProperty(object, core, QVariant(), context, flags);
- } else if (type == qMetaTypeId<QJSValue>()) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
- writeValueProperty(object, core, QVariant::fromValue(
- QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
- context, flags);
- } else if (isUndefined) {
- QString errorStr = QLatin1String("Unable to assign [undefined] to ");
- if (!QMetaType::typeName(type))
- errorStr += QLatin1String("[unknown property type]");
- else
- errorStr += QLatin1String(QMetaType::typeName(type));
- expression->delayedError()->setErrorDescription(errorStr);
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (QV4::FunctionObject *f = result.asFunctionObject()) {
- if (f->isBinding())
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- else
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (!writeValueProperty(object, core, value, context, flags)) {
-
- if (watcher.wasDeleted())
- return true;
-
- const char *valueType = 0;
- const char *propertyType = 0;
-
- if (value.userType() == QMetaType::QObjectStar) {
- if (QObject *o = *(QObject *const *)value.constData()) {
- valueType = o->metaObject()->className();
-
- QQmlMetaObject propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
- if (!propertyMetaObject.isNull())
- propertyType = propertyMetaObject.className();
- }
- } else if (value.userType() != QVariant::Invalid) {
- if (value.userType() == QMetaType::VoidStar)
- valueType = "null";
- else
- valueType = QMetaType::typeName(value.userType());
- }
-
- if (!valueType)
- valueType = "undefined";
- if (!propertyType)
- propertyType = QMetaType::typeName(type);
- if (!propertyType)
- propertyType = "[unknown property type]";
-
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(propertyType));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- return true;
-}
-
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
{
QMetaType metaType(userType);
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 98e310ebce..51a1db7b90 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
+
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
@@ -103,15 +104,18 @@ public:
QQmlContextData *, WriteFlags flags = 0);
static void findAliasTarget(QObject *, int, QObject **, int *);
- static QQmlAbstractBinding *setBinding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
- static QQmlAbstractBinding *setBindingNoEnable(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *);
- static QQmlAbstractBinding *binding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */);
+ enum BindingFlag {
+ None = 0,
+ DontEnable = 0x1
+ };
+ Q_DECLARE_FLAGS(BindingFlags, BindingFlag)
+
+ static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding);
+
+ static void removeBinding(const QQmlProperty &that);
+ static void removeBinding(QObject *o, int index);
+ static void removeBinding(QQmlAbstractBinding *b);
+ static QQmlAbstractBinding *binding(QObject *, int index);
static QQmlPropertyData saveValueType(const QQmlPropertyData &,
const QMetaObject *, int,
@@ -128,20 +132,13 @@ public:
// "Public" (to QML) methods
static QQmlAbstractBinding *binding(const QQmlProperty &that);
- static QQmlAbstractBinding *setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
+ static void setBinding(const QQmlProperty &that, QQmlAbstractBinding *);
static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that);
- static QQmlBoundSignalExpressionPointer setSignalExpression(const QQmlProperty &that,
+ static void setSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
- static QQmlBoundSignalExpressionPointer takeSignalExpression(const QQmlProperty &that,
+ static void takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
- static bool writeBinding(QObject *, const QQmlPropertyData &,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags);
static int valueTypeCoreIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlPropertyData &that);
@@ -150,9 +147,12 @@ public:
const QObject *receiver, int method_index,
int type = 0, int *types = 0);
static void flushSignal(const QObject *sender, int signal_index);
+
+ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::WriteFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags)
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 0018275b95..cd8eb0d3e2 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -42,7 +42,7 @@
#include <private/qqmlaccessors_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qdebug.h>
@@ -837,7 +837,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
void QQmlPropertyCache::update(const QMetaObject *metaObject)
{
Q_ASSERT(metaObject);
- Q_ASSERT(stringCache.isEmpty());
+ stringCache.clear();
// Preallocate enough space in the index caches for all the properties/methods/signals that
// are not cached in a parent cache so that the caches never need to be reallocated as this
@@ -862,7 +862,6 @@ void QQmlPropertyCache::update(const QMetaObject *metaObject)
*/
void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
{
- stringCache.clear();
propertyIndexCache.clear();
methodIndexCache.clear();
signalHandlerIndexCache.clear();
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 6ed9ec0d36..4d8c6dd9a5 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -54,7 +54,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -174,7 +174,6 @@ public:
int propType; // When !NotFullyResolved
const char *propTypeName; // When NotFullyResolved
};
- int coreIndex;
union {
// The notify index is in the range returned by QObjectPrivate::signalIndex().
// This is different from QMetaMethod::methodIndex().
@@ -208,6 +207,7 @@ public:
qintptr accessorData;
};
};
+ int coreIndex;
private:
friend class QQmlPropertyData;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d713e9ee03..408f17ffde 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -81,7 +81,7 @@
#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false)
#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
-#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
+#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
#else
@@ -1612,6 +1612,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
} else {
QQmlTypeLoader::load(typeData, mode);
}
+ } else if ((mode == PreferSynchronous) && QQmlFile::isSynchronous(url)) {
+ // this was started Asynchronous, but we need to force Synchronous
+ // completion now (if at all possible with this type of URL).
+
+ if (!m_thread->isThisThread()) {
+ // this only works when called directly from the UI thread, but not
+ // when recursively called on the QML thread via resolveTypes()
+
+ while (!typeData->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
typeData->addref();
@@ -2114,6 +2128,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
+ errors.reserve(compiler.errors.count());
foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
QQmlError e;
e.setUrl(finalUrl());
@@ -2519,8 +2534,8 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
return QV4::PersistentValue();
}
- QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
- QV4::QmlContextWrapper::takeContextOwnership(qmlglobal);
+ QV4::Scoped<QV4::QmlContextWrapper> qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
+ qmlglobal->takeContextOwnership();
m_program->qml.set(scope.engine, qmlglobal);
m_program->run();
@@ -2594,7 +2609,7 @@ void QQmlScriptBlob::dataReceived(const Data &data)
return;
}
if (!unit) {
- unit.take(new EmptyCompilationUnit);
+ unit.adopt(new EmptyCompilationUnit);
}
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index d9ea273698..5be478fa65 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -60,7 +60,7 @@
#include <private/qflagpointer_p.h>
#include <private/qqmlirbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4script_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index d0658f2c3c..23cc12c895 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -125,7 +125,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons
const Import *i = static_cast<const Import *>(importNamespace);
Q_ASSERT(i->scriptIndex == -1);
- QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.find(i);
+ QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i);
if (it != m_namespacedImports.constEnd()) {
Result r = query(*it, name);
if (r.isValid())
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 8a2118ef27..1d72b2da0d 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -124,19 +124,19 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
}
-ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlTypeWrapper>());
- QV4::ExecutionEngine *v4 = static_cast<QmlTypeWrapper *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, static_cast<QmlTypeWrapper *>(m));
+ Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m));
if (hasProperty)
*hasProperty = true;
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QObject *object = w->d()->object;
@@ -240,7 +240,7 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scope scope(v4);
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QQmlType *type = w->d()->type;
if (type && !type->isSingleton() && w->d()->object) {
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 660d2836ff..14741a5bad 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpointer.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -94,7 +94,7 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static bool isEqualTo(Managed *that, Managed *o);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 10eaae0c77..6a71a07e9b 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -517,7 +517,9 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
if ((variantList.count() % 6) == 0) {
bool allRealsOk = true;
QList<qreal> reals;
- for (int i = 0; i < variantList.count(); i++) {
+ const int variantListCount = variantList.count();
+ reals.reserve(variantListCount);
+ for (int i = 0; i < variantListCount; i++) {
bool ok;
const qreal real = variantList.at(i).toReal(&ok);
reals.append(real);
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 2c02cc0aa1..abd73d7f35 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -209,7 +209,6 @@ struct QQmlEasingValueType
{
QEasingCurve v;
Q_GADGET
- Q_ENUMS(Type)
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude FINAL)
@@ -243,6 +242,7 @@ public:
SineCurve = QEasingCurve::SineCurve, CosineCurve = QEasingCurve::CosineCurve,
Bezier = QEasingCurve::BezierSpline
};
+ Q_ENUM(Type)
Type type() const;
qreal amplitude() const;
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index cfc9b196d2..3bc8493cbb 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -35,80 +35,42 @@
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlValueTypeProxyBinding>,
- QQmlAbstractBinding::default_expression,
- QQmlValueTypeProxyBinding::propertyIndex,
- QQmlValueTypeProxyBinding::object,
- QQmlValueTypeProxyBinding::setEnabled,
- QQmlValueTypeProxyBinding::update,
- QQmlAbstractBinding::default_retargetBinding
-};
-
QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index)
-: QQmlAbstractBinding(ValueTypeProxy), m_object(o), m_index(index), m_bindings(0)
+ : QQmlAbstractBinding(),
+ m_bindings(0)
{
+ m_target = o;
+ m_targetIndex = index;
}
QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding()
{
- QQmlAbstractBinding *binding = m_bindings;
- // This must be identical to the logic in QQmlData::destroyed()
+ QQmlAbstractBinding *binding = m_bindings.data();
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::setEnabled(QQmlAbstractBinding *_This,
- bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
- QQmlValueTypeProxyBinding *This = static_cast<QQmlValueTypeProxyBinding *>(_This);
-
- if (e) {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveEnable(bindings, flags);
- } else {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveDisable(bindings);
+ QQmlAbstractBinding *b = m_bindings.data();
+ while (b) {
+ b->setEnabled(e, flags);
+ b = b->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags)
-{
- if (!b)
- return;
-
- recursiveEnable(b->nextBinding(), flags);
-
- if (b)
- b->setEnabled(true, flags);
-}
-
-void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b)
-{
- if (!b)
- return;
-
- recursiveDisable(b->nextBinding());
-
- if (b)
- b->setEnabled(false, 0);
-}
-
-void QQmlValueTypeProxyBinding::update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags)
+bool QQmlValueTypeProxyBinding::isValueTypeProxy() const
{
+ return true;
}
QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
- while (binding && binding->propertyIndex() != propertyIndex)
+ while (binding && binding->targetPropertyIndex() != propertyIndex)
binding = binding->nextBinding();
return binding;
@@ -119,23 +81,20 @@ Removes a collection of bindings, corresponding to the set bits in \a mask.
*/
void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
QQmlAbstractBinding *lastBinding = 0;
while (binding) {
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->propertyIndex());
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex());
if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) {
QQmlAbstractBinding *remove = binding;
+ remove->setAddedToObject(false);
binding = remove->nextBinding();
if (lastBinding == 0)
m_bindings = remove->nextBinding();
else
lastBinding->setNextBinding(remove->nextBinding());
-
- remove->setAddedToObject(false);
- remove->setNextBinding(0);
- remove->destroy();
} else {
lastBinding = binding;
binding = binding->nextBinding();
@@ -143,24 +102,4 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
}
}
-int QQmlValueTypeProxyBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_object;
-}
-
-int QQmlValueTypeProxyBinding::propertyIndex() const
-{
- return m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object() const
-{
- return m_object;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index 873fbb4af1..4afadfc17d 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -54,30 +54,18 @@ class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
public:
QQmlValueTypeProxyBinding(QObject *o, int coreIndex);
- int propertyIndex() const;
- QObject *object() const;
-
- QQmlAbstractBinding *binding(int propertyIndex);
-
+ QQmlAbstractBinding *binding(int targetPropertyIndex);
void removeBindings(quint32 mask);
- // "Inherited" from QQmlAbstractBinding
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags);
+ virtual bool isValueTypeProxy() const;
protected:
~QQmlValueTypeProxyBinding();
private:
- void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void recursiveDisable(QQmlAbstractBinding *);
-
friend class QQmlAbstractBinding;
- QObject *m_object;
- int m_index;
- QQmlAbstractBinding *m_bindings;
+ Ptr m_bindings;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index e87d9ede77..b0ab85199d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -43,7 +43,6 @@
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4variantobject_p.h>
-#include <private/qv4qmlextensions_p.h>
#include <private/qv4alloca_p.h>
QT_BEGIN_NAMESPACE
@@ -165,13 +164,13 @@ bool QQmlValueTypeReference::readReferenceValue() const
void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
- if (v4->qmlExtensions()->valueTypeWrapperPrototype)
+ if (v4->valueTypeWrapperPrototype()->as<Object>())
return;
Scope scope(v4);
ScopedObject o(scope, v4->newObject());
- o->defineDefaultProperty(v4->id_toString, method_toString, 1);
- v4->qmlExtensions()->valueTypeWrapperPrototype = o->d();
+ o->defineDefaultProperty(v4->id_toString(), method_toString, 1);
+ v4->jsObjects[QV4::ExecutionEngine::ValueTypeProto] = o->d();
}
ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *object, int property, const QMetaObject *metaObject, int typeId)
@@ -180,7 +179,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
initProto(engine);
Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
r->setPrototype(proto);
r->d()->object = object; r->d()->property = property;
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
@@ -195,7 +194,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
initProto(engine);
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
r->setPrototype(proto);
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
@@ -292,7 +291,7 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
{
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>();
@@ -327,14 +326,14 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
return Encode(ctx->engine()->newString(result));
}
-ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
- QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = r->engine();
// Note: readReferenceValue() can change the reference->type.
- if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
if (!reference->readReferenceValue())
return Primitive::undefinedValue().asReturnedValue();
}
@@ -410,45 +409,41 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QMetaProperty property = metaObject->property(pd->coreIndex);
Q_ASSERT(property.isValid());
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (reference && f) {
- if (!f->isBinding()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
- ScopedString e(scope, v4->newString(error));
- v4->throwError(e);
- return;
- }
+ if (reference) {
+ QV4::ScopedFunctionObject f(scope, value);
+ if (f) {
+ if (!f->isBinding()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ ScopedString e(scope, v4->newString(error));
+ v4->throwError(e);
+ return;
+ }
- QQmlContextData *context = QmlContextWrapper::callingContext(v4);
+ QQmlContextData *context = v4->callingQmlContext();
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = writeBackPropertyType;
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ QQmlBinding *newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData);
+ QQmlPropertyPrivate::setBinding(newBinding);
+ return;
+ } else {
+ QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex));
- if (reference) {
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ }
}
- if (newBinding)
- return;
QVariant v = v4->toVariant(value, property.userType());
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index cad48e661c..5f0edfb71d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -89,7 +89,7 @@ public:
int typeId() const;
bool write(QObject *target, int propertyIndex) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 97fc382c33..9f02c905fc 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -104,13 +104,11 @@ public:
inline double asDouble();
inline const QString &asQString();
inline const QUrl &asQUrl();
- inline const QTime &asQTime();
inline const QDate &asQDate();
inline const QDateTime &asQDateTime();
inline const QRectF &asQRectF();
inline const QPointF &asQPointF();
inline const QSizeF &asQSizeF();
- inline const QJSValue &asQJSValue();
inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
inline void setValue(const QVariant &);
@@ -125,9 +123,6 @@ public:
inline void setValue(const QRectF &);
inline void setValue(const QPointF &);
inline void setValue(const QSizeF &);
- inline void setValue(const QJSValue &);
-
- inline void setDataType(int t);
inline void ensureValueType(int);
@@ -196,9 +191,6 @@ void QQmlVMEVariant::cleanup()
} else if (type == qMetaTypeId<QVariant>()) {
((QVariant *)dataPtr())->~QVariant();
type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QJSValue>()) {
- ((QJSValue *)dataPtr())->~QJSValue();
- type = QVariant::Invalid;
} else {
if (QQml_valueTypeProvider()->destroyValueType(type, dataPtr(), dataSize())) {
type = QVariant::Invalid;
@@ -282,14 +274,6 @@ const QUrl &QQmlVMEVariant::asQUrl()
return *(QUrl *)(dataPtr());
}
-const QTime &QQmlVMEVariant::asQTime()
-{
- if (type != QMetaType::QTime)
- setValue(QTime());
-
- return *(QTime *)(dataPtr());
-}
-
const QDate &QQmlVMEVariant::asQDate()
{
if (type != QMetaType::QDate)
@@ -330,14 +314,6 @@ const QPointF &QQmlVMEVariant::asQPointF()
return *(QPointF *)(dataPtr());
}
-const QJSValue &QQmlVMEVariant::asQJSValue()
-{
- if (type != qMetaTypeId<QJSValue>())
- setValue(QJSValue());
-
- return *(QJSValue *)(dataPtr());
-}
-
void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index)
{
if (type != QMetaType::QObjectStar) {
@@ -474,22 +450,6 @@ void QQmlVMEVariant::setValue(const QSizeF &v)
}
}
-void QQmlVMEVariant::setValue(const QJSValue &v)
-{
- if (type != qMetaTypeId<QJSValue>()) {
- cleanup();
- type = qMetaTypeId<QJSValue>();
- new (dataPtr()) QJSValue(v);
- } else {
- *(QJSValue *)(dataPtr()) = v;
- }
-}
-
-void QQmlVMEVariant::setDataType(int t)
-{
- type = t;
-}
-
void QQmlVMEVariant::ensureValueType(int t)
{
if (type != t) {
@@ -500,8 +460,8 @@ void QQmlVMEVariant::ensureValueType(int t)
}
QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
{
- setCallback(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint);
}
void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
@@ -874,10 +834,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int flags = *reinterpret_cast<int*>(a[3]);
if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
- if (targetData && targetData->hasBindingBit(d->propertyIndex())) {
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0);
- if (binding) binding->destroy();
- }
+ if (targetData && targetData->hasBindingBit(d->propertyIndex()))
+ QQmlPropertyPrivate::removeBinding(target, d->propertyIdx);
}
}
@@ -1183,7 +1141,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
v8methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex].set(function.asObject()->engine(), function);
+ v8methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1220,8 +1178,9 @@ bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
void QQmlVMEMetaObject::ensureQObjectWrapper()
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ Q_ASSERT(ctxt && ctxt->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(ctxt->engine);
+ QV4::ExecutionEngine *v4 = ep->v4engine();
QV4::QObjectWrapper::wrap(v4, object);
}
@@ -1251,7 +1210,7 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
void QQmlVMEMetaObject::allocateVarPropertiesArray()
{
QQmlEngine *qml = qmlEngine(object);
- assert(qml);
+ Q_ASSERT(qml);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
QV4::Scope scope(v4);
varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index f3048d426a..a320163f23 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -63,7 +63,7 @@
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlwatcher.cpp b/src/qml/qml/qqmlwatcher.cpp
deleted file mode 100644
index 9726b6f3b9..0000000000
--- a/src/qml/qml/qqmlwatcher.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlwatcher_p.h"
-
-#include "qqmlexpression.h"
-#include "qqmlcontext.h"
-#include "qqml.h"
-
-#include <private/qqmldebugservice_p.h>
-#include "qqmlproperty_p.h"
-#include "qqmlvaluetype_p.h"
-
-#include <QtCore/qmetaobject.h>
-#include <QtCore/qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlWatchProxy : public QObject
-{
- Q_OBJECT
-public:
- QQmlWatchProxy(int id,
- QObject *object,
- int debugId,
- const QMetaProperty &prop,
- QQmlWatcher *parent = 0);
-
- QQmlWatchProxy(int id,
- QQmlExpression *exp,
- int debugId,
- QQmlWatcher *parent = 0);
-
-public slots:
- void notifyValueChanged();
-
-private:
- friend class QQmlWatcher;
- int m_id;
- QQmlWatcher *m_watch;
- QObject *m_object;
- int m_debugId;
- QMetaProperty m_property;
-
- QQmlExpression *m_expr;
-};
-
-QQmlWatchProxy::QQmlWatchProxy(int id,
- QQmlExpression *exp,
- int debugId,
- QQmlWatcher *parent)
-: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
-{
- QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged()));
-}
-
-QQmlWatchProxy::QQmlWatchProxy(int id,
- QObject *object,
- int debugId,
- const QMetaProperty &prop,
- QQmlWatcher *parent)
-: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(0)
-{
- static int refreshIdx = -1;
- if(refreshIdx == -1)
- refreshIdx = QQmlWatchProxy::staticMetaObject.indexOfMethod("notifyValueChanged()");
-
- if (prop.hasNotifySignal())
- QQmlPropertyPrivate::connect(m_object, prop.notifySignalIndex(), this, refreshIdx);
-}
-
-void QQmlWatchProxy::notifyValueChanged()
-{
- QVariant v;
- if (m_expr)
- v = m_expr->evaluate();
- else if (QQmlValueTypeFactory::isValueType(m_property.userType()))
- v = m_property.read(m_object);
-
- emit m_watch->propertyChanged(m_id, m_debugId, m_property, v);
-}
-
-
-QQmlWatcher::QQmlWatcher(QObject *parent)
- : QObject(parent)
-{
-}
-
-bool QQmlWatcher::addWatch(int id, quint32 debugId)
-{
- QObject *object = QQmlDebugService::objectForId(debugId);
- if (object) {
- int propCount = object->metaObject()->propertyCount();
- for (int ii=0; ii<propCount; ii++)
- addPropertyWatch(id, object, debugId, object->metaObject()->property(ii));
- return true;
- }
- return false;
-}
-
-bool QQmlWatcher::addWatch(int id, quint32 debugId, const QByteArray &property)
-{
- QObject *object = QQmlDebugService::objectForId(debugId);
- if (object) {
- int index = object->metaObject()->indexOfProperty(property.constData());
- if (index >= 0) {
- addPropertyWatch(id, object, debugId, object->metaObject()->property(index));
- return true;
- }
- }
- return false;
-}
-
-bool QQmlWatcher::addWatch(int id, quint32 objectId, const QString &expr)
-{
- QObject *object = QQmlDebugService::objectForId(objectId);
- QQmlContext *context = qmlContext(object);
- if (context) {
- QQmlExpression *exprObj = new QQmlExpression(context, object, expr);
- exprObj->setNotifyOnValueChanged(true);
- QQmlWatchProxy *proxy = new QQmlWatchProxy(id, exprObj, objectId, this);
- exprObj->setParent(proxy);
- m_proxies[id].append(proxy);
- proxy->notifyValueChanged();
- return true;
- }
- return false;
-}
-
-bool QQmlWatcher::removeWatch(int id)
-{
- if (!m_proxies.contains(id))
- return false;
-
- QList<QPointer<QQmlWatchProxy> > proxies = m_proxies.take(id);
- qDeleteAll(proxies);
- return true;
-}
-
-void QQmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property)
-{
- QQmlWatchProxy *proxy = new QQmlWatchProxy(id, object, debugId, property, this);
- m_proxies[id].append(proxy);
-
- proxy->notifyValueChanged();
-}
-
-QT_END_NAMESPACE
-
-#include <qqmlwatcher.moc>
diff --git a/src/qml/qml/qqmlwatcher_p.h b/src/qml/qml/qqmlwatcher_p.h
deleted file mode 100644
index a7bb3c3418..0000000000
--- a/src/qml/qml/qqmlwatcher_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLWATCHER_P_H
-#define QQMLWATCHER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qobject.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qpair.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qset.h>
-#include <QtCore/qpointer.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlWatchProxy;
-class QQmlExpression;
-class QQmlContext;
-class QMetaProperty;
-
-class QQmlWatcher : public QObject
-{
- Q_OBJECT
-public:
- QQmlWatcher(QObject * = 0);
-
- bool addWatch(int id, quint32 objectId);
- bool addWatch(int id, quint32 objectId, const QByteArray &property);
- bool addWatch(int id, quint32 objectId, const QString &expr);
-
- bool removeWatch(int id);
-
-Q_SIGNALS:
- void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
-
-private:
- friend class QQmlWatchProxy;
- void addPropertyWatch(int id, QObject *object, quint32 objectId, const QMetaProperty &property);
-
- QHash<int, QList<QPointer<QQmlWatchProxy> > > m_proxies;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLWATCHER_P_H
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 2a3ede6a22..0edb672517 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -60,6 +60,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4arraybuffer_p.h>
+#include <private/qv4jsonobject_p.h>
using namespace QV4;
@@ -99,7 +100,7 @@ static ReturnedValue constructMeObject(const Value &thisObj, ExecutionEngine *v4
Scope scope(v4);
ScopedObject meObj(scope, v4->newObject());
meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
- ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->v8Engine->callingContext(), 0));
+ ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->callingQmlContext(), 0));
meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
return meObj.asReturnedValue();
}
@@ -222,8 +223,8 @@ public:
static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
@@ -244,8 +245,8 @@ public:
V4_NEEDS_DESTROY
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
// C++ API
static ReturnedValue create(ExecutionEngine *, NodeImpl *);
@@ -273,6 +274,7 @@ public:
static ReturnedValue method_get_nodeName(CallContext *ctx);
static ReturnedValue method_get_nodeValue(CallContext *ctx);
static ReturnedValue method_get_nodeType(CallContext *ctx);
+ static ReturnedValue method_get_namespaceUri(CallContext *ctx);
static ReturnedValue method_get_parentNode(CallContext *ctx);
static ReturnedValue method_get_childNodes(CallContext *ctx);
@@ -302,6 +304,7 @@ Heap::NodePrototype::NodePrototype(ExecutionEngine *engine)
o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0);
o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, 0);
o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, 0);
+ o->defineAccessorProperty(QStringLiteral("namespaceUri"), QV4::NodePrototype::method_get_namespaceUri, 0);
o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, 0);
o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, 0);
@@ -470,6 +473,16 @@ ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
return Encode(r->d()->d->type);
}
+ReturnedValue NodePrototype::method_get_namespaceUri(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ if (!r)
+ return ctx->engine()->throwTypeError();
+
+ return Encode(ctx->d()->engine->newString(r->d()->d->namespaceUri));
+}
+
ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
{
Scope scope(ctx);
@@ -871,10 +884,10 @@ bool Node::isNull() const
return d()->d == 0;
}
-ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->list.count()) {
@@ -887,14 +900,14 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
QString str = name->toQString();
@@ -916,10 +929,10 @@ ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QL
return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
}
-ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->d->children.count()) {
@@ -932,15 +945,15 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
return Object::get(m, name, hasProperty);
}
@@ -1019,13 +1032,15 @@ public:
QString header(const QString &name);
QString headers();
-
QString responseBody();
const QByteArray & rawResponseBody() const;
bool receivedXml() const;
const QString & responseType() const;
void setResponseType(const QString &);
+
+ QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
+ QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine*);
private slots:
void readyRead();
void error(QNetworkReply::NetworkError);
@@ -1076,6 +1091,7 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
QString m_responseType;
+ QV4::PersistentValue m_parsedDocument;
};
QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
@@ -1083,6 +1099,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessMa
, m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
, m_responseType()
+ , m_parsedDocument()
{
}
@@ -1233,11 +1250,12 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
m_network = networkAccessManager()->put(request, m_data);
} else if (m_method == QLatin1String("DELETE")) {
m_network = networkAccessManager()->deleteResource(request);
- } else if (m_method == QLatin1String("OPTIONS")) {
+ } else if ((m_method == QLatin1String("OPTIONS")) ||
+ m_method == QLatin1String("PROPFIND")) {
QBuffer *buffer = new QBuffer;
buffer->setData(m_data);
buffer->open(QIODevice::ReadOnly);
- m_network = networkAccessManager()->sendCustomRequest(request, QByteArrayLiteral("OPTIONS"), buffer);
+ m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
buffer->setParent(m_network);
}
@@ -1478,6 +1496,32 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType)
m_responseType = responseType;
}
+QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.isEmpty()) {
+ Scope scope(engine);
+
+ QJsonParseError error;
+ const QString& jtext = responseBody();
+ JsonParser parser(scope.engine, jtext.constData(), jtext.length());
+ ScopedValue jsonObject(scope, parser.parse(&error));
+ if (error.error != QJsonParseError::NoError)
+ return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
+
+ m_parsedDocument.set(scope.engine, jsonObject);
+ }
+
+ return m_parsedDocument.value();
+}
+
+QV4::ReturnedValue QQmlXMLHttpRequest::xmlResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.isEmpty()) {
+ m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
+ }
+
+ return m_parsedDocument.value();
+}
#ifndef QT_NO_TEXTCODEC
QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
@@ -1599,7 +1643,7 @@ struct QQmlXMLHttpRequestWrapper : Object {
struct QQmlXMLHttpRequestCtor : FunctionObject {
QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
- Object *proto;
+ Pointer<Object> proto;
};
}
@@ -1625,9 +1669,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
- static ReturnedValue construct(Managed *that, QV4::CallData *)
+ static ReturnedValue construct(const Managed *that, QV4::CallData *)
{
- Scope scope(static_cast<QQmlXMLHttpRequestCtor *>(that)->engine());
+ Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
if (!ctor)
return scope.engine->throwTypeError();
@@ -1639,7 +1683,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
return w.asReturnedValue();
}
- static ReturnedValue call(Managed *, QV4::CallData *) {
+ static ReturnedValue call(const Managed *, QV4::CallData *) {
return Primitive::undefinedValue().asReturnedValue();
}
@@ -1679,7 +1723,7 @@ Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
if (!ctor->d()->proto)
ctor->setupProto();
- ScopedString s(scope, engine->id_prototype);
+ ScopedString s(scope, engine->id_prototype());
ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
}
@@ -1739,14 +1783,15 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
method != QLatin1String("DELETE") &&
- method != QLatin1String("OPTIONS"))
+ method != QLatin1String("OPTIONS") &&
+ method != QLatin1String("PROPFIND"))
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
QUrl url = QUrl(ctx->args()[1].toQStringNoThrow());
if (url.isRelative())
- url = scope.engine->v8Engine->callingContext()->resolvedUrl(url);
+ url = scope.engine->callingQmlContext()->resolvedUrl(url);
bool async = true;
// Argument 2 - async (optional)
@@ -1965,7 +2010,9 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::Done)) {
return Encode::null();
} else {
- return Document::load(scope.engine, r->rawResponseBody());
+ if (r->responseType().isEmpty())
+ r->setResponseType(QLatin1String("document"));
+ return r->xmlResponseBody(scope.engine);
}
}
@@ -1986,6 +2033,10 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx)
return QV4::Encode(scope.engine->newString(r->responseBody()));
} else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody()));
+ } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
+ return r->jsonResponseBody(scope.engine);
+ } else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
+ return r->xmlResponseBody(scope.engine);
} else {
return QV4::Encode(scope.engine->newString(QString()));
}
@@ -2033,7 +2084,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
- v4->globalObject()->defineReadonlyProperty(s, ctor);
+ v4->globalObject->defineReadonlyProperty(s, ctor);
QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData;
return data;
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f53b9a0c7d..ce86fd3923 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -41,7 +41,8 @@
#include <private/qv8engine_p.h>
#include <QFileInfo>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlplatform_p.h>
@@ -51,6 +52,7 @@
#include <private/qv4include_p.h>
#include <private/qv4context_p.h>
#include <private/qv4stringobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4objectproto_p.h>
@@ -669,7 +671,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1);
QTime time;
- if (ctx->args()[0].asDateObject() || (argVariant.type() == QVariant::String))
+ if (ctx->args()[0].as<DateObject>() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
@@ -839,21 +841,21 @@ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
*/
ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ ExecutionEngine *v4 = ctx->engine();
- QUrl url = ctx->engine()->toVariant(ctx->args()[0], -1).toUrl();
- QQmlEngine *e = v8engine->engine();
+ QUrl url = v4->toVariant(ctx->args()[0], -1).toUrl();
+ QQmlEngine *e = v4->qmlEngine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
- QQmlContextData *ctxt = v8engine->callingContext();
+ QQmlContextData *ctxt = v4->callingQmlContext();
if (ctxt)
- return ctx->d()->engine->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
+ return v4->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
else
- return ctx->d()->engine->newString(url.toString())->asReturnedValue();
+ return v4->newString(url.toString())->asReturnedValue();
}
- return ctx->d()->engine->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
+ return v4->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
}
/*!
@@ -983,7 +985,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContext *effectiveContext = 0;
if (context->isPragmaLibraryContext)
@@ -1090,7 +1092,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContextData *effectiveContext = context;
if (context->isPragmaLibraryContext)
@@ -1178,7 +1180,7 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
return QQmlLocale::locale(ctx->engine(), code);
}
-Heap::QQmlBindingFunction::QQmlBindingFunction(QV4::FunctionObject *originalFunction)
+Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction)
: QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
, originalFunction(originalFunction->d())
{
@@ -1191,10 +1193,10 @@ void QQmlBindingFunction::initBindingLocation()
d()->bindingLocation.line = frame.line;
}
-ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData)
+ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<QQmlBindingFunction*>(that)->engine());
- ScopedFunctionObject function(scope, static_cast<QQmlBindingFunction*>(that)->d()->originalFunction);
+ Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine());
+ ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction);
return function->call(callData);
}
@@ -1256,7 +1258,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
{
if (ctx->argc() != 1)
V4THROW_ERROR("binding() requires 1 argument");
- QV4::FunctionObject *f = ctx->args()[0].asFunctionObject();
+ const QV4::FunctionObject *f = ctx->args()[0].as<FunctionObject>();
if (!f)
V4THROW_TYPE("binding(): argument (binding expression) must be a function");
@@ -1267,7 +1269,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
ReturnedValue QtObject::method_get_platform(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1284,7 +1286,7 @@ ReturnedValue QtObject::method_get_platform(CallContext *ctx)
ReturnedValue QtObject::method_get_application(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1353,12 +1355,12 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
QString stackFrame;
if (frame.column >= 0)
- stackFrame = QString::fromLatin1("%1 (%2:%3:%4)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3:%4)").arg(frame.function,
frame.source,
QString::number(frame.line),
QString::number(frame.column));
else
- stackFrame = QString::fromLatin1("%1 (%2:%3)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3)").arg(frame.function,
frame.source,
QString::number(frame.line));
@@ -1379,7 +1381,7 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
if (i != 0)
result.append(QLatin1Char(' '));
- if (ctx->args()[i].asArrayObject())
+ if (ctx->args()[i].as<ArrayObject>())
result.append(QStringLiteral("[") + ctx->args()[i].toQStringNoThrow() + QStringLiteral("]"));
else
result.append(ctx->args()[i].toQStringNoThrow());
@@ -1446,10 +1448,11 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
} else {
- QQmlProfilerService::instance()->startProfiling(v4->qmlEngine());
+ service->startProfiling(v4->qmlEngine());
logger.debug("Profiling started.");
}
@@ -1465,10 +1468,11 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- QQmlProfilerService::instance()->stopProfiling(v4->qmlEngine());
+ service->stopProfiling(v4->qmlEngine());
logger.debug("Profiling ended.");
}
@@ -1612,7 +1616,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
// string prototype extension
- v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
+ v4->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
}
@@ -1726,9 +1730,8 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
V4THROW_ERROR("qsTr(): third argument (n) must be a number");
Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QString context;
- if (QQmlContextData *ctxt = v8engine->callingContext()) {
+ if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index b78375118b..bdd53fe601 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -68,8 +68,8 @@ struct ConsoleObject : Object {
};
struct QQmlBindingFunction : FunctionObject {
- QQmlBindingFunction(QV4::FunctionObject *originalFunction);
- FunctionObject *originalFunction;
+ QQmlBindingFunction(const QV4::FunctionObject *originalFunction);
+ Pointer<FunctionObject> originalFunction;
// Set when the binding is created later
QQmlSourceLocation bindingLocation;
};
@@ -166,7 +166,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject
void initBindingLocation(); // from caller stack trace
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp
index c318e2e550..1baaa113aa 100644
--- a/src/qml/qml/v8/qv4domerrors.cpp
+++ b/src/qml/qml/v8/qv4domerrors.cpp
@@ -59,7 +59,7 @@ void qt_add_domexceptions(ExecutionEngine *e)
domexception->defineReadonlyProperty(QStringLiteral("INVALID_ACCESS_ERR"), Primitive::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR));
domexception->defineReadonlyProperty(QStringLiteral("VALIDATION_ERR"), Primitive::fromInt32(DOMEXCEPTION_VALIDATION_ERR));
domexception->defineReadonlyProperty(QStringLiteral("TYPE_MISMATCH_ERR"), Primitive::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR));
- e->globalObject()->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
+ e->globalObject->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp
index b7a5b71540..c61e57560d 100644
--- a/src/qml/qml/v8/qv4sqlerrors.cpp
+++ b/src/qml/qml/v8/qv4sqlerrors.cpp
@@ -51,7 +51,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
sqlexception->defineReadonlyProperty(QStringLiteral("SYNTAX_ERR"), Primitive::fromInt32(SQLEXCEPTION_SYNTAX_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("CONSTRAINT_ERR"), Primitive::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("TIMEOUT_ERR"), Primitive::fromInt32(SQLEXCEPTION_TIMEOUT_ERR));
- engine->globalObject()->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
+ engine->globalObject->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index a7c63c9df1..6cb316ce9f 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -61,7 +61,7 @@
#include <QtCore/qdatastream.h>
#include <private/qsimd_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4mm_p.h>
@@ -171,15 +171,10 @@ const QSet<QString> &QV8Engine::illegalNames() const
return m_illegalNames;
}
-QQmlContextData *QV8Engine::callingContext()
-{
- return QV4::QmlContextWrapper::callingContext(m_v4Engine);
-}
-
void QV8Engine::initializeGlobal()
{
QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject());
+ QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject);
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
@@ -191,9 +186,9 @@ void QV8Engine::initializeGlobal()
qt_add_sqlexceptions(m_v4Engine);
{
- for (uint i = 0; i < m_v4Engine->globalObject()->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject()->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject()->internalClass()->nameMap.at(i)->string);
+ for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
+ m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
}
}
@@ -229,7 +224,7 @@ void QV8Engine::freezeObject(const QV4::Value &value)
QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject();
+ callData->thisObject = m_v4Engine->globalObject;
f->call(callData);
}
@@ -266,9 +261,7 @@ void QV8Engine::setExtensionData(int index, Deletable *data)
void QV8Engine::initQmlGlobalObject()
{
initializeGlobal();
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedValue v(scope, m_v4Engine->globalObject());
- freezeObject(v);
+ freezeObject(*m_v4Engine->globalObject);
}
void QV8Engine::setEngine(QQmlEngine *engine)
@@ -279,7 +272,7 @@ void QV8Engine::setEngine(QQmlEngine *engine)
QV4::ReturnedValue QV8Engine::global()
{
- return m_v4Engine->globalObject()->asReturnedValue();
+ return m_v4Engine->globalObject->asReturnedValue();
}
void QV8Engine::startTimer(const QString &timerName)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index fb538772d1..5d12244dcb 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -60,7 +60,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qv4identifier_p.h>
@@ -101,19 +101,19 @@ namespace QV4 {
return rv; \
} \
-// Used to allow a QObject method take and return raw V8 handles without having to expose
-// v8 in the public API.
+// Used to allow a QObject method take and return raw V4 handles without having to expose
+// 48 in the public API.
// Use like this:
// class MyClass : public QObject {
// Q_OBJECT
// ...
-// Q_INVOKABLE void myMethod(QQmlV8Function*);
+// Q_INVOKABLE void myMethod(QQmlV4Function*);
// };
// The QQmlV8Function - and consequently the arguments and return value - only remains
// valid during the call. If the return value isn't set within myMethod(), the will return
// undefined.
class QV8Engine;
-// ### GC
+
class QQmlV4Function
{
public:
@@ -133,7 +133,7 @@ private:
const QV4::Value &global, QQmlContextData *c, QV4::ExecutionEngine *e)
: callData(callData), retVal(retVal), ctx(c), e(e)
{
- callData->thisObject.val = global.asReturnedValue();
+ callData->thisObject = QV4::Value::fromReturnedValue(global.asReturnedValue());
}
QV4::CallData *callData;
@@ -163,8 +163,6 @@ class QQmlContextData;
class Q_QML_PRIVATE_EXPORT QV8Engine
{
friend class QJSEngine;
- // ### GC
- typedef QSet<QV4::Heap::Object *> V8ObjectSet;
public:
static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
@@ -192,8 +190,6 @@ public:
Deletable *listModelData() { return m_listModelData; }
void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
- QQmlContextData *callingContext();
-
void freezeObject(const QV4::Value &value);
// Return the network access manager for this engine. By default this returns the network
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 7814fa6d56..a154da8323 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -52,8 +52,8 @@ QT_BEGIN_NAMESPACE
class QQmlBindPrivate : public QObjectPrivate
{
public:
- QQmlBindPrivate() : componentComplete(true), obj(0), prevBind(0) {}
- ~QQmlBindPrivate() { if (prevBind) prevBind->destroy(); }
+ QQmlBindPrivate() : componentComplete(true), obj(0) {}
+ ~QQmlBindPrivate() { }
QQmlNullableValue<bool> when;
bool componentComplete;
@@ -61,7 +61,7 @@ public:
QString propName;
QQmlNullableValue<QVariant> value;
QQmlProperty prop;
- QQmlAbstractBinding *prevBind;
+ QQmlAbstractBinding::Ptr prevBind;
};
@@ -70,65 +70,56 @@ public:
\instantiates QQmlBind
\inqmlmodule QtQml
\ingroup qtquick-interceptors
- \brief Enables the arbitrary creation of property bindings
+ \brief Enables the arbitrary creation of property bindings.
- \section1 Binding to an Inaccessible Property
+ In QML, property bindings result in a dependency between the properties of
+ different objects.
- Sometimes it is necessary to bind to a property of an object that wasn't
- directly instantiated by QML - generally a property of a class exported
- to QML by C++. In these cases, regular property binding doesn't work. Binding
- allows you to bind any value to any property.
+ \section1 Binding to an inaccessible property
+
+ Sometimes it is necessary to bind an object's property to
+ that of another object that isn't directly instantiated by QML, such as a
+ property of a class exported to QML by C++. You can use the Binding type
+ to establish this dependency; binding any value to any object's property.
+
+ For example, in a C++ application that maps an "app.enteredText" property
+ into QML, you can use Binding to update the enteredText property.
- For example, imagine a C++ application that maps an "app.enteredText"
- property into QML. You could use Binding to update the enteredText property
- like this.
\code
TextEdit { id: myTextField; text: "Please type here..." }
Binding { target: app; property: "enteredText"; value: myTextField.text }
\endcode
- Whenever the text in the TextEdit is updated, the C++ property will be
- updated also.
- \section1 "Single-branch" conditional binding
+ When \c{text} changes, the C++ property \c{enteredText} will update
+ automatically.
- In some circumstances you may want to control the value of a property
- only when a certain condition is true (and relinquish control in all
- other circumstances). This often isn't possible to accomplish with a direct
- binding, as you need to supply values for all possible branches.
+ \section1 Conditional bindings
- \code
+ In some cases you may want to modify the value of a property when a certain
+ condition is met but leave it unmodified otherwise. Often, it's not possible
+ to do this with direct bindings, as you have to supply values for all
+ possible branches.
+
+ For example, the code snippet below results in a warning whenever you
+ release the mouse. This is because the value of the binding is undefined
+ when the mouse isn't pressed.
+
+ \qml
// produces warning: "Unable to assign [undefined] to double value"
value: if (mouse.pressed) mouse.mouseX
- \endcode
+ \endqml
- The above example will produce a warning whenever we release the mouse, as the value
- of the binding is undefined when the mouse isn't pressed. We can use the Binding
- type to rewrite the above code and avoid the warning.
+ The Binding type can prevent this warning.
- \code
+ \qml
Binding on value {
when: mouse.pressed
value: mouse.mouseX
}
- \endcode
-
- The Binding type will also restore any previously set direct bindings on
- the property. In that sense, it functions much like a simplified State.
-
- \qml
- // this is equivalent to the above Binding
- State {
- name: "pressed"
- when: mouse.pressed
- PropertyChanges {
- target: obj
- value: mouse.mouseX
- }
- }
\endqml
- If the binding target or binding property is changed, the bound value is
- immediately pushed onto the new target.
+ The Binding type restores any previously set direct bindings on the
+ property.
\sa {Qt QML}
*/
@@ -277,22 +268,17 @@ void QQmlBind::eval()
if (!d->when) {
//restore any previous binding
if (d->prevBind) {
- QQmlAbstractBinding *tmp = d->prevBind;
+ QQmlAbstractBinding::Ptr p = d->prevBind;
d->prevBind = 0;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp);
- if (tmp) //should this ever be true?
- tmp->destroy();
+ QQmlPropertyPrivate::setBinding(p.data());
}
return;
}
//save any set binding for restoration
- QQmlAbstractBinding *tmp;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, 0);
- if (tmp && d->prevBind)
- tmp->destroy();
- else if (!d->prevBind)
- d->prevBind = tmp;
+ if (!d->prevBind)
+ d->prevBind = QQmlPropertyPrivate::binding(d->prop);
+ QQmlPropertyPrivate::removeBinding(d->prop);
}
d->prop.write(d->value.value);
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 0c81855e49..6a93410ecb 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -165,7 +165,7 @@ void QQmlConnections::setTarget(QObject *obj)
foreach (QQmlBoundSignal *s, d->boundsignals) {
// It is possible that target is being changed due to one of our signal
// handlers -> use deleteLater().
- if (s->isEvaluating())
+ if (s->isNotifying())
(new QQmlBoundSignalDeleter(s))->deleteLater();
else
delete s;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 201fd4572c..bc70e68904 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -44,7 +44,7 @@
#include <private/qqmlincubator_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <qv4objectiterator_p.h>
@@ -86,16 +86,11 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
}
- static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
+ static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData)
{
- return static_cast<DelegateModelGroupFunction *>(m)->engine()->throwTypeError();
- }
-
- static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData)
- {
- QV4::ExecutionEngine *v4 = static_cast<DelegateModelGroupFunction *>(that)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const DelegateModelGroupFunction *>(that)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<DelegateModelGroupFunction *>(that));
+ QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject);
if (!o)
return v4->throwTypeError(QStringLiteral("Not a valid VisualData object"));
@@ -1062,7 +1057,7 @@ int QQmlDelegateModel::indexOf(QObject *item, QObject *) const
return -1;
}
-void QQmlDelegateModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlDelegateModel::setWatchedRoles(const QList<QByteArray> &roles)
{
Q_D(QQmlDelegateModel);
d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
@@ -1637,7 +1632,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
if (!object.isObject())
return false;
- QV4::ExecutionEngine *v4 = object.asObject()->engine();
+ QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, object);
if (!o)
@@ -2511,7 +2506,7 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *ind
if (!value.isObject())
return false;
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
@@ -2579,9 +2574,9 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
groups |= model->m_cacheMetaType->parseGroups(val);
}
- if (v->asArrayObject()) {
+ if (v->as<QV4::ArrayObject>()) {
return;
- } else if (v->asObject()) {
+ } else if (v->as<QV4::Object>()) {
model->insert(before, v, groups);
model->emitChanges();
}
@@ -2626,7 +2621,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
v = (*args)[i];
- if (v->asObject()) {
+ if (v->as<QV4::Object>()) {
int groups = 1 << d->group;
if (++i < args->length()) {
QV4::ScopedValue val(scope, (*args)[i]);
@@ -3190,7 +3185,7 @@ QString QQmlPartsModel::stringValue(int index, const QString &role)
return QQmlDelegateModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
}
-void QQmlPartsModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
{
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
@@ -3286,12 +3281,12 @@ public:
quint32 count() const { return d()->changes.count(); }
const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); }
- static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<QQmlDelegateModelGroupChangeArray *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<QQmlDelegateModelGroupChangeArray *>(m));
+ QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
if (index >= array->count()) {
if (hasProperty)
@@ -3311,12 +3306,12 @@ public:
return object.asReturnedValue();
}
- static QV4::ReturnedValue get(QV4::Managed *m, QV4::String *name, bool *hasProperty)
+ static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QQmlDelegateModelGroupChangeArray *array = static_cast<QQmlDelegateModelGroupChangeArray *>(m);
+ const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
- if (name->equals(array->engine()->id_length)) {
+ if (name->equals(array->engine()->id_length())) {
if (hasProperty)
*hasProperty = true;
return QV4::Encode(array->count());
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index 5ebffd5b9d..e222fadec2 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -96,7 +96,7 @@ public:
ReleaseFlags release(QObject *object);
void cancel(int index);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
+ virtual void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *object, QObject *objectContext) const;
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index dc289eb35e..5c28021c0e 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -356,7 +356,7 @@ public:
ReleaseFlags release(QObject *item);
QString stringValue(int index, const QString &role);
QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(QList<QByteArray> roles);
+ void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *item, QObject *objectContext) const;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index ed97690adb..de46020ad8 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -88,7 +88,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -101,7 +101,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -150,7 +150,9 @@ const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::R
ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
{
- for (int i=0 ; i < other->roles.count() ; ++i) {
+ const int otherRolesCount = other->roles.count();
+ roles.reserve(otherRolesCount);
+ for (int i=0 ; i < otherRolesCount; ++i) {
Role *role = new Role(other->roles[i]);
roles.append(role);
roleHash.insert(role->name, role);
@@ -421,13 +423,13 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
int roleIndex = -1;
// Add the value now
- if (QV4::String *s = propertyValue->asString()) {
+ if (const QV4::String *s = propertyValue->as<QV4::String>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
roleIndex = e->setStringProperty(r, s->toQString());
} else if (propertyValue->isNumber()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -441,11 +443,11 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
} else if (propertyValue->isBoolean()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
- } else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
+ } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
QDateTime dt = dd->toQDateTime();
roleIndex = e->setDateTimeProperty(r, dt);
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -502,7 +504,7 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Number) {
e->setDoublePropertyFast(r, propertyValue->asDouble());
}
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
if (r.type == ListLayout::Role::List) {
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -520,13 +522,13 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Bool) {
e->setBoolPropertyFast(r, propertyValue->booleanValue());
}
- } else if (QV4::DateObject *date = propertyValue->asDateObject()) {
+ } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
if (r.type == ListLayout::Role::DateTime) {
QDateTime dt = date->toQDateTime();;
e->setDateTimePropertyFast(r, dt);
}
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -1169,7 +1171,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
roleIndex = setStringProperty(role, qstr);
} else if (d.isNumber()) {
roleIndex = setDoubleProperty(role, d.asDouble());
- } else if (d.asArrayObject()) {
+ } else if (d.as<QV4::ArrayObject>()) {
QV4::ScopedArrayObject a(scope, d);
if (role.type == ListLayout::Role::List) {
QV4::Scope scope(a->engine());
@@ -1183,11 +1185,11 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
}
roleIndex = setListProperty(role, subModel);
} else {
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
}
} else if (d.isBoolean()) {
roleIndex = setBoolProperty(role, d.booleanValue());
- } else if (d.asDateObject()) {
+ } else if (d.as<QV4::DateObject>()) {
QV4::Scoped<QV4::DateObject> dd(scope, d);
QDateTime dt = dd->toQDateTime();
roleIndex = setDateTimeProperty(role, dt);
@@ -1330,8 +1332,8 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int>
QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
QVariantList subArray = value.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
@@ -1398,8 +1400,8 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
QVariantList subArray = v.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index 3e53efd8b9..062d30c252 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -48,6 +48,7 @@ void QQmlModelsModule::defineModule()
qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
+ qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
}
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index 1d892beabf..0076c26950 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -36,10 +36,12 @@
#include <QtCore/qcoreapplication.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlinfo.h>
#include <private/qqmlchangeset_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qobject_p.h>
+#include <private/qpodvector_p.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
@@ -67,9 +69,8 @@ public:
QQmlObjectModelPrivate() : QObjectPrivate() {}
static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.append(Item(item));
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemAppended();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ int index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
}
static int children_count(QQmlListProperty<QObject> *prop) {
@@ -81,33 +82,77 @@ public:
}
static void children_clear(QQmlListProperty<QObject> *prop) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemCleared(static_cast<QQmlObjectModelPrivate *>(prop->data)->children);
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.clear();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
}
- void itemAppended() {
+ void insert(int index, QObject *item) {
Q_Q(QQmlObjectModel);
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.last().item);
- attached->setIndex(children.count()-1);
+ children.insert(index, Item(item));
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
QQmlChangeSet changeSet;
- changeSet.insert(children.count() - 1, 1);
+ changeSet.insert(index, 1);
emit q->modelUpdated(changeSet, false);
emit q->countChanged();
+ emit q->childrenChanged();
}
- void itemCleared(const QList<Item> &children) {
+ void move(int from, int to, int n) {
Q_Q(QQmlObjectModel);
- foreach (const Item &child, children)
- emit q->destroyingItem(child.item);
- emit q->countChanged();
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+
+ QPODVector<QQmlObjectModelPrivate::Item, 4> store;
+ for (int i = 0; i < to - from; ++i)
+ store.append(children[from + n + i]);
+ for (int i = 0; i < n; ++i)
+ store.append(children[from + i]);
+
+ for (int i = 0; i < store.count(); ++i) {
+ children[from + i] = store[i];
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(from + i).item);
+ attached->setIndex(from + i);
+ }
+
+ QQmlChangeSet changeSet;
+ changeSet.move(from, to, n, -1);
+ emit q->modelUpdated(changeSet, false);
+ emit q->childrenChanged();
}
- void emitChildrenChanged() {
+ void remove(int index, int n) {
Q_Q(QQmlObjectModel);
+ for (int i = index; i < index + n; ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(-1);
+ }
+ children.erase(children.begin() + index, children.begin() + index + n);
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
+ QQmlChangeSet changeSet;
+ changeSet.remove(index, n);
+ emit q->modelUpdated(changeSet, false);
+ emit q->countChanged();
emit q->childrenChanged();
}
+ void clear() {
+ Q_Q(QQmlObjectModel);
+ foreach (const Item &child, children)
+ emit q->destroyingItem(child.item);
+ remove(0, children.count());
+ }
+
int indexOf(QObject *item) const {
for (int i = 0; i < children.count(); ++i)
if (children.at(i).item == item)
@@ -258,4 +303,133 @@ QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
return QQmlObjectModelAttached::properties(obj);
}
+/*!
+ \qmlmethod object QtQml.Models::ObjectModel::get(int index)
+ \since 5.6
+
+ Returns the item at \a index in the model. This allows the item
+ to be accessed or modified from JavaScript:
+
+ \code
+ Component.onCompleted: {
+ objectModel.append(objectComponent.createObject())
+ console.log(objectModel.get(0).objectName);
+ objectModel.get(0).objectName = "first";
+ }
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+QObject *QQmlObjectModel::get(int index) const
+{
+ Q_D(const QQmlObjectModel);
+ if (index < 0 || index >= d->children.count())
+ return 0;
+ return d->children.at(index).item;
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::append(object item)
+ \since 5.6
+
+ Appends a new item to the end of the model.
+
+ \code
+ objectModel.append(objectComponent.createObject())
+ \endcode
+
+ \sa insert(), remove()
+*/
+void QQmlObjectModel::append(QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ d->insert(count(), object);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
+ \since 5.6
+
+ Inserts a new item to the model at position \a index.
+
+ \code
+ objectModel.insert(2, objectComponent.createObject())
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::insert(int index, QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || index > count()) {
+ qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ return;
+ }
+ d->insert(index, object);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
+ \since 5.6
+
+ Moves \a n items \a from one position \a to another.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the model:
+
+ \code
+ objectModel.move(0, objectModel.count - 3, 3)
+ \endcode
+
+ \sa append()
+*/
+void QQmlObjectModel::move(int from, int to, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (n <= 0 || from == to)
+ return;
+ if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
+ qmlInfo(this) << tr("move: out of range");
+ return;
+ }
+ d->move(from, to, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
+ \since 5.6
+
+ Removes the items at \a index from the model.
+
+ \sa clear()
+*/
+void QQmlObjectModel::remove(int index, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || n <= 0 || index + n > count()) {
+ qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
+ return;
+ }
+ d->remove(index, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::clear()
+ \since 5.6
+
+ Clears all items from the model.
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::clear()
+{
+ Q_D(QQmlObjectModel);
+ d->clear();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
index 4c37a5ac30..f6ab2a19e2 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -61,7 +61,7 @@ public:
virtual ReleaseFlags release(QObject *object) = 0;
virtual void cancel(int) {}
virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
+ virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
@@ -99,7 +99,7 @@ public:
virtual QObject *object(int index, bool asynchronous=false);
virtual ReleaseFlags release(QObject *object);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray>) {}
+ virtual void setWatchedRoles(const QList<QByteArray> &) {}
virtual int indexOf(QObject *object, QObject *objectContext) const;
@@ -107,6 +107,15 @@ public:
static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj);
+ Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const;
+ Q_REVISION(3) Q_INVOKABLE void append(QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1);
+ Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1);
+
+public Q_SLOTS:
+ Q_REVISION(3) void clear();
+
Q_SIGNALS:
void childrenChanged();
@@ -120,7 +129,7 @@ class QQmlObjectModelAttached : public QObject
public:
QQmlObjectModelAttached(QObject *parent)
- : QObject(parent), m_index(0) {}
+ : QObject(parent), m_index(-1) {}
~QQmlObjectModelAttached() {
attachedProperties.remove(parent());
}
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index c2c6e5ef5c..0aa5dc4ef6 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -54,7 +54,7 @@
#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 356970eef0..17f4ffd62b 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -38,7 +38,7 @@
#include <private/qqmlproperty_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -159,7 +159,9 @@ public:
signalIndexes.append(propertyId + signalOffset);
}
if (roles.isEmpty()) {
- for (int propertyId = 0; propertyId < propertyRoles.count(); ++propertyId)
+ const int propertyRolesCount = propertyRoles.count();
+ signalIndexes.reserve(propertyRolesCount);
+ for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
signalIndexes.append(propertyId + signalOffset);
}