summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-05-28 17:59:34 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-05-28 17:59:40 +0200
commit1f3c157ec6b8be5de1eb89295713c2980fb1a7aa (patch)
treeb85888d73518f6abc7bbde74ab71a27887682f9d
parent44ca7e31ee9365a72cd17ecd335ec4d0161420a9 (diff)
parent0f5c34f2c6b64bae3429706a6c4211334c689092 (diff)
Merge "Merge remote-tracking branch 'origin/dev' into wip/scenegraphng"wip/scenegraphng
-rw-r--r--.gitignore1
-rw-r--r--src/3rdparty/masm/assembler/ARM64Assembler.h7
-rw-r--r--src/3rdparty/masm/assembler/ARMv7Assembler.h25
-rw-r--r--src/3rdparty/masm/assembler/AbstractMacroAssembler.h14
-rw-r--r--src/3rdparty/masm/assembler/LinkBuffer.h6
-rw-r--r--src/3rdparty/masm/assembler/MacroAssembler.h14
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerARM64.h31
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerARMv7.h71
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86.h32
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86_64.h27
-rw-r--r--src/3rdparty/masm/assembler/X86Assembler.h41
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/imports/localstorage/plugin.cpp2
-rw-r--r--src/imports/qtquick2/plugin.cpp6
-rw-r--r--src/imports/qtquick2/qtquick2.pro2
-rw-r--r--src/imports/statemachine/signaltransition.cpp6
-rw-r--r--src/imports/statemachine/signaltransition.h6
-rw-r--r--src/imports/statemachine/statemachine.cpp13
-rw-r--r--src/imports/statemachine/statemachine.h3
-rw-r--r--src/imports/workerscript/dependencies.json2
-rw-r--r--src/imports/workerscript/plugin.cpp81
-rw-r--r--src/imports/workerscript/qmldir3
-rw-r--r--src/imports/workerscript/workerscript.pro11
-rw-r--r--src/particles/qquickv4particledata.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp12
-rw-r--r--src/qml/compiler/compiler.pri12
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp283
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h47
-rw-r--r--src/qml/compiler/qqmlirloader.cpp205
-rw-r--r--src/qml/compiler/qqmlirloader_p.h81
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator.cpp4
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h3
-rw-r--r--src/qml/compiler/qqmlpropertyresolver.cpp92
-rw-r--r--src/qml/compiler/qqmlpropertyresolver_p.h87
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp43
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator_p.h6
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp41
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h15
-rw-r--r--src/qml/compiler/qv4codegen.cpp74
-rw-r--r--src/qml/compiler/qv4codegen_p.h13
-rw-r--r--src/qml/compiler/qv4compileddata.cpp772
-rw-r--r--src/qml/compiler/qv4compileddata_p.h300
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp1
-rw-r--r--src/qml/compiler/qv4executablecompilationunit.cpp809
-rw-r--r--src/qml/compiler/qv4executablecompilationunit_p.h324
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp35
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/configure.json4
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h15
-rw-r--r--src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc4
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h2
-rw-r--r--src/qml/jsapi/qjsengine.cpp4
-rw-r--r--src/qml/jsruntime/jsruntime.pri10
-rw-r--r--src/qml/jsruntime/qv4calldata_p.h113
-rw-r--r--src/qml/jsruntime/qv4context.cpp4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp288
-rw-r--r--src/qml/jsruntime/qv4engine_p.h152
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h6
-rw-r--r--src/qml/jsruntime/qv4function.cpp13
-rw-r--r--src/qml/jsruntime/qv4function_p.h33
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4generatorobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4include.cpp16
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h1
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp4
-rw-r--r--src/qml/jsruntime/qv4module.cpp4
-rw-r--r--src/qml/jsruntime/qv4module_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp9
-rw-r--r--src/qml/jsruntime/qv4object_p.h10
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h2
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp2
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h20
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp7
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp62
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtimecodegen.cpp1
-rw-r--r--src/qml/jsruntime/qv4script.cpp18
-rw-r--r--src/qml/jsruntime/qv4script_p.h10
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h54
-rw-r--r--src/qml/jsruntime/qv4string.cpp11
-rw-r--r--src/qml/jsruntime/qv4string_p.h47
-rw-r--r--src/qml/jsruntime/qv4stringtoarrayindex_p.h96
-rw-r--r--src/qml/jsruntime/qv4value.cpp6
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp16
-rw-r--r--src/qml/memory/qv4mm.cpp1
-rw-r--r--src/qml/memory/qv4writebarrier_p.h2
-rw-r--r--src/qml/qml.pro3
-rw-r--r--src/qml/qml/qqmlbinding.cpp6
-rw-r--r--src/qml/qml/qqmlbinding_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp5
-rw-r--r--src/qml/qml/qqmlcomponent.h7
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-rw-r--r--src/qml/qml/qqmlcontext.cpp29
-rw-r--r--src/qml/qml/qqmlcontext_p.h6
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h4
-rw-r--r--src/qml/qml/qqmldata_p.h8
-rw-r--r--src/qml/qml/qqmlengine.cpp31
-rw-r--r--src/qml/qml/qqmlengine_p.h28
-rw-r--r--src/qml/qml/qqmlglobal_p.h1
-rw-r--r--src/qml/qml/qqmlincubator_p.h2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp4
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h4
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype_p.h6
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp98
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h8
-rw-r--r--src/qml/qml/qqmlprivate.h5
-rw-r--r--src/qml/qml/qqmlproperty_p.h1
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp2
-rw-r--r--src/qml/qml/qqmltype.cpp4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp95
-rw-r--r--src/qml/qml/qqmltypeloader_p.h19
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp1
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h4
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp18
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp18
-rw-r--r--src/qml/qml/v8/qv8engine.cpp331
-rw-r--r--src/qml/qml/v8/qv8engine_p.h228
-rw-r--r--src/qml/qml/v8/v8.pri2
-rw-r--r--src/qml/qtqml.tracepoints14
-rw-r--r--src/qml/qtqmlglobal.h2
-rw-r--r--src/qml/types/qqmlbind.cpp142
-rw-r--r--src/qml/types/qqmlbind_p.h18
-rw-r--r--src/qml/types/qqmlconnections.cpp6
-rw-r--r--src/qml/types/qqmlconnections_p.h4
-rw-r--r--src/qml/types/types.pri7
-rw-r--r--src/qmlmodels/configure.json13
-rw-r--r--src/qmlmodels/qmlmodels.pro54
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp2
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp2
-rw-r--r--src/qmlmodels/qqmlinstantiator_p.h2
-rw-r--r--src/qmlmodels/qqmlinstantiator_p_p.h2
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp20
-rw-r--r--src/qmlmodels/qqmllistmodel_p.h10
-rw-r--r--src/qmlmodels/qqmllistmodelworkeragent_p.h2
-rw-r--r--src/qmlmodels/qqmlmodelsmodule.cpp31
-rw-r--r--src/qmlmodels/qqmlobjectmodel_p.h2
-rw-r--r--src/qmlmodels/qqmltableinstancemodel_p.h2
-rw-r--r--src/qmlmodels/qqmltablemodel_p.h2
-rw-r--r--src/qmlmodels/qqmltablemodelcolumn_p.h2
-rw-r--r--src/qmlmodels/qquickpackage_p.h3
-rw-r--r--src/qmltest/quicktest.cpp11
-rw-r--r--src/qmlworkerscript/qmlworkerscript.pro20
-rw-r--r--src/qmlworkerscript/qqmlworkerscriptmodule.cpp62
-rw-r--r--src/qmlworkerscript/qqmlworkerscriptmodule_p.h69
-rw-r--r--src/qmlworkerscript/qquickworkerscript.cpp (renamed from src/qml/types/qquickworkerscript.cpp)104
-rw-r--r--src/qmlworkerscript/qquickworkerscript_p.h (renamed from src/qml/types/qquickworkerscript_p.h)0
-rw-r--r--src/qmlworkerscript/qtqmlworkerscriptglobal.h58
-rw-r--r--src/qmlworkerscript/qtqmlworkerscriptglobal_p.h60
-rw-r--r--src/qmlworkerscript/qv4serialize.cpp (renamed from src/qml/jsruntime/qv4serialize.cpp)0
-rw-r--r--src/qmlworkerscript/qv4serialize_p.h (renamed from src/qml/jsruntime/qv4serialize_p.h)0
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp16
-rw-r--r--src/quick/accessible/qaccessiblequickitem_p.h1
-rw-r--r--src/quick/configure.json1
-rw-r--r--src/quick/designer/qquickdesignercustomparserobject.cpp4
-rw-r--r--src/quick/designer/qquickdesignercustomparserobject_p.h4
-rw-r--r--src/quick/doc/snippets/pointerHandlers/tapHandlerOnTapped.qml64
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp37
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h13
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp27
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp14
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp43
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h32
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp7
-rw-r--r--src/quick/items/qquickopenglshadereffect_p.h2
-rw-r--r--src/quick/items/qquickopenglshadereffectnode.cpp8
-rw-r--r--src/quick/items/qquickopenglshadereffectnode_p.h4
-rw-r--r--src/quick/items/qquickshadereffect.cpp3
-rw-r--r--src/quick/items/qquicktableview.cpp367
-rw-r--r--src/quick/items/qquicktableview_p.h5
-rw-r--r--src/quick/items/qquicktableview_p_p.h7
-rw-r--r--src/quick/items/qquicktext.cpp16
-rw-r--r--src/quick/items/qquicktext_p.h1
-rw-r--r--src/quick/items/qquicktext_p_p.h1
-rw-r--r--src/quick/items/qquicktextcontrol.cpp3
-rw-r--r--src/quick/items/qquicktextdocument.cpp8
-rw-r--r--src/quick/items/qquicktextdocument_p.h3
-rw-r--r--src/quick/items/qquicktextedit.cpp19
-rw-r--r--src/quick/items/qquicktextedit_p.h1
-rw-r--r--src/quick/items/qquicktextedit_p_p.h1
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp11
-rw-r--r--src/quick/items/qquickwindow.cpp42
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp2
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp1
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h1
-rw-r--r--src/quick/util/qquickpropertychanges.cpp18
-rw-r--r--src/quick/util/qquickpropertychanges_p.h6
-rw-r--r--src/quick/util/qquickstategroup.cpp2
-rw-r--r--src/src.pro2
-rw-r--r--sync.profile1
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp2
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp35
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding2.qml55
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding3.qml56
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding4.qml59
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp75
-rw-r--r--tests/auto/qml/qqmlengine/data/CachedGetterLookup.qml20
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp11
-rw-r--r--tests/auto/qml/qqmllanguage/data/bareQmlImport.errors.txt0
-rw-r--r--tests/auto/qml/qqmllanguage/data/bareQmlImport.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp6
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h18
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp8
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp6
-rw-r--r--tests/auto/qml/qquickworkerscript/qquickworkerscript.pro2
-rw-r--r--tests/auto/qmltest/statemachine/tst_parallelmachine.qml32
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml86
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro1
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp74
-rw-r--r--tests/auto/quick/qquickaccessible/data/text.qml (renamed from tests/auto/quick/qquickaccessible/data/statictext.qml)29
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp70
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicktableview/data/syncviewsimple.qml122
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp609
-rw-r--r--tests/auto/quick/qquicktextedit/qquicktextedit.pro1
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp56
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp56
-rw-r--r--tests/manual/tableview/abstracttablemodel/Button.qml2
-rw-r--r--tests/manual/tableview/abstracttablemodel/main.qml156
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp47
-rw-r--r--tools/qmljs/qmljs.cpp3
234 files changed, 5712 insertions, 3284 deletions
diff --git a/.gitignore b/.gitignore
index 57606bfacf..9905dd1fdc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,7 @@ wrapper.bat
*.*#
core
.qmake.cache
+.qmake.stash
.qmake.vars
*.prl
tags
diff --git a/src/3rdparty/masm/assembler/ARM64Assembler.h b/src/3rdparty/masm/assembler/ARM64Assembler.h
index a9166e83a2..ca6b33d39a 100644
--- a/src/3rdparty/masm/assembler/ARM64Assembler.h
+++ b/src/3rdparty/masm/assembler/ARM64Assembler.h
@@ -26,7 +26,7 @@
#ifndef ARM64Assembler_h
#define ARM64Assembler_h
-#if ENABLE(ASSEMBLER) && (CPU(ARM64) || defined(V4_BOOTSTRAP))
+#if ENABLE(ASSEMBLER) && CPU(ARM64)
#include "AssemblerBuffer.h"
#include "AbstractMacroAssembler.h"
@@ -3021,10 +3021,7 @@ public:
static void cacheFlush(void* code, size_t size)
{
-#if defined(V4_BOOTSTRAP)
- UNUSED_PARAM(code)
- UNUSED_PARAM(size)
-#elif OS(IOS)
+#if OS(IOS)
sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
#elif OS(LINUX)
size_t page = pageSize();
diff --git a/src/3rdparty/masm/assembler/ARMv7Assembler.h b/src/3rdparty/masm/assembler/ARMv7Assembler.h
index d57e5a7c78..f2e8dc1a1b 100644
--- a/src/3rdparty/masm/assembler/ARMv7Assembler.h
+++ b/src/3rdparty/masm/assembler/ARMv7Assembler.h
@@ -27,7 +27,7 @@
#ifndef ARMAssembler_h
#define ARMAssembler_h
-#if ENABLE(ASSEMBLER) && (CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP))
+#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
#include "AssemblerBuffer.h"
#include "MacroAssemblerCodeRef.h"
@@ -2166,7 +2166,6 @@ public:
linkJumpAbsolute(location, to);
}
-#if !defined(V4_BOOTSTRAP)
static void linkCall(void* code, AssemblerLabel from, void* to)
{
ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
@@ -2175,14 +2174,12 @@ public:
setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to, false);
}
-#endif
static void linkPointer(void* code, AssemblerLabel where, void* value)
{
setPointer(reinterpret_cast<char*>(code) + where.m_offset, value, false);
}
-#if !defined(V4_BOOTSTRAP)
static void relinkJump(void* from, void* to)
{
ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
@@ -2205,7 +2202,6 @@ public:
{
return readPointer(reinterpret_cast<uint16_t*>(from) - 1);
}
-#endif
static void repatchInt32(void* where, int32_t value)
{
@@ -2234,7 +2230,6 @@ public:
cacheFlush(location, sizeof(uint16_t) * 2);
}
-#if !defined(V4_BOOTSTRAP)
static void repatchPointer(void* where, void* value)
{
ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
@@ -2246,7 +2241,6 @@ public:
{
return reinterpret_cast<void*>(readInt32(where));
}
-#endif
static void replaceWithJump(void* instructionStart, void* to)
{
@@ -2321,7 +2315,7 @@ public:
unsigned debugOffset() { return m_formatter.debugOffset(); }
-#if OS(LINUX) && !defined(V4_BOOTSTRAP)
+#if OS(LINUX)
static inline void linuxPageFlush(uintptr_t begin, uintptr_t end)
{
asm volatile(
@@ -2341,10 +2335,7 @@ public:
static void cacheFlush(void* code, size_t size)
{
-#if defined(V4_BOOTSTRAP)
- UNUSED_PARAM(code)
- UNUSED_PARAM(size)
-#elif OS(IOS)
+#if OS(IOS)
sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
#elif OS(LINUX)
size_t page = pageSize();
@@ -2662,11 +2653,6 @@ private:
static void linkBX(uint16_t* instruction, void* target)
{
-#if defined(V4_BOOTSTRAP)
- UNUSED_PARAM(instruction);
- UNUSED_PARAM(target);
- RELEASE_ASSERT_NOT_REACHED();
-#else
// FIMXE: this should be up in the MacroAssembler layer. :-(
ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
@@ -2679,7 +2665,6 @@ private:
instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
-#endif
}
void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
@@ -2712,9 +2697,6 @@ private:
instruction[-3] = OP_NOP_T2b;
linkJumpT4(instruction, target);
} else {
-#if defined(V4_BOOTSTRAP)
- RELEASE_ASSERT_NOT_REACHED();
-#else
const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
@@ -2723,7 +2705,6 @@ private:
instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
-#endif
}
}
diff --git a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h
index d0c1c4613e..14644a4193 100644
--- a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h
+++ b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h
@@ -66,7 +66,7 @@ public:
typedef MacroAssemblerCodePtr CodePtr;
typedef MacroAssemblerCodeRef CodeRef;
-#if !CPU(ARM_THUMB2) && !CPU(ARM64) && !defined(V4_BOOTSTRAP)
+#if !CPU(ARM_THUMB2) && !CPU(ARM64)
class Jump;
#endif
@@ -328,7 +328,7 @@ public:
friend class AbstractMacroAssembler;
friend struct DFG::OSRExit;
-#if CPU(ARM_THUMB2) || CPU(ARM64) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2) || CPU(ARM64)
using Jump = typename AssemblerType::template Jump<Label>;
friend Jump;
#else
@@ -461,7 +461,7 @@ public:
AssemblerLabel m_label;
};
-#if CPU(ARM_THUMB2) || CPU(ARM64) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2) || CPU(ARM64)
using Jump = typename AssemblerType::template Jump<Label>;
friend Jump;
#endif
@@ -516,7 +516,7 @@ public:
// into the code buffer - it is typically used to link the jump, setting the
// relative offset such that when executed it will jump to the desired
// destination.
-#if !CPU(ARM_THUMB2) && !CPU(ARM64) && !defined(V4_BOOTSTRAP)
+#if !CPU(ARM_THUMB2) && !CPU(ARM64)
class Jump {
template<class TemplateAssemblerType>
friend class AbstractMacroAssembler;
@@ -528,7 +528,7 @@ public:
{
}
-#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2)
// Fixme: this information should be stored in the instruction stream, not in the Jump object.
Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
: m_label(jmp)
@@ -621,7 +621,7 @@ public:
private:
AssemblerLabel m_label;
-#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2)
ARMv7Assembler::JumpType m_type;
ARMv7Assembler::Condition m_condition;
#endif
@@ -878,12 +878,10 @@ protected:
AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
}
-#if !defined(V4_BOOTSTRAP)
static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
{
return AssemblerType::readPointer(dataLabelPtr.dataLocation());
}
-#endif
static void replaceWithLoad(CodeLocationConvertibleLoad label)
{
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index a1bb046d43..8e9a3d9c7a 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -374,7 +374,7 @@ public:
}
};
-#if CPU(ARM_THUMB2) || CPU(ARM64) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2) || CPU(ARM64)
template <typename T>
struct BranchCompactingExecutableOffsetCalculator {
@@ -509,7 +509,7 @@ inline void BranchCompactingLinkBuffer<MacroAssembler>::linkCode(void* ownerUID,
m_executableMemory->shrink(m_size);
}
-#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2)
template <>
class LinkBuffer<JSC::MacroAssembler<MacroAssemblerARMv7>> : public BranchCompactingLinkBuffer<JSC::MacroAssembler<MacroAssemblerARMv7>>
{
@@ -520,7 +520,7 @@ public:
};
#endif
-#if CPU(ARM64) || defined(V4_BOOTSTRAP)
+#if CPU(ARM64)
template <>
class LinkBuffer<JSC::MacroAssembler<MacroAssemblerARM64>> : public BranchCompactingLinkBuffer<JSC::MacroAssembler<MacroAssemblerARM64>>
{
diff --git a/src/3rdparty/masm/assembler/MacroAssembler.h b/src/3rdparty/masm/assembler/MacroAssembler.h
index b442a81bd0..aada47303f 100644
--- a/src/3rdparty/masm/assembler/MacroAssembler.h
+++ b/src/3rdparty/masm/assembler/MacroAssembler.h
@@ -97,10 +97,7 @@ public:
using MacroAssemblerBase::load32;
-#if defined(V4_BOOTSTRAP)
- using MacroAssemblerBase::loadPtr;
- using MacroAssemblerBase::storePtr;
-#elif CPU(X86_64) || CPU(ARM64)
+#if CPU(X86_64) || CPU(ARM64)
using MacroAssemblerBase::add64;
using MacroAssemblerBase::sub64;
using MacroAssemblerBase::xor64;
@@ -214,14 +211,12 @@ public:
store32(value, addressForPoke(index));
}
-#if !defined(V4_BOOTSTRAP)
void poke(TrustedImmPtr imm, int index = 0)
{
storePtr(imm, addressForPoke(index));
}
-#endif
-#if (CPU(X86_64) || CPU(ARM64)) && !defined(V4_BOOTSTRAP)
+#if CPU(X86_64) || CPU(ARM64)
void peek64(RegisterID dest, int index = 0)
{
load64(Address(MacroAssemblerBase::stackPointerRegister, (index * sizeof(void*))), dest);
@@ -352,7 +347,6 @@ public:
return !(this->random() & (BlindingModulus - 1));
}
-#if !defined(V4_BOOTSTRAP)
// Ptr methods
// On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
// FIXME: should this use a test for 32-bitness instead of this specific exception?
@@ -877,7 +871,7 @@ public:
{
return branchSub64(cond, src1, src2, dest);
}
-#endif // !defined(V4_BOOTSTRAP)
+#endif // !CPU(X86_64) && !CPU(ARM64)
#if ENABLE(JIT_CONSTANT_BLINDING)
using MacroAssemblerBase::and64;
@@ -1101,8 +1095,6 @@ public:
#endif
-#endif // !CPU(X86_64)
-
#if ENABLE(JIT_CONSTANT_BLINDING)
bool shouldBlind(Imm32 imm)
{
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
index 3e6dfcf635..c0c68f6393 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
@@ -26,7 +26,7 @@
#ifndef MacroAssemblerARM64_h
#define MacroAssemblerARM64_h
-#if ENABLE(ASSEMBLER) && (CPU(ARM64) || defined(V4_BOOTSTRAP))
+#if ENABLE(ASSEMBLER) && CPU(ARM64)
#include "ARM64Assembler.h"
#include "AbstractMacroAssembler.h"
@@ -211,33 +211,6 @@ public:
static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
-#if defined(V4_BOOTSTRAP)
- void loadPtr(ImplicitAddress address, RegisterID dest)
- {
- load64(address, dest);
- }
-
- void subPtr(TrustedImm32 imm, RegisterID dest)
- {
- sub64(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID dest)
- {
- add64(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
- {
- add64(imm, src, dest);
- }
-
- void storePtr(RegisterID src, ImplicitAddress address)
- {
- store64(src, address);
- }
-#endif
-
// Integer operations:
void add32(RegisterID a, RegisterID b, RegisterID dest)
@@ -2822,7 +2795,6 @@ public:
return branch32(cond, left, dataTempRegister);
}
-#if !defined(V4_BOOTSTRAP)
PatchableJump patchableBranchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
{
m_makeJumpPatchable = true;
@@ -2830,7 +2802,6 @@ public:
m_makeJumpPatchable = false;
return PatchableJump(result);
}
-#endif
PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
{
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
index 99801a0e3b..6232834fde 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
@@ -27,7 +27,7 @@
#ifndef MacroAssemblerARMv7_h
#define MacroAssemblerARMv7_h
-#if ENABLE(ASSEMBLER) && (CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP))
+#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
#include "ARMv7Assembler.h"
#include "AbstractMacroAssembler.h"
@@ -162,41 +162,12 @@ public:
{
add32(imm, dest, dest);
}
-
-#if defined(V4_BOOTSTRAP)
- void loadPtr(ImplicitAddress address, RegisterID dest)
- {
- load32(address, dest);
- }
-
- void subPtr(TrustedImm32 imm, RegisterID dest)
- {
- sub32(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID dest)
- {
- add32(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
- {
- add32(imm, src, dest);
- }
-
- void storePtr(RegisterID src, ImplicitAddress address)
- {
- store32(src, address);
- }
-#endif
-#if !defined(V4_BOOTSTRAP)
void add32(AbsoluteAddress src, RegisterID dest)
{
load32(src.m_ptr, dataTempRegister);
add32(dataTempRegister, dest);
}
-#endif
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
@@ -237,7 +208,6 @@ public:
add32(dataTempRegister, dest);
}
-#if !defined(V4_BOOTSTRAP)
void add32(TrustedImm32 imm, AbsoluteAddress address)
{
load32(address.m_ptr, dataTempRegister);
@@ -282,7 +252,6 @@ public:
m_assembler.adc(dataTempRegister, dataTempRegister, ARMThumbImmediate::makeEncodedImm(imm.m_value >> 31));
m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt12(4));
}
-#endif
void and32(RegisterID op1, RegisterID op2, RegisterID dest)
{
@@ -384,7 +353,6 @@ public:
or32(dataTempRegister, dest);
}
-#if !defined(V4_BOOTSTRAP)
void or32(RegisterID src, AbsoluteAddress dest)
{
move(TrustedImmPtr(dest.m_ptr), addressTempRegister);
@@ -392,7 +360,6 @@ public:
or32(src, dataTempRegister);
store32(dataTempRegister, addressTempRegister);
}
-#endif
void or32(TrustedImm32 imm, RegisterID dest)
{
@@ -504,7 +471,6 @@ public:
sub32(dataTempRegister, dest);
}
-#if !defined(V4_BOOTSTRAP)
void sub32(TrustedImm32 imm, AbsoluteAddress address)
{
load32(address.m_ptr, dataTempRegister);
@@ -521,7 +487,6 @@ public:
store32(dataTempRegister, address.m_ptr);
}
-#endif
void xor32(Address src, RegisterID dest)
{
@@ -698,13 +663,11 @@ public:
load16(setupArmAddress(address), dest);
}
-#if !defined(V4_BOOTSTRAP)
void load32(const void* address, RegisterID dest)
{
move(TrustedImmPtr(address), addressTempRegister);
m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
}
-#endif
ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
{
@@ -809,7 +772,6 @@ public:
store32(dataTempRegister, setupArmAddress(address));
}
-#if !defined(V4_BOOTSTRAP)
void store32(RegisterID src, const void* address)
{
move(TrustedImmPtr(address), addressTempRegister);
@@ -821,7 +783,6 @@ public:
move(imm, dataTempRegister);
store32(dataTempRegister, address);
}
-#endif
void store8(RegisterID src, BaseIndex address)
{
@@ -839,7 +800,6 @@ public:
store8(dataTempRegister, address);
}
-#if !defined(V4_BOOTSTRAP)
void store8(RegisterID src, void* address)
{
move(TrustedImmPtr(address), addressTempRegister);
@@ -851,7 +811,6 @@ public:
move(imm, dataTempRegister);
store8(dataTempRegister, address);
}
-#endif
void store16(RegisterID src, BaseIndex address)
{
@@ -949,13 +908,11 @@ public:
m_assembler.vmov(dest, src);
}
-#if !defined(V4_BOOTSTRAP)
void loadDouble(const void* address, FPRegisterID dest)
{
move(TrustedImmPtr(address), addressTempRegister);
m_assembler.vldr(dest, addressTempRegister, 0);
}
-#endif
void storeDouble(FPRegisterID src, ImplicitAddress address)
{
@@ -987,13 +944,11 @@ public:
m_assembler.fsts(ARMRegisters::asSingle(src), base, offset);
}
-#if !defined(V4_BOOTSTRAP)
void storeDouble(FPRegisterID src, const void* address)
{
move(TrustedImmPtr(address), addressTempRegister);
storeDouble(src, addressTempRegister);
}
-#endif
void storeDouble(FPRegisterID src, BaseIndex address)
{
@@ -1027,13 +982,11 @@ public:
m_assembler.vadd(dest, op1, op2);
}
-#if !defined(V4_BOOTSTRAP)
void addDouble(AbsoluteAddress address, FPRegisterID dest)
{
loadDouble(address.m_ptr, fpTempRegister);
m_assembler.vadd(dest, dest, fpTempRegister);
}
-#endif
void divDouble(FPRegisterID src, FPRegisterID dest)
{
@@ -1112,7 +1065,6 @@ public:
m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
}
-#if !defined(V4_BOOTSTRAP)
void convertInt32ToDouble(AbsoluteAddress address, FPRegisterID dest)
{
// Fixme: load directly into the fpr!
@@ -1120,7 +1072,6 @@ public:
m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister);
m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
}
-#endif
void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID /*scratch*/)
{
@@ -1316,12 +1267,10 @@ public:
m_assembler.mov(dest, src);
}
-#if !defined(V4_BOOTSTRAP)
void move(TrustedImmPtr imm, RegisterID dest)
{
move(TrustedImm32(imm), dest);
}
-#endif
void swap(RegisterID reg1, RegisterID reg2)
{
@@ -1462,7 +1411,6 @@ public:
return branch32(cond, addressTempRegister, right);
}
-#if !defined(V4_BOOTSTRAP)
Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
{
load32(left.m_ptr, dataTempRegister);
@@ -1475,7 +1423,6 @@ public:
load32(left.m_ptr, addressTempRegister);
return branch32(cond, addressTempRegister, right);
}
-#endif
Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right)
{
@@ -1532,7 +1479,6 @@ public:
return branchTest32(cond, addressTempRegister, mask);
}
-#if !defined(V4_BOOTSTRAP)
Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
{
// use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
@@ -1540,7 +1486,6 @@ public:
load8(Address(addressTempRegister), addressTempRegister);
return branchTest32(cond, addressTempRegister, mask);
}
-#endif
void jump(RegisterID target)
{
@@ -1554,14 +1499,12 @@ public:
m_assembler.bx(dataTempRegister);
}
-#if !defined(V4_BOOTSTRAP)
void jump(AbsoluteAddress address)
{
move(TrustedImmPtr(address.m_ptr), dataTempRegister);
load32(Address(dataTempRegister), dataTempRegister);
m_assembler.bx(dataTempRegister);
}
-#endif
// Arithmetic control flow operations:
@@ -1602,7 +1545,6 @@ public:
return branchAdd32(cond, dest, imm, dest);
}
-#if !defined(V4_BOOTSTRAP)
Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
{
// Move the high bits of the address into addressTempRegister,
@@ -1628,7 +1570,6 @@ public:
return Jump(makeBranch(cond));
}
-#endif
Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
{
@@ -1799,7 +1740,6 @@ public:
return DataLabel32(this);
}
-#if !defined(V4_BOOTSTRAP)
ALWAYS_INLINE DataLabelPtr moveWithPatch(TrustedImmPtr imm, RegisterID dst)
{
padBeforePatch();
@@ -1827,7 +1767,6 @@ public:
m_makeJumpPatchable = false;
return PatchableJump(result);
}
-#endif
PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
{
@@ -1845,7 +1784,6 @@ public:
return PatchableJump(result);
}
-#if !defined(V4_BOOTSTRAP)
PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
{
m_makeJumpPatchable = true;
@@ -1853,7 +1791,6 @@ public:
m_makeJumpPatchable = false;
return PatchableJump(result);
}
-#endif
PatchableJump patchableJump()
{
@@ -1864,7 +1801,6 @@ public:
return PatchableJump(result);
}
-#if !defined(V4_BOOTSTRAP)
ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
{
DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
@@ -1872,7 +1808,6 @@ public:
return label;
}
ALWAYS_INLINE DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
-#endif
ALWAYS_INLINE Call tailRecursiveCall()
{
@@ -1893,7 +1828,6 @@ public:
return m_assembler.executableOffsetFor(location);
}
-#if !defined(V4_BOOTSTRAP)
static FunctionPtr readCallTarget(CodeLocationCall call)
{
return FunctionPtr(reinterpret_cast<void(*)()>(ARMv7Assembler::readCallTarget(call.dataLocation())));
@@ -1906,7 +1840,6 @@ public:
const unsigned twoWordOpSize = 4;
return label.labelAtOffset(-twoWordOpSize * 2);
}
-#endif
static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue)
{
@@ -2024,7 +1957,6 @@ private:
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
-#if !defined(V4_BOOTSTRAP)
static void linkCall(void* code, Call call, FunctionPtr function)
{
ARMv7Assembler::linkCall(code, call.m_label, function.value());
@@ -2039,7 +1971,6 @@ private:
{
ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
}
-#endif
bool m_makeJumpPatchable;
};
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86.h b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
index e3e0bfe5e1..5cffa787ec 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
@@ -55,38 +55,6 @@ public:
using MacroAssemblerX86Common::convertInt32ToDouble;
using MacroAssemblerX86Common::branchTest8;
-#if defined(V4_BOOTSTRAP)
- void loadPtr(ImplicitAddress address, RegisterID dest)
- {
- load32(address, dest);
- }
-
- void subPtr(TrustedImm32 imm, RegisterID dest)
- {
- sub32(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID dest)
- {
- add32(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
- {
- add32(imm, src, dest);
- }
-
- void storePtr(RegisterID src, ImplicitAddress address)
- {
- store32(src, address);
- }
-
- Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
- {
- return branchTest8(cond, Address(address.base, address.offset), mask);
- }
-#endif
-
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
m_assembler.leal_mr(imm.m_value, src, dest);
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
index 64df58d121..0a6db0805b 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
@@ -53,33 +53,6 @@ public:
using MacroAssemblerX86Common::loadDouble;
using MacroAssemblerX86Common::convertInt32ToDouble;
-#if defined(V4_BOOTSTRAP)
- void loadPtr(ImplicitAddress address, RegisterID dest)
- {
- load64(address, dest);
- }
-
- void subPtr(TrustedImm32 imm, RegisterID dest)
- {
- sub64(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID dest)
- {
- add64(imm, dest);
- }
-
- void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
- {
- add64(imm, src, dest);
- }
-
- void storePtr(RegisterID src, ImplicitAddress address)
- {
- store64(src, address);
- }
-#endif
-
void add32(TrustedImm32 imm, AbsoluteAddress address)
{
move(TrustedImmPtr(address.m_ptr), scratchRegister);
diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h
index 2257cb2b9a..e8ae687036 100644
--- a/src/3rdparty/masm/assembler/X86Assembler.h
+++ b/src/3rdparty/masm/assembler/X86Assembler.h
@@ -255,47 +255,6 @@ public:
{
}
-#if defined(V4_BOOTSTRAP)
- template <typename LabelType>
- class Jump {
- template<class TemplateAssemblerType>
- friend class AbstractMacroAssembler;
- friend class Call;
- template <typename, template <typename> class> friend class LinkBufferBase;
- public:
- Jump()
- {
- }
-
- Jump(AssemblerLabel jmp)
- : m_label(jmp)
- {
- }
-
- LabelType label() const
- {
- LabelType result;
- result.m_label = m_label;
- return result;
- }
-
- void link(AbstractMacroAssembler<X86Assembler>* masm) const
- {
- masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
- }
-
- void linkTo(LabelType label, AbstractMacroAssembler<X86Assembler>* masm) const
- {
- masm->m_assembler.linkJump(m_label, label.label());
- }
-
- bool isSet() const { return m_label.isSet(); }
-
- private:
- AssemblerLabel m_label;
- };
-#endif
-
// Stack operations:
void push_r(RegisterID reg)
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 901c263be5..6b31dfc65d 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += qml-private
SUBDIRS += \
builtins \
@@ -6,6 +7,7 @@ SUBDIRS += \
models \
labsmodels
+qtConfig(qml-worker-script): SUBDIRS += workerscript
qtConfig(thread): SUBDIRS += folderlistmodel
qtHaveModule(sql): SUBDIRS += localstorage
qtConfig(settings): SUBDIRS += settings
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 0aad0d7c16..9004d1ee6f 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -85,7 +85,7 @@ QT_BEGIN_NAMESPACE
}
-class QQmlSqlDatabaseData : public QV8Engine::Deletable
+class QQmlSqlDatabaseData : public QV4::ExecutionEngine::Deletable
{
public:
QQmlSqlDatabaseData(QV4::ExecutionEngine *engine);
diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp
index a5a2c73ced..efa05c349c 100644
--- a/src/imports/qtquick2/plugin.cpp
+++ b/src/imports/qtquick2/plugin.cpp
@@ -42,6 +42,9 @@
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QtQml/private/qqmlengine_p.h>
#include <QtQmlModels/private/qqmlmodelsmodule_p.h>
+#if QT_CONFIG(qml_worker_script)
+#include <QtQmlWorkerScript/private/qqmlworkerscriptmodule_p.h>
+#endif
#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <private/qtquick2_p.h>
@@ -63,6 +66,9 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QQmlEnginePrivate::registerQuickTypes();
QQmlModelsModule::registerQuickTypes();
+#if QT_CONFIG(qml_worker_script)
+ QQmlWorkerScriptModule::registerQuickTypes();
+#endif
#endif
QQmlQtQuick2Module::defineModule();
diff --git a/src/imports/qtquick2/qtquick2.pro b/src/imports/qtquick2/qtquick2.pro
index 1b45d69eb7..8543049ead 100644
--- a/src/imports/qtquick2/qtquick2.pro
+++ b/src/imports/qtquick2/qtquick2.pro
@@ -8,4 +8,6 @@ SOURCES += \
QT += quick-private qml-private qmlmodels-private
+qtConfig(qml-worker-script): QT += qmlworkerscript-private
+
load(qml_plugin)
diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp
index 52dffe9004..468f2020c7 100644
--- a/src/imports/statemachine/signaltransition.cpp
+++ b/src/imports/statemachine/signaltransition.cpp
@@ -184,7 +184,7 @@ void SignalTransition::connectTriggered()
m_signalExpression = expression;
}
-void SignalTransitionParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
+void SignalTransitionParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
for (int ii = 0; ii < props.count(); ++ii) {
const QV4::CompiledData::Binding *binding = props.at(ii);
@@ -203,7 +203,9 @@ void SignalTransitionParser::verifyBindings(const QQmlRefPointer<QV4::CompiledDa
}
}
-void SignalTransitionParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void SignalTransitionParser::applyBindings(
+ QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QList<const QV4::CompiledData::Binding *> &bindings)
{
SignalTransition *st = qobject_cast<SignalTransition*>(object);
st->m_compilationUnit = compilationUnit;
diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h
index 90e6f96fbc..f005c5e9b1 100644
--- a/src/imports/statemachine/signaltransition.h
+++ b/src/imports/statemachine/signaltransition.h
@@ -89,7 +89,7 @@ private:
QJSValue m_signal;
QQmlScriptString m_guard;
bool m_complete;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
QList<const QV4::CompiledData::Binding *> m_bindings;
QQmlBoundSignalExpressionPointer m_signalExpression;
};
@@ -97,8 +97,8 @@ private:
class SignalTransitionParser : public QQmlCustomParser
{
public:
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
- void applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
+ void applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
QT_END_NAMESPACE
diff --git a/src/imports/statemachine/statemachine.cpp b/src/imports/statemachine/statemachine.cpp
index ca6c59b6ac..a983644018 100644
--- a/src/imports/statemachine/statemachine.cpp
+++ b/src/imports/statemachine/statemachine.cpp
@@ -51,6 +51,7 @@ StateMachine::StateMachine(QObject *parent)
: QStateMachine(parent), m_completed(false), m_running(false)
{
connect(this, SIGNAL(runningChanged(bool)), SIGNAL(qmlRunningChanged()));
+ connect(this, SIGNAL(childModeChanged()), SLOT(checkChildMode()));
}
bool StateMachine::isRunning() const
@@ -66,6 +67,15 @@ void StateMachine::setRunning(bool running)
m_running = running;
}
+void StateMachine::checkChildMode()
+{
+ if (childMode() != QState::ExclusiveStates) {
+ qmlWarning(this) << "Setting the childMode of a StateMachine to anything else than\n"
+ "QState.ExclusiveStates will result in an invalid state machine,\n"
+ "and can lead to incorrect behavior!";
+ }
+}
+
void StateMachine::componentComplete()
{
if (QStateMachine::initialState() == nullptr && childMode() == QState::ExclusiveStates)
@@ -129,6 +139,9 @@ QQmlListProperty<QObject> StateMachine::children()
erroneous state, the machine will stop executing and an error message will
be printed to the console.
+ \warning Setting the childMode of a StateMachine to anything else than QState::ExclusiveStates
+ will result in an invalid state machine, and can lead to incorrect behavior.
+
\clearfloat
\sa QAbstractState, State, SignalTransition, TimeoutTransition, HistoryState {The Declarative State Machine Framework}
diff --git a/src/imports/statemachine/statemachine.h b/src/imports/statemachine/statemachine.h
index cb0ab43f8b..1fa7a9da43 100644
--- a/src/imports/statemachine/statemachine.h
+++ b/src/imports/statemachine/statemachine.h
@@ -69,6 +69,9 @@ public:
bool isRunning() const;
void setRunning(bool running);
+private Q_SLOTS:
+ void checkChildMode();
+
Q_SIGNALS:
void childrenChanged();
/*!
diff --git a/src/imports/workerscript/dependencies.json b/src/imports/workerscript/dependencies.json
new file mode 100644
index 0000000000..0d4f101c7a
--- /dev/null
+++ b/src/imports/workerscript/dependencies.json
@@ -0,0 +1,2 @@
+[
+]
diff --git a/src/imports/workerscript/plugin.cpp b/src/imports/workerscript/plugin.cpp
new file mode 100644
index 0000000000..5b3bff7934
--- /dev/null
+++ b/src/imports/workerscript/plugin.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQmlWorkerScript/private/qqmlworkerscriptmodule_p.h>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlmodule QtQml.WorkerScript 2.\QtMinorVersion
+ \title Qt QML WorkerScript QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for worker scripts
+ \since 5.14
+
+ This QML module contains types for using worker scripts.
+
+ To use the types in this module, import the module with the following line:
+
+ \qml \QtMinorVersion
+ import QtQml.WorkerScript 2.\1
+ \endqml
+*/
+
+class QtQmlWorkerScriptPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QtQmlWorkerScriptPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
+ void registerTypes(const char *uri) override
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQml.WorkerScript"));
+
+ QQmlWorkerScriptModule::defineModule();
+
+ // Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR);
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/workerscript/qmldir b/src/imports/workerscript/qmldir
new file mode 100644
index 0000000000..0e811d1dbc
--- /dev/null
+++ b/src/imports/workerscript/qmldir
@@ -0,0 +1,3 @@
+module QtQml.WorkerScript
+plugin workerscriptsplugin
+classname QtQmlWorkerScriptPlugin
diff --git a/src/imports/workerscript/workerscript.pro b/src/imports/workerscript/workerscript.pro
new file mode 100644
index 0000000000..d48e285bda
--- /dev/null
+++ b/src/imports/workerscript/workerscript.pro
@@ -0,0 +1,11 @@
+CXX_MODULE = qml
+TARGET = workerscriptplugin
+TARGETPATH = QtQml/WorkerScript.2
+IMPORT_VERSION = 2.$$QT_MINOR_VERSION
+
+SOURCES += \
+ plugin.cpp
+
+QT = qml-private qmlworkerscript-private
+
+load(qml_plugin)
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index 383444a808..459797f977 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -290,7 +290,7 @@ struct QV4ParticleData : public QV4::Object
DEFINE_OBJECT_VTABLE(QV4ParticleData);
-class QV4ParticleDataDeletable : public QV8Engine::Deletable
+class QV4ParticleDataDeletable : public QV4::ExecutionEngine::Deletable
{
public:
QV4ParticleDataDeletable(QV4::ExecutionEngine *engine);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index b424ef9f6c..61fea96e2f 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -264,7 +264,7 @@ GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine)
void GatherSourcesJob::run()
{
- for (QV4::CompiledData::CompilationUnit *unit : engine->compilationUnits) {
+ for (QV4::ExecutableCompilationUnit *unit : engine->compilationUnits) {
QString fileName = unit->fileName();
if (!fileName.isEmpty())
sources.append(fileName);
diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
index bac4e01df1..012730902b 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
@@ -48,6 +48,7 @@
#include <private/qversionedpacket_p.h>
#include <QtGui/qwindow.h>
+#include <QtCore/qregularexpression.h>
//INSPECTOR SERVICE PROTOCOL
// <HEADER><COMMAND><DATA>
@@ -273,8 +274,10 @@ QString GlobalInspector::titleForItem(QQuickItem *item) const
QString className = QLatin1String(item->metaObject()->className());
QString objectStringId = idStringForObject(item);
- className.remove(QRegExp(QLatin1String("_QMLTYPE_\\d+")));
- className.remove(QRegExp(QLatin1String("_QML_\\d+")));
+#if QT_CONFIG(regularexpression)
+ className.remove(QRegularExpression(QLatin1String("_QMLTYPE_\\d+")));
+ className.remove(QRegularExpression(QLatin1String("_QML_\\d+")));
+#endif
if (className.startsWith(QLatin1String("QQuick")))
className = className.mid(6);
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index 8293e88038..2d5282b48c 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -355,14 +355,12 @@ void QQmlDebugServerImpl::parseArguments()
if (argsNext == argsItEnd)
break;
if (ok) {
- const QString nextArgument = argsNext->toString();
-
- // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
- // shared copy of the passed string. That copy isn't properly detached when the library
- // is unloaded if the original string lives in the library's .rodata
- if (nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
+ portTo = argsNext->toString().toInt(&ok);
+ if (ok) {
++argsIt;
+ } else {
+ portTo = portFrom;
+ ok = true;
}
}
} else if (strArgument.startsWith(QLatin1String("host:"))) {
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index da3c173545..3291d6e1f5 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -10,7 +10,6 @@ HEADERS += \
$$PWD/qv4compilerscanfunctions_p.h \
$$PWD/qv4codegen_p.h \
$$PWD/qqmlirbuilder_p.h \
- $$PWD/qqmltypecompiler_p.h \
$$PWD/qv4instr_moth_p.h \
$$PWD/qv4bytecodehandler_p.h
@@ -28,17 +27,22 @@ SOURCES += \
!qmldevtools_build {
HEADERS += \
+ $$PWD/qqmlirloader_p.h \
+ $$PWD/qqmlpropertyresolver_p.h \
$$PWD/qqmltypecompiler_p.h \
$$PWD/qqmlpropertycachecreator_p.h \
$$PWD/qqmlpropertyvalidator_p.h \
- $$PWD/qv4compilationunitmapper_p.h
-
+ $$PWD/qv4compilationunitmapper_p.h \
+ $$PWD/qv4executablecompilationunit_p.h
SOURCES += \
+ $$PWD/qqmlirloader.cpp \
+ $$PWD/qqmlpropertyresolver.cpp \
$$PWD/qqmltypecompiler.cpp \
$$PWD/qqmlpropertycachecreator.cpp \
$$PWD/qqmlpropertyvalidator.cpp \
- $$PWD/qv4compilationunitmapper.cpp
+ $$PWD/qv4compilationunitmapper.cpp \
+ $$PWD/qv4executablecompilationunit.cpp
unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp
else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 6e077ec44c..6f46648572 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -48,12 +48,6 @@
#include <QCryptographicHash>
#include <cmath>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlglobal_p.h>
-#include <private/qqmltypeloader_p.h>
-#include <private/qqmlengine_p.h>
-#endif
-
#ifdef CONST
#undef CONST
#endif
@@ -61,11 +55,6 @@
QT_USE_NAMESPACE
static const quint32 emptyStringIndex = 0;
-
-#if 0 //ndef V4_BOOTSTRAP
-DEFINE_BOOL_CONFIG_OPTION(lookupHints, QML_LOOKUP_HINTS);
-#endif // V4_BOOTSTRAP
-
using namespace QmlIR;
#define COMPILE_EXCEPTION(location, desc) \
@@ -1559,20 +1548,12 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
output.jsGenerator.stringTable.registerString(output.jsModule.fileName);
output.jsGenerator.stringTable.registerString(output.jsModule.finalUrl);
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit;
-
- const QV4::CompiledData::Unit *jsUnit = nullptr;
- std::function<QV4::CompiledData::QmlUnit *(QV4::CompiledData::QmlUnit *, uint)> unitFinalizer
- = [](QV4::CompiledData::QmlUnit *unit, uint) {
- return unit;
- };
+ QV4::CompiledData::Unit *jsUnit = nullptr;
// We may already have unit data if we're loading an ahead-of-time generated cache file.
- if (compilationUnit->data) {
- jsUnit = compilationUnit->data;
-#ifndef V4_BOOTSTRAP
- output.javaScriptCompilationUnit->dynamicStrings = output.jsGenerator.stringTable.allStrings();
-#endif
+ if (output.javaScriptCompilationUnit.data) {
+ jsUnit = const_cast<QV4::CompiledData::Unit *>(output.javaScriptCompilationUnit.data);
+ output.javaScriptCompilationUnit.dynamicStrings = output.jsGenerator.stringTable.allStrings();
} else {
QV4::CompiledData::Unit *createdUnit;
jsUnit = createdUnit = output.jsGenerator.generateUnit();
@@ -1584,38 +1565,17 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
break;
}
}
- // This unit's memory was allocated with malloc on the heap, so it's
- // definitely not suitable for StaticData access.
- createdUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
-#ifndef V4_BOOTSTRAP
if (dependencyHasher) {
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (dependencyHasher(&hash)) {
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(createdUnit->dependencyMD5Checksum));
- memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(), sizeof(createdUnit->dependencyMD5Checksum));
+ const QByteArray checksum = dependencyHasher();
+ if (checksum.size() == sizeof(createdUnit->dependencyMD5Checksum)) {
+ memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(),
+ sizeof(createdUnit->dependencyMD5Checksum));
}
}
-#else
- Q_UNUSED(dependencyHasher);
-#endif
+
createdUnit->sourceFileIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.fileName);
createdUnit->finalUrlIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.finalUrl);
-
- // Combine the qml data into the general unit data.
- unitFinalizer = [&jsUnit](QV4::CompiledData::QmlUnit *qmlUnit, uint qmlDataSize) {
- void *ptr = const_cast<QV4::CompiledData::Unit*>(jsUnit);
- QV4::CompiledData::Unit *newUnit = (QV4::CompiledData::Unit *)realloc(ptr, jsUnit->unitSize + qmlDataSize);
- jsUnit = newUnit;
- newUnit->offsetToQmlUnit = newUnit->unitSize;
- newUnit->unitSize += qmlDataSize;
- memcpy(const_cast<QV4::CompiledData::QmlUnit *>(newUnit->qmlUnit()), qmlUnit, qmlDataSize);
- free(const_cast<QV4::CompiledData::QmlUnit*>(qmlUnit));
- qmlUnit = nullptr;
- newUnit->generateChecksum();
- return const_cast<QV4::CompiledData::QmlUnit*>(newUnit->qmlUnit());
- };
}
// No more new strings after this point, we're calculating offsets.
@@ -1782,7 +1742,16 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
}
}
- qmlUnit = unitFinalizer(qmlUnit, totalSize);
+ if (!output.javaScriptCompilationUnit.data) {
+ // Combine the qml data into the general unit data.
+ jsUnit = static_cast<QV4::CompiledData::Unit *>(realloc(jsUnit, jsUnit->unitSize + totalSize));
+ jsUnit->offsetToQmlUnit = jsUnit->unitSize;
+ jsUnit->unitSize += totalSize;
+ memcpy(jsUnit->qmlUnit(), qmlUnit, totalSize);
+ free(qmlUnit);
+ jsUnit->generateChecksum();
+ qmlUnit = jsUnit->qmlUnit();
+ }
static const bool showStats = qEnvironmentVariableIsSet("QML_SHOW_UNIT_STATS");
if (showStats) {
@@ -1806,7 +1775,8 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
qDebug() << " " << totalStringSize << "bytes total strings";
}
- compilationUnit->setUnitData(jsUnit, qmlUnit, output.jsModule.fileName, output.jsModule.finalUrl);
+ output.javaScriptCompilationUnit.setUnitData(jsUnit, qmlUnit, output.jsModule.fileName,
+ output.jsModule.finalUrl);
}
char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const
@@ -1911,214 +1881,3 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
return runtimeFunctionIndices;
}
-
-#ifndef V4_BOOTSTRAP
-
-QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
-
- // Find the first property
- while (d && d->isFunction())
- d = cache->overrideData(d);
-
- if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else {
- return d;
- }
-}
-
-
-QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
- if (notInRevision) *notInRevision = false;
-
- while (d && !(d->isFunction()))
- d = cache->overrideData(d);
-
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else if (d && d->isSignal()) {
- return d;
- }
-
- if (name.endsWith(QLatin1String("Changed"))) {
- QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
-
- d = property(propName, notInRevision);
- if (d)
- return cache->signal(d->notifyIndex());
- }
-
- return nullptr;
-}
-
-IRLoader::IRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
- : unit(qmlData)
- , output(output)
-{
- pool = output->jsParserEngine.pool();
-}
-
-void IRLoader::load()
-{
- output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
-
- const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
-
- for (quint32 i = 0; i < qmlUnit->nImports; ++i)
- output->imports << qmlUnit->importAt(i);
-
- if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
- QmlIR::Pragma *p = New<QmlIR::Pragma>();
- p->location = QV4::CompiledData::Location();
- p->type = QmlIR::Pragma::PragmaSingleton;
- output->pragmas << p;
- }
-
- for (uint i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
- QmlIR::Object *object = loadObject(serializedObject);
- output->objects.append(object);
- }
-}
-
-struct FakeExpression : public QQmlJS::AST::NullExpression
-{
- FakeExpression(int start, int length)
- : location(start, length)
- {}
-
- virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
- { return location; }
-
- virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
- { return location; }
-
-private:
- QQmlJS::AST::SourceLocation location;
-};
-
-QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
-{
- QmlIR::Object *object = pool->New<QmlIR::Object>();
- object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
-
- object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
- object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
- object->flags = serializedObject->flags;
- object->id = serializedObject->id;
- object->location = serializedObject->location;
- object->locationOfIdProperty = serializedObject->locationOfIdProperty;
-
- QVector<int> functionIndices;
- functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
-
- for (uint i = 0; i < serializedObject->nBindings; ++i) {
- QmlIR::Binding *b = pool->New<QmlIR::Binding>();
- *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
- object->bindings->append(b);
- if (b->type == QV4::CompiledData::Binding::Type_Script) {
- functionIndices.append(b->value.compiledScriptIndex);
- b->value.compiledScriptIndex = functionIndices.count() - 1;
-
- QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
- foe->nameIndex = 0;
-
- QQmlJS::AST::ExpressionNode *expr;
-
- if (b->stringIndex != quint32(0)) {
- const int start = output->code.length();
- const QString script = output->stringAt(b->stringIndex);
- const int length = script.length();
- output->code.append(script);
- expr = new (pool) FakeExpression(start, length);
- } else
- expr = new (pool) QQmlJS::AST::NullExpression();
- foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
- object->functionsAndExpressions->append(foe);
- }
- }
-
- Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
-
- for (uint i = 0; i < serializedObject->nSignals; ++i) {
- const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
- QmlIR::Signal *s = pool->New<QmlIR::Signal>();
- s->nameIndex = serializedSignal->nameIndex;
- s->location = serializedSignal->location;
- s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
-
- for (uint i = 0; i < serializedSignal->nParameters; ++i) {
- QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
- *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
- s->parameters->append(p);
- }
-
- object->qmlSignals->append(s);
- }
-
- for (uint i = 0; i < serializedObject->nEnums; ++i) {
- const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
- QmlIR::Enum *e = pool->New<QmlIR::Enum>();
- e->nameIndex = serializedEnum->nameIndex;
- e->location = serializedEnum->location;
- e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
-
- for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
- QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
- *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
- e->enumValues->append(v);
- }
-
- object->qmlEnums->append(e);
- }
-
- const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
- for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
- QmlIR::Property *p = pool->New<QmlIR::Property>();
- *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
- object->properties->append(p);
- }
-
- {
- const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
- for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
- QmlIR::Alias *a = pool->New<QmlIR::Alias>();
- *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
- object->aliases->append(a);
- }
- }
-
- const quint32_le *functionIdx = serializedObject->functionOffsetTable();
- for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
- QmlIR::Function *f = pool->New<QmlIR::Function>();
- const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
-
- functionIndices.append(*functionIdx);
- f->index = functionIndices.count() - 1;
- f->location = compiledFunction->location;
- f->nameIndex = compiledFunction->nameIndex;
-
- f->formals.allocate(pool, int(compiledFunction->nFormals));
- const quint32_le *formalNameIdx = compiledFunction->formalsTable();
- for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
- f->formals[i] = *formalNameIdx;
-
- object->functions->append(f);
- }
-
- object->runtimeFunctionIndices.allocate(pool, functionIndices);
-
- return object;
-}
-
-#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 298fe7dd92..b49eaee420 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -65,11 +65,11 @@ QT_BEGIN_NAMESPACE
class QQmlPropertyCache;
class QQmlContextData;
class QQmlTypeNameCache;
+struct QQmlIRLoader;
namespace QmlIR {
struct Document;
-struct IRLoader;
template <typename T>
struct PoolList
@@ -347,7 +347,7 @@ public:
const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
private:
- friend struct IRLoader;
+ friend struct ::QQmlIRLoader;
PoolList<Property> *properties;
PoolList<Alias> *aliases;
@@ -379,7 +379,7 @@ struct Q_QML_PRIVATE_EXPORT Document
QVector<Object*> objects;
QV4::Compiler::JSUnitGenerator jsGenerator;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> javaScriptCompilationUnit;
+ QV4::CompiledData::CompilationUnit javaScriptCompilationUnit;
int registerString(const QString &str) { return jsGenerator.registerString(str); }
QString stringAt(int index) const { return jsGenerator.stringForIndex(index); }
@@ -508,32 +508,6 @@ private:
char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
};
-#ifndef V4_BOOTSTRAP
-struct Q_QML_EXPORT PropertyResolver
-{
- PropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
- : cache(cache)
- {}
-
- QQmlPropertyData *property(int index) const
- {
- return cache->property(index);
- }
-
- enum RevisionCheck {
- CheckRevision,
- IgnoreRevision
- };
-
- QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr, RevisionCheck check = CheckRevision) const;
-
- // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
- QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
-
- QQmlRefPointer<QQmlPropertyCache> cache;
-};
-#endif
-
struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
{
JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule,
@@ -550,21 +524,6 @@ private:
const QV4::Compiler::StringTableGenerator *stringPool;
};
-struct Q_QML_PRIVATE_EXPORT IRLoader {
- IRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
-
- void load();
-
-private:
- QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
-
- template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
-
- const QV4::CompiledData::Unit *unit;
- QmlIR::Document *output;
- QQmlJS::MemoryPool *pool;
-};
-
} // namespace QmlIR
struct QQmlCompileError
diff --git a/src/qml/compiler/qqmlirloader.cpp b/src/qml/compiler/qqmlirloader.cpp
new file mode 100644
index 0000000000..c2eb6da2fa
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlirloader_p.h"
+#include <private/qqmlirbuilder_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlIRLoader::QQmlIRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
+ : unit(qmlData)
+ , output(output)
+{
+ pool = output->jsParserEngine.pool();
+}
+
+void QQmlIRLoader::load()
+{
+ output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
+
+ const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
+
+ for (quint32 i = 0; i < qmlUnit->nImports; ++i)
+ output->imports << qmlUnit->importAt(i);
+
+ if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
+ QmlIR::Pragma *p = New<QmlIR::Pragma>();
+ p->location = QV4::CompiledData::Location();
+ p->type = QmlIR::Pragma::PragmaSingleton;
+ output->pragmas << p;
+ }
+
+ for (uint i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
+ QmlIR::Object *object = loadObject(serializedObject);
+ output->objects.append(object);
+ }
+}
+
+struct FakeExpression : public QQmlJS::AST::NullExpression
+{
+ FakeExpression(int start, int length)
+ : location(start, length)
+ {}
+
+ virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
+ { return location; }
+
+ virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
+ { return location; }
+
+private:
+ QQmlJS::AST::SourceLocation location;
+};
+
+QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
+{
+ QmlIR::Object *object = pool->New<QmlIR::Object>();
+ object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
+
+ object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
+ object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
+ object->flags = serializedObject->flags;
+ object->id = serializedObject->id;
+ object->location = serializedObject->location;
+ object->locationOfIdProperty = serializedObject->locationOfIdProperty;
+
+ QVector<int> functionIndices;
+ functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
+
+ for (uint i = 0; i < serializedObject->nBindings; ++i) {
+ QmlIR::Binding *b = pool->New<QmlIR::Binding>();
+ *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
+ object->bindings->append(b);
+ if (b->type == QV4::CompiledData::Binding::Type_Script) {
+ functionIndices.append(b->value.compiledScriptIndex);
+ b->value.compiledScriptIndex = functionIndices.count() - 1;
+
+ QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
+ foe->nameIndex = 0;
+
+ QQmlJS::AST::ExpressionNode *expr;
+
+ if (b->stringIndex != quint32(0)) {
+ const int start = output->code.length();
+ const QString script = output->stringAt(b->stringIndex);
+ const int length = script.length();
+ output->code.append(script);
+ expr = new (pool) FakeExpression(start, length);
+ } else
+ expr = new (pool) QQmlJS::AST::NullExpression();
+ foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
+ object->functionsAndExpressions->append(foe);
+ }
+ }
+
+ Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
+
+ for (uint i = 0; i < serializedObject->nSignals; ++i) {
+ const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
+ QmlIR::Signal *s = pool->New<QmlIR::Signal>();
+ s->nameIndex = serializedSignal->nameIndex;
+ s->location = serializedSignal->location;
+ s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
+
+ for (uint i = 0; i < serializedSignal->nParameters; ++i) {
+ QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
+ *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
+ s->parameters->append(p);
+ }
+
+ object->qmlSignals->append(s);
+ }
+
+ for (uint i = 0; i < serializedObject->nEnums; ++i) {
+ const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
+ QmlIR::Enum *e = pool->New<QmlIR::Enum>();
+ e->nameIndex = serializedEnum->nameIndex;
+ e->location = serializedEnum->location;
+ e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
+
+ for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
+ QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
+ *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
+ e->enumValues->append(v);
+ }
+
+ object->qmlEnums->append(e);
+ }
+
+ const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
+ for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
+ QmlIR::Property *p = pool->New<QmlIR::Property>();
+ *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
+ object->properties->append(p);
+ }
+
+ {
+ const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
+ for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
+ QmlIR::Alias *a = pool->New<QmlIR::Alias>();
+ *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
+ object->aliases->append(a);
+ }
+ }
+
+ const quint32_le *functionIdx = serializedObject->functionOffsetTable();
+ for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
+ QmlIR::Function *f = pool->New<QmlIR::Function>();
+ const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
+
+ functionIndices.append(*functionIdx);
+ f->index = functionIndices.count() - 1;
+ f->location = compiledFunction->location;
+ f->nameIndex = compiledFunction->nameIndex;
+
+ f->formals.allocate(pool, int(compiledFunction->nFormals));
+ const quint32_le *formalNameIdx = compiledFunction->formalsTable();
+ for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
+ f->formals[i] = *formalNameIdx;
+
+ object->functions->append(f);
+ }
+
+ object->runtimeFunctionIndices.allocate(pool, functionIndices);
+
+ return object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlirloader_p.h b/src/qml/compiler/qqmlirloader_p.h
new file mode 100644
index 0000000000..aa303c923f
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLIRLOADER_P_H
+#define QQMLIRLOADER_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/qv4compileddata_p.h>
+#include <private/qqmljsmemorypool_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlIR {
+struct Document;
+struct Object;
+}
+
+struct Q_QML_PRIVATE_EXPORT QQmlIRLoader {
+ QQmlIRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
+
+ void load();
+
+private:
+ QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
+
+ template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
+
+ const QV4::CompiledData::Unit *unit;
+ QmlIR::Document *output;
+ QQmlJS::MemoryPool *pool;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLIRLOADER_P_H
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp
index fb54da5b73..bd4f2a0612 100644
--- a/src/qml/compiler/qqmlpropertycachecreator.cpp
+++ b/src/qml/compiler/qqmlpropertycachecreator.cpp
@@ -64,7 +64,9 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty()
Q_ASSERT(instantiatingBinding->propertyNameIndex != 0);
bool notInRevision = false;
- instantiatingProperty = QmlIR::PropertyResolver(referencingObjectPropertyCache).property(instantiatingPropertyName, &notInRevision, QmlIR::PropertyResolver::IgnoreRevision);
+ instantiatingProperty = QQmlPropertyResolver(referencingObjectPropertyCache)
+ .property(instantiatingPropertyName, &notInRevision,
+ QQmlPropertyResolver::IgnoreRevision);
return instantiatingProperty != nullptr;
}
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 346cfb5803..28eea27675 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -53,6 +53,7 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlmetaobject_p.h>
+#include <private/qqmlpropertyresolver_p.h>
QT_BEGIN_NAMESPACE
@@ -323,7 +324,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
int varPropCount = 0;
- QmlIR::PropertyResolver resolver(baseTypeCache);
+ QQmlPropertyResolver resolver(baseTypeCache);
auto p = obj->propertiesBegin();
auto pend = obj->propertiesEnd();
diff --git a/src/qml/compiler/qqmlpropertyresolver.cpp b/src/qml/compiler/qqmlpropertyresolver.cpp
new file mode 100644
index 0000000000..90eaca0b90
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpropertyresolver_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlPropertyData *QQmlPropertyResolver::property(const QString &name, bool *notInRevision,
+ RevisionCheck check) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+
+ // Find the first property
+ while (d && d->isFunction())
+ d = cache->overrideData(d);
+
+ if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else {
+ return d;
+ }
+}
+
+
+QQmlPropertyData *QQmlPropertyResolver::signal(const QString &name, bool *notInRevision) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+ if (notInRevision) *notInRevision = false;
+
+ while (d && !(d->isFunction()))
+ d = cache->overrideData(d);
+
+ if (d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else if (d && d->isSignal()) {
+ return d;
+ }
+
+ if (name.endsWith(QLatin1String("Changed"))) {
+ QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
+
+ d = property(propName, notInRevision);
+ if (d)
+ return cache->signal(d->notifyIndex());
+ }
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlpropertyresolver_p.h b/src/qml/compiler/qqmlpropertyresolver_p.h
new file mode 100644
index 0000000000..df857f242e
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROPERTYRESOLVER_P_H
+#define QQMLPROPERTYRESOLVER_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/qtqmlglobal_p.h>
+#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlrefcount_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_QML_EXPORT QQmlPropertyResolver
+{
+ QQmlPropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
+ : cache(cache)
+ {}
+
+ QQmlPropertyData *property(int index) const
+ {
+ return cache->property(index);
+ }
+
+ enum RevisionCheck {
+ CheckRevision,
+ IgnoreRevision
+ };
+
+ QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr,
+ RevisionCheck check = CheckRevision) const;
+
+ // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
+ QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
+
+ QQmlRefPointer<QQmlPropertyCache> cache;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYRESOLVER_P_H
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 8c06760d42..71d5318652 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -41,11 +41,12 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlstringconverters_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
-QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
+QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit)
: enginePrivate(enginePrivate)
, compilationUnit(compilationUnit)
, imports(imports)
@@ -121,7 +122,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
groupProperties.insert(pos, binding);
}
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QString defaultPropertyName;
QQmlPropertyData *defaultProperty = nullptr;
@@ -164,7 +165,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
pd = propertyResolver.signal(name, &notInRevision);
} else {
pd = propertyResolver.property(name, &notInRevision,
- QmlIR::PropertyResolver::CheckRevision);
+ QQmlPropertyResolver::CheckRevision);
}
if (notInRevision) {
@@ -338,7 +339,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum)
return noError;
- QString value = binding->valueAsString(compilationUnit.data());
+ QString value = compilationUnit->bindingValueAsString(binding);
QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex());
bool ok;
if (p.isFlagType()) {
@@ -396,7 +397,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::UInt: {
if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
if (double(uint(d)) == d)
return noError;
}
@@ -405,7 +406,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Int: {
if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
if (double(int(d)) == d)
return noError;
}
@@ -426,7 +427,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Color: {
bool ok = false;
- QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: color expected"));
}
@@ -435,7 +436,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
#if QT_CONFIG(datestring)
case QVariant::Date: {
bool ok = false;
- QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: date expected"));
}
@@ -443,7 +444,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Time: {
bool ok = false;
- QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: time expected"));
}
@@ -451,7 +452,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::DateTime: {
bool ok = false;
- QQmlStringConverters::dateTimeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: datetime expected"));
}
@@ -460,7 +461,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
#endif // datestring
case QVariant::Point: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -468,7 +469,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::PointF: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -476,7 +477,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Size: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: size expected"));
}
@@ -484,7 +485,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::SizeF: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: size expected"));
}
@@ -492,7 +493,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Rect: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: rect expected"));
}
@@ -500,7 +501,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::RectF: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -517,7 +518,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float xp;
float yp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 2D vector expected"));
}
}
@@ -528,7 +529,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float yp;
float zy;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 3D vector expected"));
}
}
@@ -540,7 +541,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float zy;
float wp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 4D vector expected"));
}
}
@@ -552,7 +553,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float yp;
float zp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: quaternion expected"));
}
}
@@ -570,7 +571,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
} else if (property->propType() == qMetaTypeId<QList<int> >()) {
bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number);
if (ok) {
- double n = binding->valueAsNumber(compilationUnit->constants);
+ double n = compilationUnit->bindingValueAsNumber(binding);
if (double(int(n)) != n)
ok = false;
}
diff --git a/src/qml/compiler/qqmlpropertyvalidator_p.h b/src/qml/compiler/qqmlpropertyvalidator_p.h
index e9ae844ccb..8244b2df21 100644
--- a/src/qml/compiler/qqmlpropertyvalidator_p.h
+++ b/src/qml/compiler/qqmlpropertyvalidator_p.h
@@ -58,7 +58,7 @@ class QQmlPropertyValidator
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
- QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
+ QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit);
QVector<QQmlCompileError> validate();
@@ -72,13 +72,13 @@ private:
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const;
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const;
QString stringAt(int index) const { return compilationUnit->stringAt(index); }
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
}
QQmlEnginePrivate *enginePrivate;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
const QQmlPropertyCacheVector &propertyCaches;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 239f04a58f..66320b8db9 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -44,6 +44,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#define COMPILE_EXCEPTION(token, desc) \
{ \
@@ -55,7 +56,7 @@ QT_BEGIN_NAMESPACE
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
: resolvedTypes(resolvedTypeCache)
, engine(engine)
, typeData(typeData)
@@ -65,7 +66,7 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *type
{
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
+QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
{
// Build property caches and VME meta object data
@@ -133,7 +134,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
return nullptr;
}
- if (!document->javaScriptCompilationUnit) {
+ if (!document->javaScriptCompilationUnit.unitData()) {
// Compile JS binding expressions and signal handlers if necessary
{
// We can compile script strings ahead of time, but they must be compiled
@@ -145,7 +146,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
document->jsModule.fileName = typeData->urlString();
document->jsModule.finalUrl = typeData->finalUrlString();
QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine,
- document->program, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
+ document->program, &document->jsGenerator.stringTable, engine->v4engine()->illegalNames());
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
@@ -158,7 +159,9 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
QmlIR::QmlUnitGenerator qmlGenerator;
qmlGenerator.generate(*document, dependencyHasher);
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
+ = QV4::ExecutableCompilationUnit::create(std::move(
+ document->javaScriptCompilationUnit));
compilationUnit->typeNameCache = typeNameCache;
compilationUnit->resolvedTypes = *resolvedTypes;
compilationUnit->propertyCaches = std::move(m_propertyCaches);
@@ -208,7 +211,7 @@ int QQmlTypeCompiler::registerConstant(QV4::ReturnedValue v)
const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const
{
- return document->javaScriptCompilationUnit->unitData();
+ return document->javaScriptCompilationUnit.unitData();
}
const QQmlImports *QQmlTypeCompiler::imports() const
@@ -252,11 +255,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const
return &document->jsGenerator.stringTable;
}
-void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
-{
- document->javaScriptCompilationUnit->bindingPropertyDataPerObject = propertyData;
-}
-
QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
{
return object->bindingAsString(document, scriptIndex);
@@ -297,7 +295,7 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
, qmlObjects(*typeCompiler->qmlObjects())
, imports(typeCompiler->imports())
, customParsers(typeCompiler->customParserCache())
- , illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
+ , illegalNames(typeCompiler->enginePrivate()->v4engine()->illegalNames())
, propertyCaches(typeCompiler->propertyCaches())
{
}
@@ -357,7 +355,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (!QmlIR::IRBuilder::isSignalPropertyName(propertyName))
continue;
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
Q_ASSERT(propertyName.startsWith(QLatin1String("on")));
propertyName.remove(0, 2);
@@ -513,7 +511,7 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
continue;
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
@@ -722,7 +720,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -754,7 +752,7 @@ void QQmlScriptStringScanner::scan()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -799,7 +797,7 @@ static bool isUsableComponent(const QMetaObject *metaObject)
void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlIR::Object *obj, QQmlPropertyCache *propertyCache)
{
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
@@ -856,7 +854,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
- auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
+ auto typeRef = new QV4::ResolvedTypeReference;
typeRef->type = componentType;
typeRef->majorVersion = componentType.majorVersion();
typeRef->minorVersion = componentType.minorVersion();
@@ -1110,7 +1108,7 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
break;
}
- QmlIR::PropertyResolver resolver(targetCache);
+ QQmlPropertyResolver resolver(targetCache);
QQmlPropertyData *targetProperty = resolver.property(property.toString());
@@ -1224,7 +1222,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QStringList deferredPropertyNames;
{
@@ -1263,7 +1261,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
continue;
bool notInRevision = false;
- pd = propertyResolver.property(name, &notInRevision, QmlIR::PropertyResolver::CheckRevision);
+ pd = propertyResolver.property(name, &notInRevision,
+ QQmlPropertyResolver::CheckRevision);
}
bool seenSubObjectWithId = false;
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index a49b97453f..f588909c42 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -81,7 +81,7 @@ struct QQmlTypeCompiler
public:
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document,
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
// --- interface used by QQmlPropertyCacheCreator
@@ -91,10 +91,10 @@ public:
QString stringAt(int idx) const;
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
+ QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
// ---
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compile();
QList<QQmlError> compilationErrors() const { return errors; }
void recordError(QQmlError error);
@@ -118,7 +118,6 @@ public:
QQmlJS::MemoryPool *memoryPool();
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
- void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -126,7 +125,7 @@ public:
void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{
return resolvedTypes->value(id);
}
@@ -157,12 +156,12 @@ protected:
void recordError(const QQmlCompileError &error)
{ compiler->recordError(error); }
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{ return compiler->resolvedType(id); }
bool containsResolvedType(int id) const
{ return compiler->resolvedTypes->contains(id); }
- QV4::CompiledData::ResolvedTypeReferenceMap::iterator insertResolvedType(
- int id, QV4::CompiledData::ResolvedTypeReference *value)
+ QV4::ResolvedTypeReferenceMap::iterator insertResolvedType(
+ int id, QV4::ResolvedTypeReference *value)
{ return compiler->resolvedTypes->insert(id, value); }
QQmlTypeCompiler *compiler;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 1bf0e7147d..b145ceb51e 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -45,16 +45,15 @@
#include <QtCore/QStack>
#include <QScopeGuard>
#include <private/qqmljsast_p.h>
-#include <private/qv4string_p.h>
+#include <private/qqmljslexer_p.h>
+#include <private/qqmljsparser_p.h>
+#include <private/qv4stringtoarrayindex_p.h>
#include <private/qv4value_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4compilercontrolflow_p.h>
#include <private/qv4bytecodegenerator_p.h>
#include <private/qv4compilerscanfunctions_p.h>
-
-#ifndef V4_BOOTSTRAP
-# include <qqmlerror.h>
-#endif
+#include <qqmlerror.h>
#include <cmath>
#include <iostream>
@@ -1243,7 +1242,7 @@ bool Codegen::visit(ArrayMemberExpression *ast)
return false;
if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) {
QString s = str->value.toString();
- uint arrayIndex = QV4::String::toArrayIndex(s);
+ uint arrayIndex = stringToArrayIndex(s);
if (arrayIndex == UINT_MAX) {
setExprResult(Reference::fromMember(base, str->value.toString()));
return false;
@@ -2513,7 +2512,7 @@ bool Codegen::visit(ObjectPattern *ast)
if (cname || p->type != PatternProperty::Literal)
break;
QString name = p->name->asString();
- uint arrayIndex = QV4::String::toArrayIndex(name);
+ uint arrayIndex = stringToArrayIndex(name);
if (arrayIndex != UINT_MAX)
break;
if (members.contains(name))
@@ -3781,23 +3780,54 @@ QList<QQmlJS::DiagnosticMessage> Codegen::errors() const
return _errors;
}
-QQmlRefPointer<CompiledData::CompilationUnit> Codegen::generateCompilationUnit(bool generateUnitData)
+QV4::CompiledData::CompilationUnit Codegen::generateCompilationUnit(
+ bool generateUnitData)
{
- CompiledData::Unit *unitData = nullptr;
- if (generateUnitData)
- unitData = jsUnitGenerator->generateUnit();
- CompiledData::CompilationUnit *compilationUnit = new CompiledData::CompilationUnit(unitData);
-
- QQmlRefPointer<CompiledData::CompilationUnit> unit;
- unit.adopt(compilationUnit);
- return unit;
+ return QV4::CompiledData::CompilationUnit(
+ generateUnitData ? jsUnitGenerator->generateUnit() : nullptr);
}
-QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading()
+CompiledData::CompilationUnit Codegen::compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
{
- QQmlRefPointer<CompiledData::CompilationUnit> result;
- result.adopt(new CompiledData::CompilationUnit);
- return result;
+ QQmlJS::Engine ee;
+ QQmlJS::Lexer lexer(&ee);
+ lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
+ QQmlJS::Parser parser(&ee);
+
+ const bool parsed = parser.parseModule();
+
+ if (diagnostics)
+ *diagnostics = parser.diagnosticMessages();
+
+ if (!parsed)
+ return CompiledData::CompilationUnit();
+
+ QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
+ if (!moduleNode) {
+ // if parsing was successful, and we have no module, then
+ // the file was empty.
+ if (diagnostics)
+ diagnostics->clear();
+ return nullptr;
+ }
+
+ using namespace QV4::Compiler;
+ Compiler::Module compilerModule(debugMode);
+ compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
+ compilerModule.sourceTimeStamp = sourceTimeStamp;
+ JSUnitGenerator jsGenerator(&compilerModule);
+ Codegen cg(&jsGenerator, /*strictMode*/true);
+ cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
+ auto errors = cg.errors();
+ if (diagnostics)
+ *diagnostics << errors;
+
+ if (!errors.isEmpty())
+ return CompiledData::CompilationUnit();
+
+ return cg.generateCompilationUnit();
}
class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor
@@ -3914,8 +3944,6 @@ Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node
}
-#ifndef V4_BOOTSTRAP
-
QList<QQmlError> Codegen::qmlErrors() const
{
QList<QQmlError> qmlErrors;
@@ -3939,8 +3967,6 @@ QList<QQmlError> Codegen::qmlErrors() const
return qmlErrors;
}
-#endif // V4_BOOTSTRAP
-
bool Codegen::RValue::operator==(const RValue &other) const
{
switch (type) {
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index ad86483132..e519da0142 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -52,12 +52,15 @@
#include "private/qv4global_p.h"
#include <private/qqmljsastvisitor_p.h>
+#include <private/qqmljsengine_p.h>
#include <private/qqmljsast_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4util_p.h>
#include <private/qv4bytecodegenerator_p.h>
-#include <private/qv4stackframe_p.h>
+#include <private/qv4calldata_p.h>
+
+#include <QtQml/qqmlerror.h>
QT_BEGIN_NAMESPACE
@@ -659,9 +662,7 @@ protected:
public:
QList<DiagnosticMessage> errors() const;
-#ifndef V4_BOOTSTRAP
QList<QQmlError> qmlErrors() const;
-#endif
Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right);
Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
@@ -681,8 +682,10 @@ public:
Reference referenceForName(const QString &name, bool lhs, const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation());
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true);
- static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading();
+ QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true);
+ static QV4::CompiledData::CompilationUnit compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<DiagnosticMessage> *diagnostics);
Context *currentContext() const { return _context; }
BytecodeGenerator *generator() const { return bytecodeGenerator; }
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index a78094f17c..0fed0a03b2 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -39,34 +39,12 @@
#include "qv4compileddata_p.h"
#include <private/qv4value_p.h>
-#ifndef V4_BOOTSTRAP
-#include <private/qv4engine_p.h>
-#include <private/qv4function_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qv4lookup_p.h>
-#include <private/qv4regexpobject_p.h>
-#include <private/qv4regexp_p.h>
-#include <private/qqmltypeloader_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qv4vme_moth_p.h>
-#include <private/qv4module_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <private/qqmlvaluetypewrapper_p.h>
-#include "qv4compilationunitmapper_p.h"
-#include <QQmlPropertyMap>
-#include <QDateTime>
-#include <QFile>
-#include <QFileInfo>
-#include <QScopedValueRollback>
-#include <QStandardPaths>
-#include <QDir>
-#include <private/qv4identifiertable_p.h>
-#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QSaveFile>
#include <QScopeGuard>
+#include <QFileInfo>
// generated by qmake:
#include "qml_compile_hash_p.h"
@@ -99,23 +77,13 @@ CompilationUnit::CompilationUnit(const Unit *unitData, const QString &fileName,
CompilationUnit::~CompilationUnit()
{
-#ifndef V4_BOOTSTRAP
- unlink();
-#endif
-
if (data) {
if (data->qmlUnit() != qmlData)
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
-#ifndef V4_BOOTSTRAP
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
-#else
- // Unconditionally free the memory. In the dev tools we create units that have
- // the flag set and will be saved to disk, so intended to persist later.
- free(const_cast<Unit *>(data));
-#endif
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -126,585 +94,11 @@ CompilationUnit::~CompilationUnit()
delete [] imports;
imports = nullptr;
}
-#ifndef V4_BOOTSTRAP
-
-QString CompilationUnit::localCacheFilePath(const QUrl &url)
-{
- const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
- QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
- fileNameHash.addData(localSourcePath.toUtf8());
- QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
- QDir::root().mkpath(directory);
- return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
-}
-
-QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
-{
- this->engine = engine;
- engine->compilationUnits.insert(this);
-
- Q_ASSERT(!runtimeStrings);
- Q_ASSERT(data);
- const quint32 stringCount = totalStringCount();
- runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*));
- // memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*));
- for (uint i = 0; i < stringCount; ++i)
- runtimeStrings[i] = engine->newString(stringAt(i));
-
- runtimeRegularExpressions = new QV4::Value[data->regexpTableSize];
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value));
- for (uint i = 0; i < data->regexpTableSize; ++i) {
- const CompiledData::RegExp *re = data->regexpAt(i);
- uint f = re->flags;
- const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
- runtimeRegularExpressions[i] = QV4::RegExp::create(engine, stringAt(re->stringIndex), flags);
- }
-
- if (data->lookupTableSize) {
- runtimeLookups = new QV4::Lookup[data->lookupTableSize];
- memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
- const CompiledData::Lookup *compiledLookups = data->lookupTable();
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup *l = runtimeLookups + i;
-
- Lookup::Type type = Lookup::Type(uint(compiledLookups[i].type_and_flags));
- if (type == CompiledData::Lookup::Type_Getter)
- l->getter = QV4::Lookup::getterGeneric;
- else if (type == CompiledData::Lookup::Type_Setter)
- l->setter = QV4::Lookup::setterGeneric;
- else if (type == CompiledData::Lookup::Type_GlobalGetter)
- l->globalGetter = QV4::Lookup::globalGetterGeneric;
- else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
- l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
- l->nameIndex = compiledLookups[i].nameIndex;
- }
- }
-
- if (data->jsClassTableSize) {
- runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
- for (uint i = 0; i < data->jsClassTableSize; ++i) {
- int memberCount = 0;
- const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
- runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
- for (int j = 0; j < memberCount; ++j, ++member)
- runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
- }
- }
-
- runtimeFunctions.resize(data->functionTableSize);
- for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
- const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
- runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
- }
-
- Scope scope(engine);
- Scoped<InternalClass> ic(scope);
-
- runtimeBlocks.resize(data->blockTableSize);
- for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
- const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
- ic = engine->internalClasses(EngineBase::Class_CallContext);
-
- // first locals
- const quint32_le *localsIndices = compiledBlock->localsTable();
- for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
- ic = ic->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]), Attr_NotConfigurable);
- runtimeBlocks[i] = ic->d();
- }
-
- static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
- if (showCode) {
- qDebug() << "=== Constant table";
- Moth::dumpConstantTable(constants, data->constantTableSize);
- qDebug() << "=== String table";
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
- qDebug() << "=== Closure table";
- for (uint i = 0; i < data->functionTableSize; ++i)
- qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
- qDebug() << "root function at index " << (data->indexOfRootFunction != -1 ? data->indexOfRootFunction : 0);
- }
-
- if (data->indexOfRootFunction != -1)
- return runtimeFunctions[data->indexOfRootFunction];
- else
- return nullptr;
-}
-
-Heap::Object *CompilationUnit::templateObjectAt(int index) const
-{
- Q_ASSERT(index < int(data->templateObjectTableSize));
- if (!templateObjects.size())
- templateObjects.resize(data->templateObjectTableSize);
- Heap::Object *o = templateObjects.at(index);
- if (o)
- return o;
-
- // create the template object
- Scope scope(engine);
- const CompiledData::TemplateObject *t = data->templateObjectAt(index);
- Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
- Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
- ScopedValue s(scope);
- for (uint i = 0; i < t->size; ++i) {
- s = runtimeStrings[t->stringIndexAt(i)];
- a->arraySet(i, s);
- s = runtimeStrings[t->rawStringIndexAt(i)];
- raw->arraySet(i, s);
- }
-
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
- a->defineReadonlyProperty(QStringLiteral("raw"), raw);
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
-
- templateObjects[index] = a->objectValue()->d();
- return templateObjects.at(index);
-}
-
-void CompilationUnit::unlink()
-{
- if (engine)
- nextCompilationUnit.remove();
-
- if (isRegisteredWithEngine) {
- Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
- if (qmlEngine)
- qmlEngine->unregisterInternalCompositeType(this);
- QQmlMetaType::unregisterInternalCompositeType(this);
- isRegisteredWithEngine = false;
- }
-
- propertyCaches.clear();
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup &l = runtimeLookups[i];
- if (l.getter == QV4::QObjectWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
- pc->release();
- }
-
- if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- }
- }
- }
-
- dependentScripts.clear();
-
- typeNameCache = nullptr;
-
- qDeleteAll(resolvedTypes);
- resolvedTypes.clear();
-
- engine = nullptr;
- qmlEngine = nullptr;
- free(runtimeStrings);
- runtimeStrings = nullptr;
- delete [] runtimeLookups;
- runtimeLookups = nullptr;
- delete [] runtimeRegularExpressions;
- runtimeRegularExpressions = nullptr;
- free(runtimeClasses);
- runtimeClasses = nullptr;
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- f->destroy();
- runtimeFunctions.clear();
-}
-void CompilationUnit::markObjects(QV4::MarkStack *markStack)
-{
- if (runtimeStrings) {
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- if (runtimeStrings[i])
- runtimeStrings[i]->mark(markStack);
- }
- if (runtimeRegularExpressions) {
- for (uint i = 0; i < data->regexpTableSize; ++i)
- runtimeRegularExpressions[i].mark(markStack);
- }
- if (runtimeClasses) {
- for (uint i = 0; i < data->jsClassTableSize; ++i)
- if (runtimeClasses[i])
- runtimeClasses[i]->mark(markStack);
- }
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- if (f && f->internalClass)
- f->internalClass->mark(markStack);
- for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
- if (c)
- c->mark(markStack);
-
- for (QV4::Heap::Object *o : qAsConst(templateObjects))
- if (o)
- o->mark(markStack);
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i)
- runtimeLookups[i].markObjects(markStack);
- }
-
- if (m_module)
- m_module->mark(markStack);
-}
-
-IdentifierHash CompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
-{
- IdentifierHash namedObjectCache(engine);
- const CompiledData::Object *component = objectAt(componentObjectIndex);
- const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
- for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
- const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
- namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
- }
- return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
-}
-
-void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
-{
- this->qmlEngine = qmlEngine;
-
- // Add to type registry of composites
- if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
- QQmlMetaType::registerInternalCompositeType(this);
- qmlEngine->registerInternalCompositeType(this);
- } else {
- const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
- auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
- Q_ASSERT(typeRef);
- if (typeRef->compilationUnit) {
- metaTypeId = typeRef->compilationUnit->metaTypeId;
- listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
- } else {
- metaTypeId = typeRef->type.typeId();
- listMetaTypeId = typeRef->type.qListTypeId();
- }
- }
-
- // Collect some data for instantiation later.
- int bindingCount = 0;
- int parserStatusCount = 0;
- int objectCount = 0;
- for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
- const QV4::CompiledData::Object *obj = objectAt(i);
- bindingCount += obj->nBindings;
- if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid()) {
- if (typeRef->type.parserStatusCast() != -1)
- ++parserStatusCount;
- }
- ++objectCount;
- if (typeRef->compilationUnit) {
- bindingCount += typeRef->compilationUnit->totalBindingsCount;
- parserStatusCount += typeRef->compilationUnit->totalParserStatusCount;
- objectCount += typeRef->compilationUnit->totalObjectCount;
- }
- }
- }
-
- totalBindingsCount = bindingCount;
- totalParserStatusCount = parserStatusCount;
- totalObjectCount = objectCount;
-}
-
-bool CompilationUnit::verifyChecksum(const DependentTypesHasher &dependencyHasher) const
-{
- if (!dependencyHasher) {
- for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) {
- if (data->dependencyMD5Checksum[i] != 0)
- return false;
- }
- return true;
- }
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (!dependencyHasher(&hash))
- return false;
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(data->dependencyMD5Checksum));
- return memcmp(data->dependencyMD5Checksum, checksum.constData(),
- sizeof(data->dependencyMD5Checksum)) == 0;
-}
-
-QStringList CompilationUnit::moduleRequests() const
-{
- QStringList requests;
- requests.reserve(data->moduleRequestTableSize);
- for (uint i = 0; i < data->moduleRequestTableSize; ++i)
- requests << stringAt(data->moduleRequestTable()[i]);
- return requests;
-}
-
-Heap::Module *CompilationUnit::instantiate(ExecutionEngine *engine)
-{
- if (isESModule() && m_module)
- return m_module;
-
- if (data->indexOfRootFunction < 0)
- return nullptr;
-
- if (!this->engine)
- linkToEngine(engine);
-
- Scope scope(engine);
- Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
-
- if (isESModule())
- m_module = module->d();
-
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return nullptr;
- dependentModuleUnit->instantiate(engine);
- }
-
- ScopedString importName(scope);
-
- const uint importCount = data->importEntryTableSize;
- if (importCount > 0) {
- imports = new const Value *[importCount];
- memset(imports, 0, importCount * sizeof(Value *));
- }
- for (uint i = 0; i < importCount; ++i) {
- const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- importName = runtimeStrings[entry.importName];
- const Value *valuePtr = dependentModuleUnit->resolveExport(importName);
- if (!valuePtr) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- imports[i] = valuePtr;
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- ScopedString importName(scope, runtimeStrings[entry.importName]);
- if (!dependentModuleUnit->resolveExport(importName)) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- }
-
- return module->d();
-}
-
-const Value *CompilationUnit::resolveExport(QV4::String *exportName)
-{
- QVector<ResolveSetEntry> resolveSet;
- return resolveExportRecursively(exportName, &resolveSet);
-}
-
-QStringList CompilationUnit::exportedNames() const
-{
- QStringList names;
- QVector<const CompiledData::CompilationUnit*> exportNameSet;
- getExportedNamesRecursively(&names, &exportNameSet);
- names.sort();
- auto last = std::unique(names.begin(), names.end());
- names.erase(last, names.end());
- return names;
-}
-
-const Value *CompilationUnit::resolveExportRecursively(QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
-{
- if (!m_module)
- return nullptr;
-
- for (const auto &entry: *resolveSet)
- if (entry.module == this && entry.exportName->isEqualTo(exportName))
- return nullptr;
-
- (*resolveSet) << ResolveSetEntry(this, exportName);
-
- if (exportName->toQString() == QLatin1String("*"))
- return &m_module->self;
-
- Scope scope(engine);
-
- if (auto localExport = lookupNameInExportTable(data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
- ScopedString localName(scope, runtimeStrings[localExport->localName]);
- uint index = m_module->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
- if (index == UINT_MAX)
- return nullptr;
- if (index >= m_module->scope->locals.size)
- return imports[index - m_module->scope->locals.size];
- return &m_module->scope->locals[index];
- }
-
- if (auto indirectExport = lookupNameInExportTable(data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(indirectExport->moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
- ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
- return dependentModuleUnit->resolveExportRecursively(importName, resolveSet);
- }
-
-
- if (exportName->toQString() == QLatin1String("default"))
- return nullptr;
-
- const Value *starResolution = nullptr;
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet);
- // ### handle ambiguous
- if (resolution) {
- if (!starResolution) {
- starResolution = resolution;
- continue;
- }
- if (resolution != starResolution)
- return nullptr;
- }
- }
-
- return starResolution;
-}
-
-const ExportEntry *CompilationUnit::lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
-{
- const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
- auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
- return stringAt(lhs.exportName) < name->toQString();
- });
- if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
- return nullptr;
- return matchingExport;
-}
-
-void CompilationUnit::getExportedNamesRecursively(QStringList *names, QVector<const CompilationUnit*> *exportNameSet, bool includeDefaultExport) const
-{
- if (exportNameSet->contains(this))
- return;
- exportNameSet->append(this);
-
- const auto append = [names, includeDefaultExport](const QString &name) {
- if (!includeDefaultExport && name == QLatin1String("default"))
- return;
- names->append(name);
- };
-
- for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return;
- dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false);
- }
-}
-
-void CompilationUnit::evaluate()
-{
- QV4::Scope scope(engine);
- QV4::Scoped<Module> module(scope, m_module);
- module->evaluate();
-}
-
-void CompilationUnit::evaluateModuleRequests()
-{
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return;
- dependentModuleUnit->evaluate();
- if (engine->hasException)
- return;
- }
-}
-
-bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
-{
- if (!QQmlFile::isLocalFile(url)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
-
- const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
-
- const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
- for (const QString &cachePath : cachePaths) {
- CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
- if (!mappedUnit)
- continue;
-
- const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
- const Unit *oldData = data;
- auto dataPtrRevert = qScopeGuard([this, oldData](){
- setUnitData(oldData);
- });
- setUnitData(mappedUnit);
-
- if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
- *errorString = QStringLiteral("QML source file has moved to a different location.");
- continue;
- }
-
- dataPtrRevert.dismiss();
- free(const_cast<Unit*>(oldDataPtr));
- backingFile.reset(cacheFile.take());
- return true;
- }
-
- return false;
-}
-
-#endif // V4_BOOTSTRAP
-
-#if defined(V4_BOOTSTRAP)
-bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString)
-#else
-bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
-#endif
+bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString) const
{
errorString->clear();
-#if !defined(V4_BOOTSTRAP)
- if (data->sourceTimeStamp == 0) {
- *errorString = QStringLiteral("Missing time stamp for source file");
- return false;
- }
-
- if (!QQmlFile::isLocalFile(unitUrl)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
- const QString outputFileName = localCacheFilePath(unitUrl);
-#endif
-
#if QT_CONFIG(temporaryfile)
// Foo.qml -> Foo.qmlc
QSaveFile cacheFile(outputFileName);
@@ -713,16 +107,9 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
return false;
}
- QByteArray modifiedUnit;
- modifiedUnit.resize(data->unitSize);
- memcpy(modifiedUnit.data(), data, data->unitSize);
- const char *dataPtr = modifiedUnit.data();
- Unit *unitPtr;
- memcpy(&unitPtr, &dataPtr, sizeof(unitPtr));
- unitPtr->flags |= Unit::StaticData;
-
- qint64 headerWritten = cacheFile.write(modifiedUnit);
- if (headerWritten != modifiedUnit.size()) {
+ SaveableUnitPointer saveable(this);
+ qint64 headerWritten = cacheFile.write(saveable.data<char>(), saveable.size());
+ if (headerWritten != saveable.size()) {
*errorString = cacheFile.errorString();
return false;
}
@@ -770,51 +157,6 @@ void CompilationUnit::setUnitData(const Unit *unitData, const QmlUnit *qmlUnit,
m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
}
-#ifndef V4_BOOTSTRAP
-QString Binding::valueAsString(const CompilationUnit *unit) const
-{
- switch (type) {
- case Type_Script:
- case Type_String:
- return unit->stringAt(stringIndex);
- case Type_Null:
- return QStringLiteral("null");
- case Type_Boolean:
- return value.b ? QStringLiteral("true") : QStringLiteral("false");
- case Type_Number:
- return QString::number(valueAsNumber(unit->constants));
- case Type_Invalid:
- return QString();
-#if !QT_CONFIG(translation)
- case Type_TranslationById:
- case Type_Translation:
- return unit->stringAt(unit->unitData()->translations()[value.translationDataIndex].stringIndex);
-#else
- case Type_TranslationById: {
- const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex];
- QByteArray id = unit->stringAt(translation.stringIndex).toUtf8();
- return qtTrId(id.constData(), translation.number);
- }
- case Type_Translation: {
- const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex];
- // This code must match that in the qsTr() implementation
- const QString &path = unit->fileName();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
- : QStringRef();
- QByteArray contextUtf8 = context.toUtf8();
- QByteArray comment = unit->stringAt(translation.commentIndex).toUtf8();
- QByteArray text = unit->stringAt(translation.stringIndex).toUtf8();
- return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
- comment.constData(), translation.number);
- }
-#endif
- default:
- break;
- }
- return QString();
-}
-
//reverse of Lexer::singleEscape()
QString Binding::escapedString(const QString &string)
{
@@ -858,101 +200,19 @@ QString Binding::escapedString(const QString &string)
return tmp;
}
-QString Binding::valueAsScriptString(const CompilationUnit *unit) const
-{
- if (type == Type_String)
- return escapedString(unit->stringAt(stringIndex));
- else
- return valueAsString(unit);
-}
-
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
-{
- if (type.isValid())
- return typePropertyCache;
- else
- return compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
- return typePropertyCache;
- } else {
- return compilationUnit->rootPropertyCache();
- }
-}
-
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
-{
- if (type.isValid()) {
- bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
- return ok;
- }
- if (!compilationUnit)
- return false;
- hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum));
- return true;
-}
-
-template <typename T>
-bool qtTypeInherits(const QMetaObject *mo) {
- while (mo) {
- if (mo == &T::staticMetaObject)
- return true;
- mo = mo->superClass();
- }
- return false;
-}
-
-void ResolvedTypeReference::doDynamicTypeCheck()
-{
- const QMetaObject *mo = nullptr;
- if (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type.isValid())
- mo = type.metaObject();
- else if (compilationUnit)
- mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
-bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
-{
- for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
- if (!it.value()->addToHash(hash, engine))
- return false;
- }
-
- return true;
-}
-
-#endif
-
-void CompilationUnit::destroy()
+void CompilationUnit::unlink()
{
-#if !defined(V4_BOOTSTRAP)
- if (qmlEngine)
- QQmlEnginePrivate::deleteInEngineThread(qmlEngine, this);
- else
-#endif
- delete this;
+ free(runtimeStrings);
+ runtimeStrings = nullptr;
+ delete [] runtimeRegularExpressions;
+ runtimeRegularExpressions = nullptr;
+ free(runtimeClasses);
+ runtimeClasses = nullptr;
}
-
void Unit::generateChecksum()
{
-#ifndef V4_BOOTSTRAP
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
QCryptographicHash hash(QCryptographicHash::Md5);
const int checksummableDataOffset = offsetof(QV4::CompiledData::Unit, md5Checksum) + sizeof(md5Checksum);
@@ -970,7 +230,6 @@ void Unit::generateChecksum()
bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const
{
-#ifndef V4_BOOTSTRAP
if (strncmp(magic, CompiledData::magic_str, sizeof(magic))) {
*errorString = QStringLiteral("Magic bytes in the header do not match");
return false;
@@ -1008,11 +267,6 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString)
#endif
return true;
-#else
- Q_UNUSED(expectedSourceTimeStamp)
- Q_UNUSED(errorString)
- return false;
-#endif
}
Location &Location::operator=(const QQmlJS::AST::SourceLocation &astLocation)
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index dd7ba471c3..94b64694ae 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -51,12 +51,12 @@
//
#include <QtCore/qstring.h>
+#include <QtCore/qcryptographichash.h>
#include <QVector>
#include <QStringList>
#include <QHash>
#include <QUrl>
-#include <private/qv4value_p.h>
#include <private/qv4executableallocator_p.h>
#include <private/qqmlrefcount_p.h>
#include <private/qqmlnullablevalue_p.h>
@@ -64,11 +64,6 @@
#include <private/qflagpointer_p.h>
#include <private/qendian_p.h>
#include <private/qqmljsastfwd_p.h>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmltypenamecache_p.h>
-#include <private/qqmlpropertycachevector_p.h>
-#include "private/qintrusivelist_p.h"
-#endif
QT_BEGIN_NAMESPACE
@@ -100,7 +95,6 @@ struct Module;
struct Function;
class EvalISelFactory;
-class CompilationUnitMapper;
namespace CompiledData {
@@ -527,17 +521,6 @@ struct Q_QML_PRIVATE_EXPORT Binding
bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; }
bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); }
-#ifndef V4_BOOTSTRAP
- QString valueAsString(const CompilationUnit *unit) const;
- QString valueAsScriptString(const CompilationUnit *unit) const;
-#endif
- double valueAsNumber(const Value *constantTable) const
- {
- if (type != Type_Number)
- return 0.0;
- return constantTable[value.constantValueIndex].doubleValue();
- }
-
bool valueAsBoolean() const
{
if (type == Type_Boolean)
@@ -903,6 +886,10 @@ struct Unit
return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
}
+ QmlUnit *qmlUnit() {
+ return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
+ }
+
bool isSingleton() const {
return flags & Unit::IsSingleton;
}
@@ -1048,20 +1035,7 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
-#ifndef V4_BOOTSTRAP
-struct ResolvedTypeReference;
-// map from name index
-// While this could be a hash, a map is chosen here to provide a stable
-// order, which is used to calculating a check-sum on dependent meta-objects.
-struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
-{
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
-};
-
-using DependentTypesHasher = std::function<bool(QCryptographicHash *)>;
-#else
-struct DependentTypesHasher {};
-#endif
+using DependentTypesHasher = std::function<QByteArray()>;
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
@@ -1070,6 +1044,30 @@ typedef QVector<QQmlPropertyData*> BindingPropertyData;
struct Q_QML_PRIVATE_EXPORT CompilationUnitBase
{
+ Q_DISABLE_COPY(CompilationUnitBase)
+
+ CompilationUnitBase() = default;
+ ~CompilationUnitBase() = default;
+
+ CompilationUnitBase(CompilationUnitBase &&other) noexcept { *this = std::move(other); }
+
+ CompilationUnitBase &operator=(CompilationUnitBase &&other) noexcept
+ {
+ if (this != &other) {
+ runtimeStrings = other.runtimeStrings;
+ other.runtimeStrings = nullptr;
+ constants = other.constants;
+ other.constants = nullptr;
+ runtimeRegularExpressions = other.runtimeRegularExpressions;
+ other.runtimeRegularExpressions = nullptr;
+ runtimeClasses = other.runtimeClasses;
+ other.runtimeClasses = nullptr;
+ imports = other.imports;
+ other.imports = nullptr;
+ }
+ return *this;
+ }
+
// pointers either to data->constants() or little-endian memory copy.
QV4::Heap::String **runtimeStrings = nullptr; // Array
const Value* constants = nullptr;
@@ -1085,105 +1083,48 @@ Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offs
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const Value *));
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const Value *));
-struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase
+struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase
{
+ Q_DISABLE_COPY(CompilationUnit)
+
const Unit *data = nullptr;
const QmlUnit *qmlData = nullptr;
+ QStringList dynamicStrings;
public:
+ using CompiledObject = CompiledData::Object;
+
CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString());
~CompilationUnit();
- void addref()
+ CompilationUnit(CompilationUnit &&other) noexcept
{
- Q_ASSERT(refCount.load() > 0);
- refCount.ref();
+ *this = std::move(other);
}
- void release()
+ CompilationUnit &operator=(CompilationUnit &&other) noexcept
{
- Q_ASSERT(refCount.load() > 0);
- if (!refCount.deref())
- destroy();
- }
- int count() const
- {
- return refCount.load();
+ if (this != &other) {
+ data = other.data;
+ other.data = nullptr;
+ qmlData = other.qmlData;
+ other.qmlData = nullptr;
+ dynamicStrings = std::move(other.dynamicStrings);
+ other.dynamicStrings.clear();
+ m_fileName = std::move(other.m_fileName);
+ other.m_fileName.clear();
+ m_finalUrlString = std::move(other.m_finalUrlString);
+ other.m_finalUrlString.clear();
+ m_module = other.m_module;
+ other.m_module = nullptr;
+ CompilationUnitBase::operator=(std::move(other));
+ }
+ return *this;
}
const Unit *unitData() const { return data; }
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
const QString &fileName = QString(), const QString &finalUrlString = QString());
-#ifndef V4_BOOTSTRAP
- QIntrusiveListNode nextCompilationUnit;
- ExecutionEngine *engine = nullptr;
- QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case.
-
- // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
- // warnings about that code. They include any potential URL interceptions and thus represent the
- // "physical" location of the code.
- //
- // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
- // They are _not_ intercepted and thus represent the "logical" name for the code.
-
- QString fileName() const { return m_fileName; }
- QString finalUrlString() const { return m_finalUrlString; }
- QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
- QUrl finalUrl() const
- {
- if (m_finalUrl.isNull)
- m_finalUrl = QUrl(finalUrlString());
- return m_finalUrl;
- }
-
- QV4::Lookup *runtimeLookups = nullptr;
- QVector<QV4::Function *> runtimeFunctions;
- QVector<QV4::Heap::InternalClass *> runtimeBlocks;
- mutable QVector<QV4::Heap::Object *> templateObjects;
- mutable QQmlNullableValue<QUrl> m_url;
- mutable QQmlNullableValue<QUrl> m_finalUrl;
-
- // QML specific fields
- QQmlPropertyCacheVector propertyCaches;
- QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
-
- QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
-
- // index is object index. This allows fast access to the
- // property data when initializing bindings, avoiding expensive
- // lookups by string (property name).
- QVector<BindingPropertyData> bindingPropertyDataPerObject;
-
- // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
- // this is initialized on-demand by QQmlContextData
- QHash<int, IdentifierHash> namedObjectsPerComponentCache;
- inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
-
- void finalizeCompositeType(QQmlEnginePrivate *qmlEngine);
-
- int totalBindingsCount = 0; // Number of bindings used in this type
- int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
- int totalObjectCount = 0; // Number of objects explicitly instantiated
-
- QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
- ResolvedTypeReferenceMap resolvedTypes;
- ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
-
- bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;
-
- int metaTypeId = -1;
- int listMetaTypeId = -1;
- bool isRegisteredWithEngine = false;
-
- QScopedPointer<CompilationUnitMapper> backingFile;
- QStringList dynamicStrings;
-
- // --- interface for QQmlPropertyCacheCreator
- typedef Object CompiledObject;
- int objectCount() const { return qmlData->nObjects; }
- const Object *objectAt(int index) const { return qmlData->objectAt(index); }
- int importCount() const { return qmlData->nImports; }
- const Import *importAt(int index) const { return qmlData->importAt(index); }
QString stringAt(int index) const
{
if (uint(index) >= data->stringTableSize)
@@ -1191,117 +1132,66 @@ public:
return data->stringAtInternal(index);
}
- Heap::Object *templateObjectAt(int index) const;
-
- struct FunctionIterator
- {
- FunctionIterator(const Unit *unit, const Object *object, int index) : unit(unit), object(object), index(index) {}
- const Unit *unit;
- const Object *object;
- int index;
-
- const Function *operator->() const { return unit->functionAt(object->functionOffsetTable()[index]); }
- void operator++() { ++index; }
- bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
- bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
- };
- FunctionIterator objectFunctionsBegin(const Object *object) const { return FunctionIterator(data, object, 0); }
- FunctionIterator objectFunctionsEnd(const Object *object) const { return FunctionIterator(data, object, object->nFunctions); }
- // ---
+ QString fileName() const { return m_fileName; }
+ QString finalUrlString() const { return m_finalUrlString; }
- bool isESModule() const { return data->flags & Unit::IsESModule; }
- bool isSharedLibrary() const { return data->flags & Unit::IsSharedLibrary; }
- QStringList moduleRequests() const;
- Heap::Module *instantiate(ExecutionEngine *engine);
- const Value *resolveExport(QV4::String *exportName);
- QStringList exportedNames() const;
- void evaluate();
- void evaluateModuleRequests();
+ Heap::Module *module() const { return m_module; }
+ void setModule(Heap::Module *module) { m_module = module; }
- QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
- void markObjects(MarkStack *markStack);
-
- bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
-
- static QString localCacheFilePath(const QUrl &url);
-
-protected:
- quint32 totalStringCount() const
- { return data->stringTableSize; }
-
-#else // V4_BOOTSTRAP
- QString stringAt(int index) const { return data->stringAtInternal(index); }
-#endif // V4_BOOTSTRAP
-
private:
- void destroy();
-
- struct ResolveSetEntry
- {
- ResolveSetEntry() {}
- ResolveSetEntry(CompilationUnit *module, QV4::String *exportName)
- : module(module), exportName(exportName) {}
- CompilationUnit *module = nullptr;
- QV4::String *exportName = nullptr;
- };
-
- const Value *resolveExportRecursively(QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet);
- const ExportEntry *lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const;
- void getExportedNamesRecursively(QStringList *names, QVector<const CompilationUnit *> *exportNameSet, bool includeDefaultExport = true) const;
-
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex
- QAtomicInt refCount = 1;
-
- Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
-
Heap::Module *m_module = nullptr;
public:
-#if defined(V4_BOOTSTRAP)
- bool saveToDisk(const QString &outputFileName, QString *errorString);
-#else
- bool saveToDisk(const QUrl &unitUrl, QString *errorString);
-#endif
+ bool saveToDisk(const QString &outputFileName, QString *errorString) const;
};
-#ifndef V4_BOOTSTRAP
-struct ResolvedTypeReference
+class SaveableUnitPointer
{
- ResolvedTypeReference()
- : majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
- {}
+ Q_DISABLE_COPY_MOVE(SaveableUnitPointer)
+public:
+ SaveableUnitPointer(const CompilationUnit *unit, quint32 temporaryFlags = Unit::StaticData) :
+ unit(unit)
+ {
+ quint32_le &unitFlags = mutableFlags();
+ quint32 origFlags = unitFlags;
+ unitFlags |= temporaryFlags;
+ changedFlags = origFlags ^ unitFlags;
+ }
- QQmlType type;
- QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ ~SaveableUnitPointer()
+ {
+ mutableFlags() ^= changedFlags;
+ }
- int majorVersion;
- int minorVersion;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
+ const CompilationUnit *operator->() const { return unit; }
+ const CompilationUnit &operator*() const { return *unit; }
+ operator const CompilationUnit *() { return unit; }
- QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
- QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+ template<typename Char>
+ const Char *data() const
+ {
+ Q_STATIC_ASSERT(sizeof(Char) == 1);
+ const Char *dataPtr;
+ memcpy(&dataPtr, &unit->data, sizeof(dataPtr));
+ return dataPtr;
+ }
- void doDynamicTypeCheck();
+ quint32 size() const
+ {
+ return unit->data->unitSize;
+ }
+
+private:
+ quint32_le &mutableFlags() { return const_cast<Unit *>(unit->unitData())->flags; };
+ const CompilationUnit *unit;
+ quint32 changedFlags;
};
-IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
-{
- auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
- if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
- return createNamedObjectsPerComponent(componentObjectIndex);
- return *it;
-}
-#endif // V4_BOOTSTRAP
} // CompiledData namespace
} // QV4 namespace
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 123d77f788..4a54e5a44b 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -40,7 +40,6 @@
#include <qv4compiler_p.h>
#include <qv4compileddata_p.h>
#include <qv4codegen_p.h>
-#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
#include <private/qv4alloca_p.h>
#include <private/qqmljslexer_p.h>
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 8984b6931e..ef67a11a70 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -49,7 +49,6 @@
#include <private/qqmljsast_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4codegen_p.h>
-#include <private/qv4string_p.h>
QT_USE_NAMESPACE
using namespace QV4;
diff --git a/src/qml/compiler/qv4executablecompilationunit.cpp b/src/qml/compiler/qv4executablecompilationunit.cpp
new file mode 100644
index 0000000000..97c828d4d8
--- /dev/null
+++ b/src/qml/compiler/qv4executablecompilationunit.cpp
@@ -0,0 +1,809 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4executablecompilationunit_p.h"
+
+#include <private/qv4engine_p.h>
+#include <private/qv4regexp_p.h>
+#include <private/qv4lookup_p.h>
+#include <private/qv4qmlcontext_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4instr_moth_p.h>
+#include <private/qv4objectproto_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qv4qobjectwrapper_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
+#include <private/qv4module_p.h>
+#include <private/qv4compilationunitmapper_p.h>
+
+#include <QtQml/qqmlfile.h>
+#include <QtQml/qqmlpropertymap.h>
+
+#include <QtCore/qdir.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qscopeguard.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+ExecutableCompilationUnit::ExecutableCompilationUnit() = default;
+
+ExecutableCompilationUnit::ExecutableCompilationUnit(
+ CompiledData::CompilationUnit &&compilationUnit)
+ : CompiledData::CompilationUnit(std::move(compilationUnit))
+{}
+
+ExecutableCompilationUnit::~ExecutableCompilationUnit()
+{
+ unlink();
+}
+
+QString ExecutableCompilationUnit::localCacheFilePath(const QUrl &url)
+{
+ const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
+ QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
+ fileNameHash.addData(localSourcePath.toUtf8());
+ QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
+ QDir::root().mkpath(directory);
+ return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
+}
+
+static QString toString(QV4::ReturnedValue v)
+{
+ Value val = Value::fromReturnedValue(v);
+ QString result;
+ if (val.isInt32())
+ result = QLatin1String("int ");
+ else if (val.isDouble())
+ result = QLatin1String("double ");
+ if (val.isEmpty())
+ result += QLatin1String("empty");
+ else
+ result += val.toQStringNoThrow();
+ return result;
+}
+
+static void dumpConstantTable(const Value *constants, uint count)
+{
+ QDebug d = qDebug();
+ d.nospace() << right;
+ for (uint i = 0; i < count; ++i) {
+ d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
+ << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
+ }
+}
+
+QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
+{
+ this->engine = engine;
+ engine->compilationUnits.insert(this);
+
+ Q_ASSERT(!runtimeStrings);
+ Q_ASSERT(data);
+ const quint32 stringCount = totalStringCount();
+ runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*));
+ // memset the strings to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*));
+ for (uint i = 0; i < stringCount; ++i)
+ runtimeStrings[i] = engine->newString(stringAt(i));
+
+ runtimeRegularExpressions
+ = new QV4::Value[data->regexpTableSize];
+ // memset the regexps to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeRegularExpressions, 0,
+ data->regexpTableSize * sizeof(QV4::Value));
+ for (uint i = 0; i < data->regexpTableSize; ++i) {
+ const CompiledData::RegExp *re = data->regexpAt(i);
+ uint f = re->flags;
+ const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
+ runtimeRegularExpressions[i] = QV4::RegExp::create(
+ engine, stringAt(re->stringIndex), flags);
+ }
+
+ if (data->lookupTableSize) {
+ runtimeLookups = new QV4::Lookup[data->lookupTableSize];
+ memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
+ const CompiledData::Lookup *compiledLookups = data->lookupTable();
+ for (uint i = 0; i < data->lookupTableSize; ++i) {
+ QV4::Lookup *l = runtimeLookups + i;
+
+ CompiledData::Lookup::Type type
+ = CompiledData::Lookup::Type(uint(compiledLookups[i].type_and_flags));
+ if (type == CompiledData::Lookup::Type_Getter)
+ l->getter = QV4::Lookup::getterGeneric;
+ else if (type == CompiledData::Lookup::Type_Setter)
+ l->setter = QV4::Lookup::setterGeneric;
+ else if (type == CompiledData::Lookup::Type_GlobalGetter)
+ l->globalGetter = QV4::Lookup::globalGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
+ l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
+ l->nameIndex = compiledLookups[i].nameIndex;
+ }
+ }
+
+ if (data->jsClassTableSize) {
+ runtimeClasses
+ = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize
+ * sizeof(QV4::Heap::InternalClass *));
+ // memset the regexps to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeClasses, 0,
+ data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
+ for (uint i = 0; i < data->jsClassTableSize; ++i) {
+ int memberCount = 0;
+ const CompiledData::JSClassMember *member
+ = data->jsClassAt(i, &memberCount);
+ runtimeClasses[i]
+ = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
+ for (int j = 0; j < memberCount; ++j, ++member)
+ runtimeClasses[i]
+ = runtimeClasses[i]->addMember(
+ engine->identifierTable->asPropertyKey(
+ runtimeStrings[member->nameOffset]),
+ member->isAccessor
+ ? QV4::Attr_Accessor
+ : QV4::Attr_Data);
+ }
+ }
+
+ runtimeFunctions.resize(data->functionTableSize);
+ for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
+ const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
+ runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
+ }
+
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope);
+
+ runtimeBlocks.resize(data->blockTableSize);
+ for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
+ const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
+ ic = engine->internalClasses(EngineBase::Class_CallContext);
+
+ // first locals
+ const quint32_le *localsIndices = compiledBlock->localsTable();
+ for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
+ ic = ic->addMember(
+ engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]),
+ Attr_NotConfigurable);
+ runtimeBlocks[i] = ic->d();
+ }
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
+ if (showCode) {
+ qDebug() << "=== Constant table";
+ dumpConstantTable(constants, data->constantTableSize);
+ qDebug() << "=== String table";
+ for (uint i = 0, end = totalStringCount(); i < end; ++i)
+ qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
+ qDebug() << "=== Closure table";
+ for (uint i = 0; i < data->functionTableSize; ++i)
+ qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
+ qDebug() << "root function at index "
+ << (data->indexOfRootFunction != -1
+ ? data->indexOfRootFunction : 0);
+ }
+
+ if (data->indexOfRootFunction != -1)
+ return runtimeFunctions[data->indexOfRootFunction];
+ else
+ return nullptr;
+}
+
+Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const
+{
+ Q_ASSERT(index < int(data->templateObjectTableSize));
+ if (!templateObjects.size())
+ templateObjects.resize(data->templateObjectTableSize);
+ Heap::Object *o = templateObjects.at(index);
+ if (o)
+ return o;
+
+ // create the template object
+ Scope scope(engine);
+ const CompiledData::TemplateObject *t = data->templateObjectAt(index);
+ Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
+ Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
+ ScopedValue s(scope);
+ for (uint i = 0; i < t->size; ++i) {
+ s = runtimeStrings[t->stringIndexAt(i)];
+ a->arraySet(i, s);
+ s = runtimeStrings[t->rawStringIndexAt(i)];
+ raw->arraySet(i, s);
+ }
+
+ ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
+ a->defineReadonlyProperty(QStringLiteral("raw"), raw);
+ ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
+
+ templateObjects[index] = a->objectValue()->d();
+ return templateObjects.at(index);
+}
+
+void ExecutableCompilationUnit::unlink()
+{
+ if (engine)
+ nextCompilationUnit.remove();
+
+ if (isRegisteredWithEngine) {
+ Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
+ if (qmlEngine)
+ qmlEngine->unregisterInternalCompositeType(this);
+ QQmlMetaType::unregisterInternalCompositeType(this);
+ isRegisteredWithEngine = false;
+ }
+
+ propertyCaches.clear();
+
+ if (runtimeLookups) {
+ for (uint i = 0; i < data->lookupTableSize; ++i) {
+ QV4::Lookup &l = runtimeLookups[i];
+ if (l.getter == QV4::QObjectWrapper::lookupGetter) {
+ if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
+ pc->release();
+ } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
+ if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
+ pc->release();
+ }
+
+ if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
+ if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
+ pc->release();
+ }
+ }
+ }
+
+ dependentScripts.clear();
+
+ typeNameCache = nullptr;
+
+ qDeleteAll(resolvedTypes);
+ resolvedTypes.clear();
+
+ engine = nullptr;
+ qmlEngine = nullptr;
+
+ delete [] runtimeLookups;
+ runtimeLookups = nullptr;
+
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ f->destroy();
+ runtimeFunctions.clear();
+
+ CompiledData::CompilationUnit::unlink();
+}
+
+void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack)
+{
+ if (runtimeStrings) {
+ for (uint i = 0, end = totalStringCount(); i < end; ++i)
+ if (runtimeStrings[i])
+ runtimeStrings[i]->mark(markStack);
+ }
+ if (runtimeRegularExpressions) {
+ for (uint i = 0; i < data->regexpTableSize; ++i)
+ runtimeRegularExpressions[i].mark(markStack);
+ }
+ if (runtimeClasses) {
+ for (uint i = 0; i < data->jsClassTableSize; ++i)
+ if (runtimeClasses[i])
+ runtimeClasses[i]->mark(markStack);
+ }
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ if (f && f->internalClass)
+ f->internalClass->mark(markStack);
+ for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
+ if (c)
+ c->mark(markStack);
+
+ for (QV4::Heap::Object *o : qAsConst(templateObjects))
+ if (o)
+ o->mark(markStack);
+
+ if (runtimeLookups) {
+ for (uint i = 0; i < data->lookupTableSize; ++i)
+ runtimeLookups[i].markObjects(markStack);
+ }
+
+ if (auto mod = module())
+ mod->mark(markStack);
+}
+
+IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
+{
+ IdentifierHash namedObjectCache(engine);
+ const CompiledData::Object *component = objectAt(componentObjectIndex);
+ const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
+ for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
+ const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
+ namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
+ }
+ return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
+}
+
+void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
+{
+ this->qmlEngine = qmlEngine;
+
+ // Add to type registry of composites
+ if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
+ QQmlMetaType::registerInternalCompositeType(this);
+ qmlEngine->registerInternalCompositeType(this);
+ } else {
+ const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
+ auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ if (typeRef->compilationUnit) {
+ metaTypeId = typeRef->compilationUnit->metaTypeId;
+ listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
+ } else {
+ metaTypeId = typeRef->type.typeId();
+ listMetaTypeId = typeRef->type.qListTypeId();
+ }
+ }
+
+ // Collect some data for instantiation later.
+ int bindingCount = 0;
+ int parserStatusCount = 0;
+ int objectCount = 0;
+ for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
+ const QV4::CompiledData::Object *obj = objectAt(i);
+ bindingCount += obj->nBindings;
+ if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
+ if (typeRef->type.isValid()) {
+ if (typeRef->type.parserStatusCast() != -1)
+ ++parserStatusCount;
+ }
+ ++objectCount;
+ if (typeRef->compilationUnit) {
+ bindingCount += typeRef->compilationUnit->totalBindingsCount;
+ parserStatusCount += typeRef->compilationUnit->totalParserStatusCount;
+ objectCount += typeRef->compilationUnit->totalObjectCount;
+ }
+ }
+ }
+
+ totalBindingsCount = bindingCount;
+ totalParserStatusCount = parserStatusCount;
+ totalObjectCount = objectCount;
+}
+
+bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
+{
+ if (!dependencyHasher) {
+ for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) {
+ if (data->dependencyMD5Checksum[i] != 0)
+ return false;
+ }
+ return true;
+ }
+ const QByteArray checksum = dependencyHasher();
+ return checksum.size() == sizeof(data->dependencyMD5Checksum)
+ && memcmp(data->dependencyMD5Checksum, checksum.constData(),
+ sizeof(data->dependencyMD5Checksum)) == 0;
+}
+
+QStringList ExecutableCompilationUnit::moduleRequests() const
+{
+ QStringList requests;
+ requests.reserve(data->moduleRequestTableSize);
+ for (uint i = 0; i < data->moduleRequestTableSize; ++i)
+ requests << stringAt(data->moduleRequestTable()[i]);
+ return requests;
+}
+
+Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine)
+{
+ if (isESModule() && module())
+ return module();
+
+ if (data->indexOfRootFunction < 0)
+ return nullptr;
+
+ if (!this->engine)
+ linkToEngine(engine);
+
+ Scope scope(engine);
+ Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
+
+ if (isESModule())
+ setModule(module->d());
+
+ for (const QString &request: moduleRequests()) {
+ auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
+ if (engine->hasException)
+ return nullptr;
+ dependentModuleUnit->instantiate(engine);
+ }
+
+ ScopedString importName(scope);
+
+ const uint importCount = data->importEntryTableSize;
+ if (importCount > 0) {
+ imports = new const Value *[importCount];
+ memset(imports, 0, importCount * sizeof(Value *));
+ }
+ for (uint i = 0; i < importCount; ++i) {
+ const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ importName = runtimeStrings[entry.importName];
+ const Value *valuePtr = dependentModuleUnit->resolveExport(importName);
+ if (!valuePtr) {
+ QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
+ referenceErrorMessage += importName->toQString();
+ engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ return nullptr;
+ }
+ imports[i] = valuePtr;
+ }
+
+ for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+
+ ScopedString importName(scope, runtimeStrings[entry.importName]);
+ if (!dependentModuleUnit->resolveExport(importName)) {
+ QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
+ referenceErrorMessage += importName->toQString();
+ engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ return nullptr;
+ }
+ }
+
+ return module->d();
+}
+
+const Value *ExecutableCompilationUnit::resolveExportRecursively(
+ QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
+{
+ if (!module())
+ return nullptr;
+
+ for (const auto &entry: *resolveSet)
+ if (entry.module == this && entry.exportName->isEqualTo(exportName))
+ return nullptr;
+
+ (*resolveSet) << ResolveSetEntry(this, exportName);
+
+ if (exportName->toQString() == QLatin1String("*"))
+ return &module()->self;
+
+ Scope scope(engine);
+
+ if (auto localExport = lookupNameInExportTable(
+ data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
+ ScopedString localName(scope, runtimeStrings[localExport->localName]);
+ uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
+ if (index == UINT_MAX)
+ return nullptr;
+ if (index >= module()->scope->locals.size)
+ return imports[index - module()->scope->locals.size];
+ return &module()->scope->locals[index];
+ }
+
+ if (auto indirectExport = lookupNameInExportTable(
+ data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
+ auto dependentModuleUnit = engine->loadModule(urlAt(indirectExport->moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+ ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
+ return dependentModuleUnit->resolveExportRecursively(importName, resolveSet);
+ }
+
+
+ if (exportName->toQString() == QLatin1String("default"))
+ return nullptr;
+
+ const Value *starResolution = nullptr;
+
+ for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+
+ const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet);
+ // ### handle ambiguous
+ if (resolution) {
+ if (!starResolution) {
+ starResolution = resolution;
+ continue;
+ }
+ if (resolution != starResolution)
+ return nullptr;
+ }
+ }
+
+ return starResolution;
+}
+
+const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable(
+ const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
+{
+ const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
+ auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
+ return stringAt(lhs.exportName) < name->toQString();
+ });
+ if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
+ return nullptr;
+ return matchingExport;
+}
+
+void ExecutableCompilationUnit::getExportedNamesRecursively(
+ QStringList *names, QVector<const ExecutableCompilationUnit*> *exportNameSet,
+ bool includeDefaultExport) const
+{
+ if (exportNameSet->contains(this))
+ return;
+ exportNameSet->append(this);
+
+ const auto append = [names, includeDefaultExport](const QString &name) {
+ if (!includeDefaultExport && name == QLatin1String("default"))
+ return;
+ names->append(name);
+ };
+
+ for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
+ append(stringAt(entry.exportName));
+ }
+
+ for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
+ append(stringAt(entry.exportName));
+ }
+
+ for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return;
+ dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false);
+ }
+}
+
+void ExecutableCompilationUnit::evaluate()
+{
+ QV4::Scope scope(engine);
+ QV4::Scoped<Module> mod(scope, module());
+ mod->evaluate();
+}
+
+void ExecutableCompilationUnit::evaluateModuleRequests()
+{
+ for (const QString &request: moduleRequests()) {
+ auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
+ if (engine->hasException)
+ return;
+ dependentModuleUnit->evaluate();
+ if (engine->hasException)
+ return;
+ }
+}
+
+bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
+{
+ if (!QQmlFile::isLocalFile(url)) {
+ *errorString = QStringLiteral("File has to be a local file.");
+ return false;
+ }
+
+ const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
+
+ const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
+ for (const QString &cachePath : cachePaths) {
+ CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
+ if (!mappedUnit)
+ continue;
+
+ const CompiledData::Unit * const oldDataPtr
+ = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data
+ : nullptr;
+ const CompiledData::Unit *oldData = data;
+ auto dataPtrRevert = qScopeGuard([this, oldData](){
+ setUnitData(oldData);
+ });
+ setUnitData(mappedUnit);
+
+ if (data->sourceFileIndex != 0
+ && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
+ *errorString = QStringLiteral("QML source file has moved to a different location.");
+ continue;
+ }
+
+ dataPtrRevert.dismiss();
+ free(const_cast<CompiledData::Unit*>(oldDataPtr));
+ backingFile.reset(cacheFile.take());
+ return true;
+ }
+
+ return false;
+}
+
+bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
+{
+ if (data->sourceTimeStamp == 0) {
+ *errorString = QStringLiteral("Missing time stamp for source file");
+ return false;
+ }
+
+ if (!QQmlFile::isLocalFile(unitUrl)) {
+ *errorString = QStringLiteral("File has to be a local file.");
+ return false;
+ }
+
+ return CompilationUnit::saveToDisk(localCacheFilePath(unitUrl), errorString);
+}
+
+/*!
+Returns the property cache, if one alread exists. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
+{
+ if (type.isValid())
+ return typePropertyCache;
+ else
+ return compilationUnit->rootPropertyCache();
+}
+
+/*!
+Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+{
+ if (typePropertyCache) {
+ return typePropertyCache;
+ } else if (type.isValid()) {
+ typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
+ return typePropertyCache;
+ } else {
+ return compilationUnit->rootPropertyCache();
+ }
+}
+
+bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
+{
+ if (type.isValid()) {
+ bool ok = false;
+ hash->addData(createPropertyCache(engine)->checksum(&ok));
+ return ok;
+ }
+ if (!compilationUnit)
+ return false;
+ hash->addData(compilationUnit->data->md5Checksum,
+ sizeof(compilationUnit->data->md5Checksum));
+ return true;
+}
+
+template <typename T>
+bool qtTypeInherits(const QMetaObject *mo) {
+ while (mo) {
+ if (mo == &T::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+void ResolvedTypeReference::doDynamicTypeCheck()
+{
+ const QMetaObject *mo = nullptr;
+ if (typePropertyCache)
+ mo = typePropertyCache->firstCppMetaObject();
+ else if (type.isValid())
+ mo = type.metaObject();
+ else if (compilationUnit)
+ mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
+}
+
+bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
+{
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ if (!it.value()->addToHash(hash, engine))
+ return false;
+ }
+
+ return true;
+}
+
+QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
+{
+ using namespace CompiledData;
+ switch (binding->type) {
+ case Binding::Type_Script:
+ case Binding::Type_String:
+ return stringAt(binding->stringIndex);
+ case Binding::Type_Null:
+ return QStringLiteral("null");
+ case Binding::Type_Boolean:
+ return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
+ case Binding::Type_Number:
+ return QString::number(bindingValueAsNumber(binding));
+ case Binding::Type_Invalid:
+ return QString();
+#if !QT_CONFIG(translation)
+ case Binding::Type_TranslationById:
+ case Binding::Type_Translation:
+ return unit->stringAt(
+ unit->data->translations()[binding->value.translationDataIndex].stringIndex);
+#else
+ case Binding::Type_TranslationById: {
+ const TranslationData &translation
+ = data->translations()[binding->value.translationDataIndex];
+ QByteArray id = stringAt(translation.stringIndex).toUtf8();
+ return qtTrId(id.constData(), translation.number);
+ }
+ case Binding::Type_Translation: {
+ const TranslationData &translation
+ = data->translations()[binding->value.translationDataIndex];
+ // This code must match that in the qsTr() implementation
+ const QString &path = fileName();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
+ : QStringRef();
+ QByteArray contextUtf8 = context.toUtf8();
+ QByteArray comment = stringAt(translation.commentIndex).toUtf8();
+ QByteArray text = stringAt(translation.stringIndex).toUtf8();
+ return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
+ comment.constData(), translation.number);
+ }
+#endif
+ default:
+ break;
+ }
+ return QString();
+}
+
+QString ExecutableCompilationUnit::bindingValueAsScriptString(
+ const CompiledData::Binding *binding) const
+{
+ return (binding->type == CompiledData::Binding::Type_String)
+ ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
+ : bindingValueAsString(binding);
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4executablecompilationunit_p.h b/src/qml/compiler/qv4executablecompilationunit_p.h
new file mode 100644
index 0000000000..4e3aadf28a
--- /dev/null
+++ b/src/qml/compiler/qv4executablecompilationunit_p.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H
+#define QV4EXECUTABLECOMPILATIONUNIT_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/qv4compileddata_p.h>
+#include <private/qqmlrefcount_p.h>
+#include <private/qintrusivelist_p.h>
+#include <private/qqmlpropertycachevector_p.h>
+#include <private/qqmltype_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEnginePrivate;
+namespace QV4 {
+
+class CompilationUnitMapper;
+struct ResolvedTypeReference;
+// map from name index
+// While this could be a hash, a map is chosen here to provide a stable
+// order, which is used to calculating a check-sum on dependent meta-objects.
+struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
+{
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
+};
+
+class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit,
+ public QQmlRefCount
+{
+ Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit)
+public:
+ friend class QQmlRefPointer<ExecutableCompilationUnit>;
+
+ static QQmlRefPointer<ExecutableCompilationUnit> create(
+ CompiledData::CompilationUnit &&compilationUnit)
+ {
+ return QQmlRefPointer<ExecutableCompilationUnit>(
+ new ExecutableCompilationUnit(std::move(compilationUnit)),
+ QQmlRefPointer<ExecutableCompilationUnit>::Adopt);
+ }
+
+ static QQmlRefPointer<ExecutableCompilationUnit> create()
+ {
+ return QQmlRefPointer<ExecutableCompilationUnit>(
+ new ExecutableCompilationUnit,
+ QQmlRefPointer<ExecutableCompilationUnit>::Adopt);
+ }
+
+ QIntrusiveListNode nextCompilationUnit;
+ ExecutionEngine *engine = nullptr;
+ QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case.
+
+ // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
+ // warnings about that code. They include any potential URL interceptions and thus represent the
+ // "physical" location of the code.
+ //
+ // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
+ // They are _not_ intercepted and thus represent the "logical" name for the code.
+
+ QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
+ QUrl finalUrl() const
+ {
+ if (m_finalUrl.isNull)
+ m_finalUrl = QUrl(finalUrlString());
+ return m_finalUrl;
+ }
+
+ QV4::Lookup *runtimeLookups = nullptr;
+ QVector<QV4::Function *> runtimeFunctions;
+ QVector<QV4::Heap::InternalClass *> runtimeBlocks;
+ mutable QVector<QV4::Heap::Object *> templateObjects;
+ mutable QQmlNullableValue<QUrl> m_url;
+ mutable QQmlNullableValue<QUrl> m_finalUrl;
+
+ // QML specific fields
+ QQmlPropertyCacheVector propertyCaches;
+ QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
+
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
+
+ // index is object index. This allows fast access to the
+ // property data when initializing bindings, avoiding expensive
+ // lookups by string (property name).
+ QVector<CompiledData::BindingPropertyData> bindingPropertyDataPerObject;
+
+ // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
+ // this is initialized on-demand by QQmlContextData
+ QHash<int, IdentifierHash> namedObjectsPerComponentCache;
+ inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
+
+ void finalizeCompositeType(QQmlEnginePrivate *qmlEngine);
+
+ int totalBindingsCount = 0; // Number of bindings used in this type
+ int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
+ int totalObjectCount = 0; // Number of objects explicitly instantiated
+
+ QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
+ ResolvedTypeReferenceMap resolvedTypes;
+ ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
+
+ bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
+
+ int metaTypeId = -1;
+ int listMetaTypeId = -1;
+ bool isRegisteredWithEngine = false;
+
+ QScopedPointer<CompilationUnitMapper> backingFile;
+
+ // --- interface for QQmlPropertyCacheCreator
+ using CompiledObject = CompiledData::Object;
+ using CompiledFunction = CompiledData::Function;
+
+ int objectCount() const { return qmlData->nObjects; }
+ const CompiledObject *objectAt(int index) const
+ {
+ return qmlData->objectAt(index);
+ }
+
+ int importCount() const { return qmlData->nImports; }
+ const CompiledData::Import *importAt(int index) const
+ {
+ return qmlData->importAt(index);
+ }
+
+ Heap::Object *templateObjectAt(int index) const;
+
+ struct FunctionIterator
+ {
+ FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
+ : unit(unit), object(object), index(index) {}
+ const CompiledData::Unit *unit;
+ const CompiledObject *object;
+ int index;
+
+ const CompiledFunction *operator->() const
+ {
+ return unit->functionAt(object->functionOffsetTable()[index]);
+ }
+
+ void operator++() { ++index; }
+ bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
+ bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
+ };
+
+ FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
+ {
+ return FunctionIterator(data, object, 0);
+ }
+
+ FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
+ {
+ return FunctionIterator(data, object, object->nFunctions);
+ }
+
+ bool isESModule() const
+ {
+ return data->flags & CompiledData::Unit::IsESModule;
+ }
+
+ bool isSharedLibrary() const
+ {
+ return data->flags & CompiledData::Unit::IsSharedLibrary;
+ }
+
+ QStringList moduleRequests() const;
+ Heap::Module *instantiate(ExecutionEngine *engine);
+ const Value *resolveExport(QV4::String *exportName)
+ {
+ QVector<ResolveSetEntry> resolveSet;
+ return resolveExportRecursively(exportName, &resolveSet);
+ }
+
+ QStringList exportedNames() const
+ {
+ QStringList names;
+ QVector<const ExecutableCompilationUnit*> exportNameSet;
+ getExportedNamesRecursively(&names, &exportNameSet);
+ names.sort();
+ auto last = std::unique(names.begin(), names.end());
+ names.erase(last, names.end());
+ return names;
+ }
+
+ void evaluate();
+ void evaluateModuleRequests();
+
+ QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
+ void unlink();
+
+ void markObjects(MarkStack *markStack);
+
+ bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
+
+ static QString localCacheFilePath(const QUrl &url);
+ bool saveToDisk(const QUrl &unitUrl, QString *errorString);
+
+ QString bindingValueAsString(const CompiledData::Binding *binding) const;
+ QString bindingValueAsScriptString(const CompiledData::Binding *binding) const;
+ double bindingValueAsNumber(const CompiledData::Binding *binding) const
+ {
+ if (binding->type != CompiledData::Binding::Type_Number)
+ return 0.0;
+ return constants[binding->value.constantValueIndex].doubleValue();
+ }
+
+protected:
+ quint32 totalStringCount() const
+ { return data->stringTableSize; }
+
+private:
+ struct ResolveSetEntry
+ {
+ ResolveSetEntry() {}
+ ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName)
+ : module(module), exportName(exportName) {}
+ ExecutableCompilationUnit *module = nullptr;
+ QV4::String *exportName = nullptr;
+ };
+
+ ExecutableCompilationUnit();
+ ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit);
+ ~ExecutableCompilationUnit();
+
+ const Value *resolveExportRecursively(QV4::String *exportName,
+ QVector<ResolveSetEntry> *resolveSet);
+
+ QUrl urlAt(int index) const { return QUrl(stringAt(index)); }
+
+ Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
+ const CompiledData::ExportEntry *lookupNameInExportTable(
+ const CompiledData::ExportEntry *firstExportEntry, int tableSize,
+ QV4::String *name) const;
+
+ void getExportedNamesRecursively(
+ QStringList *names, QVector<const ExecutableCompilationUnit *> *exportNameSet,
+ bool includeDefaultExport = true) const;
+};
+
+struct ResolvedTypeReference
+{
+ ResolvedTypeReference()
+ : majorVersion(0)
+ , minorVersion(0)
+ , isFullyDynamicType(false)
+ {}
+
+ QQmlType type;
+ QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
+
+ int majorVersion;
+ int minorVersion;
+ // Types such as QQmlPropertyMap can add properties dynamically at run-time and
+ // therefore cannot have a property cache installed when instantiated.
+ bool isFullyDynamicType;
+
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+
+ void doDynamicTypeCheck();
+};
+
+IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
+{
+ auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
+ if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
+ return createNamedObjectsPerComponent(componentObjectIndex);
+ return *it;
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4EXECUTABLECOMPILATIONUNIT_P_H
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 5148154a6a..8a9bd66103 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -39,7 +39,7 @@
#include "qv4instr_moth_p.h"
#include <private/qv4compileddata_p.h>
-#include <private/qv4stackframe_p.h>
+#include <private/qv4calldata_p.h>
using namespace QV4;
using namespace QV4::Moth;
@@ -56,9 +56,7 @@ int InstrInfo::size(Instr::Type type)
static QByteArray alignedNumber(int n) {
QByteArray number = QByteArray::number(n);
- while (number.size() < 8)
- number.prepend(' ');
- return number;
+ return number.prepend(8 - number.size(), ' ');
}
static QByteArray alignedLineNumber(int line) {
@@ -83,25 +81,6 @@ static QByteArray rawBytes(const char *data, int n)
return ba;
}
-static QString toString(QV4::ReturnedValue v)
-{
-#ifdef V4_BOOTSTRAP
- return QStringLiteral("string-const(%1)").arg(v);
-#else // !V4_BOOTSTRAP
- Value val = Value::fromReturnedValue(v);
- QString result;
- if (val.isInt32())
- result = QLatin1String("int ");
- else if (val.isDouble())
- result = QLatin1String("double ");
- if (val.isEmpty())
- result += QLatin1String("empty");
- else
- result += val.toQStringNoThrow();
- return result;
-#endif // V4_BOOTSTRAP
-}
-
#define ABSOLUTE_OFFSET() \
(code - start + offset)
@@ -128,16 +107,6 @@ const int InstrInfo::argumentCount[] = {
FOR_EACH_MOTH_INSTR_ALL(MOTH_COLLECT_NARGS)
};
-
-void dumpConstantTable(const Value *constants, uint count)
-{
- QDebug d = qDebug();
- d.nospace();
- for (uint i = 0; i < count; ++i)
- d << alignedNumber(int(i)).constData() << ": "
- << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
-}
-
QString dumpRegister(int reg, int nFormals)
{
Q_STATIC_ASSERT(offsetof(CallData, function) == 0);
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 35a5fdfba5..5338583164 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
#include <private/qv4global_p.h>
-#include <private/qv4value_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper
#include <qendian.h>
@@ -534,7 +533,6 @@ inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackS
// When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
-void dumpConstantTable(const Value *constants, uint count);
void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1,
const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>());
inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1,
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 2f88aef1fb..9313e4594b 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -90,8 +90,8 @@
"purpose": "Provides a JIT for QML and JavaScript",
"section": "QML",
"condition": [
- " (arch.i386 && tests.pointer_32bit)
- || (arch.x86_64 && tests.pointer_64bit)
+ " (arch.i386 && tests.pointer_32bit && features.sse2)
+ || (arch.x86_64 && tests.pointer_64bit && features.sse2)
|| (arch.arm && tests.pointer_32bit && tests.arm_fp && tests.arm_thumb
&& (config.linux || config.ios || config.tvos || config.qnx))
|| (arch.arm64 && tests.pointer_64bit && tests.arm_fp
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index d01e2bc429..d3eedab1c6 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -171,10 +171,11 @@ public:
: Location(ref->sourceLocation()), locationType(Binding), sent(false)
{
function = ref;
- function->compilationUnit->addref();
+ function->executableCompilationUnit()->addref();
}
- RefLocation(QV4::CompiledData::CompilationUnit *ref, const QUrl &url, const QV4::CompiledData::Object *obj, const QString &type)
+ RefLocation(QV4::ExecutableCompilationUnit *ref, const QUrl &url,
+ const QV4::CompiledData::Object *obj, const QString &type)
: Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
locationType(Creating), sent(false)
{
@@ -230,7 +231,7 @@ public:
switch (locationType) {
case Binding:
- function->compilationUnit->addref();
+ function->executableCompilationUnit()->addref();
break;
case Creating:
unit->addref();
@@ -254,7 +255,7 @@ public:
switch (locationType) {
case Binding:
- function->compilationUnit->release();
+ function->executableCompilationUnit()->release();
break;
case Creating:
unit->release();
@@ -284,7 +285,7 @@ public:
RangeType locationType;
union {
QV4::Function *function;
- QV4::CompiledData::CompilationUnit *unit;
+ QV4::ExecutableCompilationUnit *unit;
QQmlBoundSignalExpression *boundSignal;
QQmlDataBlob *blob;
void *something;
@@ -356,7 +357,7 @@ public:
}
void updateCreating(const QV4::CompiledData::Object *obj,
- QV4::CompiledData::CompilationUnit *ref,
+ QV4::ExecutableCompilationUnit *ref,
const QUrl &url, const QString &type)
{
quintptr locationId(id(obj));
@@ -492,7 +493,7 @@ public:
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
- void update(QV4::CompiledData::CompilationUnit *ref, const QV4::CompiledData::Object *obj,
+ void update(QV4::ExecutableCompilationUnit *ref, const QV4::CompiledData::Object *obj,
const QString &typeName, const QUrl &url)
{
profiler->updateCreating(obj, ref, url, typeName);
diff --git a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
index c4c1b61693..5144fe219e 100644
--- a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
@@ -44,6 +44,10 @@ Basic types can be used to refer to:
\li A value that contains a simple set of property-value pairs (e.g. \l size refers to a value with \c width and \c height attributes)
\endlist
+When a variable or property holds a basic type and it is assigned to another
+variable or property, then a copy of the value is made. In JavaScript, this
+value is called a primitive value.
+
\sa {qtqml-typesystem-topic.html}{The QML Type System}
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index f305213ce2..b9f71b7bd9 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -449,7 +449,7 @@ public:
// r6 is used by MacroAssemblerARMv7
static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8;
static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10;
-#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2)
static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
static const RegisterID EngineRegister = JSC::ARMRegisters::r11;
#else // Thumbs down
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 45ea79d31a..7bf2a4d004 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -41,7 +41,6 @@
#include "qjsengine_p.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "private/qv8engine_p.h"
#include "private/qv4engine_p.h"
#include "private/qv4mm_p.h"
@@ -348,7 +347,6 @@ QJSEngine::QJSEngine(QObject *parent)
: QObject(*new QJSEnginePrivate, parent)
, m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
QJSEnginePrivate::addToDebugServer(this);
@@ -361,7 +359,6 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
: QObject(dd, parent)
, m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
}
@@ -375,7 +372,6 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
QJSEngine::~QJSEngine()
{
QJSEnginePrivate::removeFromDebugServer(this);
- delete m_v4Engine->v8Engine;
delete m_v4Engine;
}
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index a24ee0a188..e6f1079aa7 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -3,6 +3,7 @@ INCLUDEPATH += $$OUT_PWD
!qmldevtools_build {
SOURCES += \
+ $$PWD/qv4engine.cpp \
$$PWD/qv4context.cpp \
$$PWD/qv4persistent.cpp \
$$PWD/qv4lookup.cpp \
@@ -36,13 +37,13 @@ SOURCES += \
$$PWD/qv4reflect.cpp \
$$PWD/qv4regexpobject.cpp \
$$PWD/qv4stackframe.cpp \
+ $$PWD/qv4string.cpp \
$$PWD/qv4stringiterator.cpp \
$$PWD/qv4stringobject.cpp \
$$PWD/qv4variantobject.cpp \
$$PWD/qv4objectiterator.cpp \
$$PWD/qv4regexp.cpp \
$$PWD/qv4runtimecodegen.cpp \
- $$PWD/qv4serialize.cpp \
$$PWD/qv4script.cpp \
$$PWD/qv4symbol.cpp \
$$PWD/qv4setobject.cpp \
@@ -103,13 +104,13 @@ HEADERS += \
$$PWD/qv4regexpobject_p.h \
$$PWD/qv4runtimecodegen_p.h \
$$PWD/qv4stackframe_p.h \
+ $$PWD/qv4string_p.h \
$$PWD/qv4stringiterator_p.h \
$$PWD/qv4stringobject_p.h \
$$PWD/qv4variantobject_p.h \
$$PWD/qv4property_p.h \
$$PWD/qv4objectiterator_p.h \
$$PWD/qv4regexp_p.h \
- $$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
$$PWD/qv4symbol_p.h \
$$PWD/qv4setobject_p.h \
@@ -142,18 +143,17 @@ qtConfig(qml-sequence-object) {
HEADERS += \
+ $$PWD/qv4calldata_p.h \
$$PWD/qv4runtime_p.h \
$$PWD/qv4runtimeapi_p.h \
$$PWD/qv4value_p.h \
- $$PWD/qv4string_p.h \
+ $$PWD/qv4stringtoarrayindex_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4value_p.h \
$$PWD/qv4functiontable_p.h
SOURCES += \
- $$PWD/qv4engine.cpp \
$$PWD/qv4runtime.cpp \
- $$PWD/qv4string.cpp \
$$PWD/qv4value.cpp \
$$PWD/qv4executableallocator.cpp
diff --git a/src/qml/jsruntime/qv4calldata_p.h b/src/qml/jsruntime/qv4calldata_p.h
new file mode 100644
index 0000000000..8487872bf5
--- /dev/null
+++ b/src/qml/jsruntime/qv4calldata_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4CALLDATA_P_H
+#define QV4CALLDATA_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/qv4value_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct CallData
+{
+ enum Offsets {
+ Function = 0,
+ Context = 1,
+ Accumulator = 2,
+ This = 3,
+ NewTarget = 4,
+ Argc = 5,
+
+ LastOffset = Argc,
+ OffsetCount = LastOffset + 1
+ };
+
+ Value function;
+ Value context;
+ Value accumulator;
+ Value thisObject;
+ Value newTarget;
+ Value _argc;
+
+ int argc() const {
+ Q_ASSERT(_argc.isInteger());
+ return _argc.int_32();
+ }
+
+ void setArgc(int argc) {
+ Q_ASSERT(argc >= 0);
+ _argc.setInt_32(argc);
+ }
+
+ inline ReturnedValue argument(int i) const {
+ return i < argc() ? args[i].asReturnedValue() : Value::undefinedValue().asReturnedValue();
+ }
+
+ Value args[1];
+
+ static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
+};
+
+Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
+Q_STATIC_ASSERT(offsetof(CallData, function ) == CallData::Function * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, context ) == CallData::Context * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, accumulator) == CallData::Accumulator * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, thisObject ) == CallData::This * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, newTarget ) == CallData::NewTarget * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, _argc ) == CallData::Argc * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, args ) == 6 * sizeof(Value));
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4CALLDATA_P_H
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index b3bcfe21d5..130727378d 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -60,7 +60,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
{
Function *function = frame->v4Function;
- Heap::InternalClass *ic = function->compilationUnit->runtimeBlocks.at(blockIndex);
+ Heap::InternalClass *ic = function->executableCompilationUnit()->runtimeBlocks.at(blockIndex);
uint nLocals = ic->size;
size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
@@ -76,7 +76,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
c->locals.size = nLocals;
c->locals.alloc = nLocals;
- c->setupLocalTemporalDeadZone(function->compilationUnit->unitData()->blockAt(blockIndex));
+ c->setupLocalTemporalDeadZone(function->executableCompilationUnit()->unitData()->blockAt(blockIndex));
return c;
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index e10bf3cf79..cd77ebd22a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include <qv4engine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
@@ -55,8 +52,6 @@
#include <QRegularExpression>
#endif
-#ifndef V4_BOOTSTRAP
-
#include <qv4qmlcontext_p.h>
#include <qv4value_p.h>
#include <qv4object_p.h>
@@ -107,7 +102,6 @@
#include "qv4dataview_p.h"
#include "qv4promiseobject_p.h"
#include "qv4typedarray_p.h"
-#include <private/qv8engine_p.h>
#include <private/qjsvalue_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
@@ -115,9 +109,16 @@
#include <private/qqmllistwrapper_p.h>
#include <private/qqmllist_p.h>
#include <private/qqmltypeloader_p.h>
+#include <private/qqmlmemoryprofiler_p.h>
+#include <private/qqmlbuiltinfunctions_p.h>
#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
#endif
+#if QT_CONFIG(qml_xml_http_request)
+#include <private/qv4domerrors_p.h>
+#include <private/qqmlxmlhttprequest_p.h>
+#endif
+#include <private/qv4sqlerrors_p.h>
#include <qqmlfile.h>
#if USE(PTHREADS)
@@ -134,14 +135,12 @@
#include <valgrind/memcheck.h>
#endif
-#endif // #ifndef V4_BOOTSTRAP
+Q_DECLARE_METATYPE(QList<int>)
QT_BEGIN_NAMESPACE
using namespace QV4;
-#ifndef V4_BOOTSTRAP
-
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
@@ -151,6 +150,43 @@ ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const
qint32 ExecutionEngine::maxCallDepth = -1;
+template <typename ReturnType>
+ReturnType convertJSValueToVariantType(const QJSValue &value)
+{
+ return value.toVariant().value<ReturnType>();
+}
+
+static void saveJSValue(QDataStream &stream, const void *data)
+{
+ const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
+ quint32 isNullOrUndefined = 0;
+ if (jsv->isNull())
+ isNullOrUndefined |= 0x1;
+ if (jsv->isUndefined())
+ isNullOrUndefined |= 0x2;
+ stream << isNullOrUndefined;
+ if (!isNullOrUndefined)
+ reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
+}
+
+static void restoreJSValue(QDataStream &stream, void *data)
+{
+ QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
+
+ quint32 isNullOrUndefined;
+ stream >> isNullOrUndefined;
+
+ if (isNullOrUndefined & 0x1) {
+ *jsv = QJSValue(QJSValue::NullValue);
+ } else if (isNullOrUndefined & 0x2) {
+ *jsv = QJSValue();
+ } else {
+ QVariant v;
+ v.load(stream);
+ QJSValuePrivate::setVariant(jsv, v);
+ }
+}
+
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -158,7 +194,6 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
, jsStack(new WTF::PageAllocation)
, gcStack(new WTF::PageAllocation)
, globalCode(nullptr)
- , v8Engine(nullptr)
, publicEngine(jsEngine)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(nullptr)
@@ -166,6 +201,10 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
#if QT_CONFIG(qml_jit)
, m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
#endif
+#if QT_CONFIG(qml_xml_http_request)
+ , m_xmlHttpRequestData(nullptr)
+#endif
+ , m_qmlEngine(nullptr)
{
memoryManager = new QV4::MemoryManager(this);
@@ -652,11 +691,28 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
pd->set = thrower();
functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
+
+ QML_MEMORY_SCOPE_STRING("QV4Engine::QV4Engine");
+ qMetaTypeId<QJSValue>();
+ qMetaTypeId<QList<int> >();
+
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
+ QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
+ QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
+ QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
+
+ QV4::QObjectWrapper::initializeBindings(this);
+
+ m_delayedCallQueue.init(this);
}
ExecutionEngine::~ExecutionEngine()
{
modules.clear();
+ qDeleteAll(m_extensionData);
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = nullptr;
delete identifierTable;
@@ -673,6 +729,11 @@ ExecutionEngine::~ExecutionEngine()
delete jsStack;
gcStack->deallocate();
delete gcStack;
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ m_xmlHttpRequestData = nullptr;
+#endif
}
ExecutionContext *ExecutionEngine::currentContext() const
@@ -1682,7 +1743,7 @@ ReturnedValue ExecutionEngine::global()
return globalObject->asReturnedValue();
}
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(const QUrl &url)
+QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const QUrl &url)
{
QFile f(QQmlFile::urlToLocalFileOrQrc(url));
if (!f.open(QIODevice::ReadOnly)) {
@@ -1699,10 +1760,12 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
}
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
+QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(
+ const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
{
QList<QQmlJS::DiagnosticMessage> diagnostics;
- auto unit = compileModule(/*debugMode*/debugger() != nullptr, url.toString(), sourceCode, sourceTimeStamp, &diagnostics);
+ auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
+ sourceCode, sourceTimeStamp, &diagnostics);
for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
if (m.isError()) {
throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
@@ -1712,56 +1775,11 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
<< ": warning: " << m.message;
}
}
- return unit;
-}
-
-#endif // ifndef V4_BOOTSTRAP
-
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(bool debugMode, const QString &url, const QString &sourceCode,
- const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
-{
- QQmlJS::Engine ee;
- QQmlJS::Lexer lexer(&ee);
- lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
- QQmlJS::Parser parser(&ee);
-
- const bool parsed = parser.parseModule();
-
- if (diagnostics)
- *diagnostics = parser.diagnosticMessages();
-
- if (!parsed)
- return nullptr;
-
- QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
- if (!moduleNode) {
- // if parsing was successful, and we have no module, then
- // the file was empty.
- if (diagnostics)
- diagnostics->clear();
- return nullptr;
- }
-
- using namespace QV4::Compiler;
- Compiler::Module compilerModule(debugMode);
- compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
- compilerModule.sourceTimeStamp = sourceTimeStamp;
- JSUnitGenerator jsGenerator(&compilerModule);
- Codegen cg(&jsGenerator, /*strictMode*/true);
- cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
- auto errors = cg.errors();
- if (diagnostics)
- *diagnostics << errors;
-
- if (!errors.isEmpty())
- return nullptr;
- return cg.generateCompilationUnit();
+ return ExecutableCompilationUnit::create(std::move(unit));
}
-#ifndef V4_BOOTSTRAP
-
-void ExecutionEngine::injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit)
+void ExecutionEngine::injectModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit)
{
// Injection can happen from the QML type loader thread for example, but instantiation and
// evaluation must be limited to the ExecutionEngine's thread.
@@ -1769,7 +1787,7 @@ void ExecutionEngine::injectModule(const QQmlRefPointer<CompiledData::Compilatio
modules.insert(moduleUnit->finalUrl(), moduleUnit);
}
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer) const
+QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer) const
{
QUrl url = QQmlTypeLoader::normalize(_url);
if (referrer)
@@ -1782,7 +1800,7 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::moduleForUrl(cons
return *existingModule;
}
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer)
+QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer)
{
QUrl url = QQmlTypeLoader::normalize(_url);
if (referrer)
@@ -1804,6 +1822,133 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::loadModule(const
return newModule;
}
+void ExecutionEngine::initQmlGlobalObject()
+{
+ initializeGlobal();
+ freezeObject(*globalObject);
+}
+
+void ExecutionEngine::initializeGlobal()
+{
+ QV4::Scope scope(this);
+ QV4::GlobalExtensions::init(globalObject, QJSEngine::AllExtensions);
+
+ QV4::ScopedObject qt(scope, memoryManager->allocate<QV4::QtObject>(qmlEngine()));
+ globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+
+#if QT_CONFIG(qml_locale)
+ QQmlLocale::registerStringLocaleCompare(this);
+ QQmlDateExtension::registerExtension(this);
+ QQmlNumberExtension::registerExtension(this);
+#endif
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_add_domexceptions(this);
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+#endif
+
+ qt_add_sqlexceptions(this);
+
+ {
+ for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
+ if (globalObject->internalClass()->nameMap.at(i).isString()) {
+ QV4::PropertyKey id = globalObject->internalClass()->nameMap.at(i);
+ m_illegalNames.insert(id.toQString());
+ }
+ }
+ }
+}
+
+const QSet<QString> &ExecutionEngine::illegalNames() const
+{
+ return m_illegalNames;
+}
+
+void ExecutionEngine::setQmlEngine(QQmlEngine *engine)
+{
+ m_qmlEngine = engine;
+ initQmlGlobalObject();
+}
+
+static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
+{
+ if (object->as<QV4::QObjectWrapper>())
+ return;
+
+ QV4::Scope scope(v4);
+
+ bool instanceOfObject = false;
+ QV4::ScopedObject p(scope, object->getPrototypeOf());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->getPrototypeOf();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ if (object->internalClass() == frozen)
+ return;
+ object->setInternalClass(frozen);
+
+ QV4::ScopedObject o(scope);
+ for (uint i = 0; i < frozen->size; ++i) {
+ if (!frozen->nameMap.at(i).isStringOrSymbol())
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
+ }
+}
+
+void ExecutionEngine::freezeObject(const QV4::Value &value)
+{
+ QV4::Scope scope(this);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(this, o);
+}
+
+void ExecutionEngine::startTimer(const QString &timerName)
+{
+ if (!m_time.isValid())
+ m_time.start();
+ m_startedTimers[timerName] = m_time.elapsed();
+}
+
+qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
+{
+ if (!m_startedTimers.contains(timerName)) {
+ *wasRunning = false;
+ return 0;
+ }
+ *wasRunning = true;
+ qint64 startedAt = m_startedTimers.take(timerName);
+ return m_time.elapsed() - startedAt;
+}
+
+int ExecutionEngine::consoleCountHelper(const QString &file, quint16 line, quint16 column)
+{
+ const QString key = file + QString::number(line) + QString::number(column);
+ int number = m_consoleCount.value(key, 0);
+ number++;
+ m_consoleCount.insert(key, number);
+ return number;
+}
+
+void ExecutionEngine::setExtensionData(int index, Deletable *data)
+{
+ if (m_extensionData.count() <= index)
+ m_extensionData.resize(index + 1);
+
+ if (m_extensionData.at(index))
+ delete m_extensionData.at(index);
+
+ m_extensionData[index] = data;
+}
+
// 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.
@@ -2050,6 +2195,23 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &v
return wrapper->object();
}
-#endif // ifndef V4_BOOTSTRAP
+struct QV4EngineRegistrationData
+{
+ QV4EngineRegistrationData() : extensionCount(0) {}
+
+ QMutex mutex;
+ int extensionCount;
+};
+Q_GLOBAL_STATIC(QV4EngineRegistrationData, registrationData);
+
+QMutex *ExecutionEngine::registrationMutex()
+{
+ return &registrationData()->mutex;
+}
+
+int ExecutionEngine::registerExtension()
+{
+ return registrationData()->extensionCount++;
+}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index d0c58eee8f..f8ac0e0268 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -53,25 +53,83 @@
#include "qv4global_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4stackframe_p.h"
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
#include <private/qqmlrefcount_p.h>
#include <private/qqmljsengine_p.h>
+#include <private/qqmldelayedcallqueue_p.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmutex.h>
-#ifndef V4_BOOTSTRAP
-# include "qv4function_p.h"
-# include <private/qv8engine_p.h>
-# include <private/qv4compileddata_p.h>
-#endif
+#include "qv4function_p.h"
+#include <private/qv4compileddata_p.h>
+#include <private/qv4executablecompilationunit_p.h>
namespace WTF {
class BumpPointerAllocator;
class PageAllocation;
}
+#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
+ static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
+ { \
+ static int extensionId = -1; \
+ if (extensionId == -1) { \
+ QV4::ExecutionEngine::registrationMutex()->lock(); \
+ if (extensionId == -1) \
+ extensionId = QV4::ExecutionEngine::registerExtension(); \
+ QV4::ExecutionEngine::registrationMutex()->unlock(); \
+ } \
+ dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
+ if (!rv) { \
+ rv = new dataclass(engine); \
+ engine->setExtensionData(extensionId, rv); \
+ } \
+ return rv; \
+ } \
+
+
QT_BEGIN_NAMESPACE
-class QV8Engine;
+namespace QV4 { struct QObjectMethod; }
+
+// 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(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 QQmlV4Function
+{
+public:
+ int length() const { return callData->argc(); }
+ QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
+ void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
+ QV4::ExecutionEngine *v4engine() const { return e; }
+private:
+ friend struct QV4::QObjectMethod;
+ QQmlV4Function();
+ QQmlV4Function(const QQmlV4Function &);
+ QQmlV4Function &operator=(const QQmlV4Function &);
+
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
+ {
+ callData->thisObject = QV4::Encode::undefined();
+ }
+
+ QV4::CallData *callData;
+ QV4::Value *retVal;
+ QV4::ExecutionEngine *e;
+};
+
class QQmlError;
class QJSEngine;
class QQmlEngine;
@@ -128,14 +186,8 @@ public:
Function *globalCode;
-#ifdef V4_BOOTSTRAP
- QJSEngine *jsEngine() const;
- QQmlEngine *qmlEngine() const;
-#else // !V4_BOOTSTRAP
QJSEngine *jsEngine() const { return publicEngine; }
- QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
-#endif // V4_BOOTSTRAP
- QV8Engine *v8Engine;
+ QQmlEngine *qmlEngine() const { return m_qmlEngine; }
QJSEngine *publicEngine;
enum JSObjects {
@@ -438,9 +490,7 @@ public:
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
-#ifndef V4_BOOTSTRAP
- QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
-#endif
+ QIntrusiveList<ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit> compilationUnits;
quint32 m_engineId;
@@ -608,30 +658,82 @@ public:
}
QV4::ReturnedValue global();
+ void initQmlGlobalObject();
+ void initializeGlobal();
+
+ void freezeObject(const QV4::Value &value);
+
+ // Return the list of illegal id names (the names of the properties on the global object)
+ const QSet<QString> &illegalNames() const;
+
+#if QT_CONFIG(qml_xml_http_request)
+ void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
+#endif
+
+ void setQmlEngine(QQmlEngine *engine);
+
+ QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
+
+ // used for console.time(), console.timeEnd()
+ void startTimer(const QString &timerName);
+ qint64 stopTimer(const QString &timerName, bool *wasRunning);
+
+ // used for console.count()
+ int consoleCountHelper(const QString &file, quint16 line, quint16 column);
+
+ struct Deletable {
+ virtual ~Deletable() {}
+ };
+
+ static QMutex *registrationMutex();
+ static int registerExtension();
+
+ void setExtensionData(int, Deletable *);
+ Deletable *extensionData(int index) const
+ {
+ if (index < m_extensionData.count())
+ return m_extensionData[index];
+ else
+ return nullptr;
+ }
double localTZA = 0.0; // local timezone, initialized at startup
- static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
-#ifndef V4_BOOTSTRAP
- QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url);
- QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
+ QQmlRefPointer<ExecutableCompilationUnit> compileModule(const QUrl &url);
+ QQmlRefPointer<ExecutableCompilationUnit> compileModule(
+ const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
mutable QMutex moduleMutex;
- QHash<QUrl, QQmlRefPointer<CompiledData::CompilationUnit>> modules;
- void injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit);
- QQmlRefPointer<CompiledData::CompilationUnit> moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const;
- QQmlRefPointer<CompiledData::CompilationUnit> loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr);
-#endif
+ QHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> modules;
+ void injectModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit);
+ QQmlRefPointer<ExecutableCompilationUnit> moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
+ QQmlRefPointer<ExecutableCompilationUnit> loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
+ QSet<QString> m_illegalNames;
int jitCallCountThreshold;
// used by generated Promise objects to handle 'then' events
QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
+
+#if QT_CONFIG(qml_xml_http_request)
+ void *m_xmlHttpRequestData;
+#endif
+
+ QQmlEngine *m_qmlEngine;
+
+ QQmlDelayedCallQueue m_delayedCallQueue;
+
+ QElapsedTimer m_time;
+ QHash<QString, qint64> m_startedTimers;
+
+ QHash<QString, quint32> m_consoleCount;
+
+ QVector<Deletable *> m_extensionData;
};
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 82eccd9f3c..788897bdad 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -79,9 +79,6 @@ struct Q_QML_EXPORT EngineBase {
#elif defined(Q_ATOMIC_INT16_IS_SUPPORTED)
quint8 unused = 0;
QAtomicInteger<quint16> isInterrupted = false;
-#elif defined(V4_BOOTSTRAP)
- // We don't need the isInterrupted flag when bootstrapping.
- quint8 unused[3];
#else
# error V4 needs either 8bit or 16bit atomics.
#endif
@@ -150,10 +147,7 @@ Q_STATIC_ASSERT(offsetof(EngineBase, jsStackTop) == offsetof(EngineBase, current
Q_STATIC_ASSERT(offsetof(EngineBase, hasException) == offsetof(EngineBase, jsStackTop) + QT_POINTER_SIZE);
Q_STATIC_ASSERT(offsetof(EngineBase, memoryManager) == offsetof(EngineBase, hasException) + 8);
Q_STATIC_ASSERT(offsetof(EngineBase, runtime) == offsetof(EngineBase, memoryManager) + QT_POINTER_SIZE);
-
-#ifndef V4_BOOTSTRAP
Q_STATIC_ASSERT(offsetof(EngineBase, isInterrupted) + sizeof(EngineBase::isInterrupted) <= offsetof(EngineBase, hasException) + 4);
-#endif
}
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index debdf23d27..d870cec68a 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -73,7 +73,8 @@ ReturnedValue Function::call(const Value *thisObject, const Value *argv, int arg
return result;
}
-Function *Function::create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
+Function *Function::create(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
+ const CompiledData::Function *function)
{
return new Function(engine, unit, function);
}
@@ -83,7 +84,8 @@ void Function::destroy()
delete this;
}
-Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
+Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
+ const CompiledData::Function *function)
: FunctionData(unit)
, compiledFunction(function)
, codeData(function->code())
@@ -146,8 +148,11 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
// first locals
const quint32_le *localsIndices = compiledFunction->localsTable();
- for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
- internalClass = internalClass->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
+ for (quint32 i = 0; i < compiledFunction->nLocals; ++i) {
+ internalClass = internalClass->addMember(
+ engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]),
+ Attr_NotConfigurable);
+ }
Scope scope(engine);
ScopedString arg(scope);
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 01b212370d..cbbb61c68c 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -51,7 +51,7 @@
//
#include "qv4global_p.h"
-#include <private/qv4compileddata_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#include <private/qv4context_p.h>
namespace JSC {
@@ -65,9 +65,13 @@ struct QQmlSourceLocation;
namespace QV4 {
struct Q_QML_EXPORT FunctionData {
- CompiledData::CompilationUnit *compilationUnit;
+ CompiledData::CompilationUnitBase *compilationUnit;
- FunctionData(CompiledData::CompilationUnit *compilationUnit)
+ // Intentionally require an ExecutableCompilationUnit but save only a pointer to
+ // CompilationUnitBase. This is so that we can take advantage of the standard layout
+ // of CompilationUnitBase in the JIT. Furthermore we can safely static_cast to
+ // ExecutableCompilationUnit where we need it.
+ FunctionData(ExecutableCompilationUnit *compilationUnit)
: compilationUnit(compilationUnit)
{}
};
@@ -76,12 +80,24 @@ Q_STATIC_ASSERT(std::is_standard_layout< FunctionData >::value);
struct Q_QML_EXPORT Function : public FunctionData {
private:
- Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function);
+ Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
+ const CompiledData::Function *function);
~Function();
public:
const CompiledData::Function *compiledFunction;
+ QV4::ExecutableCompilationUnit *executableCompilationUnit() const
+ {
+ // This is safe: We require an ExecutableCompilationUnit in the ctor.
+ return static_cast<QV4::ExecutableCompilationUnit *>(compilationUnit);
+ }
+
+ QV4::Heap::String *runtimeString(uint i)
+ {
+ return compilationUnit->runtimeStrings[i];
+ }
+
ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context);
const char *codeData;
@@ -96,7 +112,8 @@ public:
int interpreterCallCount = 0;
bool isEval = false;
- static Function *create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function);
+ static Function *create(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
+ const CompiledData::Function *function);
void destroy();
// used when dynamically assigning signal handlers (QQmlConnection)
@@ -108,8 +125,8 @@ public:
static QString prettyName(const Function *function, const void *address);
- inline QString sourceFile() const { return compilationUnit->fileName(); }
- inline QUrl finalUrl() const { return compilationUnit->finalUrl(); }
+ inline QString sourceFile() const { return executableCompilationUnit()->fileName(); }
+ inline QUrl finalUrl() const { return executableCompilationUnit()->finalUrl(); }
inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; }
inline bool isArrowFunction() const { return compiledFunction->flags & CompiledData::Function::IsArrowFunction; }
@@ -121,7 +138,7 @@ public:
{
if (compiledFunction->nestedFunctionIndex == std::numeric_limits<uint32_t>::max())
return nullptr;
- return compilationUnit->runtimeFunctions[compiledFunction->nestedFunctionIndex];
+ return executableCompilationUnit()->runtimeFunctions[compiledFunction->nestedFunctionIndex];
}
};
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 41a21ba379..b1b0d67e64 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -135,13 +135,13 @@ void Heap::FunctionObject::setFunction(Function *f)
{
if (f) {
function = f;
- function->compilationUnit->addref();
+ function->executableCompilationUnit()->addref();
}
}
void Heap::FunctionObject::destroy()
{
if (function)
- function->compilationUnit->release();
+ function->executableCompilationUnit()->release();
Object::destroy();
}
@@ -229,7 +229,7 @@ void Heap::FunctionCtor::init(QV4::ExecutionContext *scope)
}
// 15.3.2
-QQmlRefPointer<CompiledData::CompilationUnit> FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t)
+QQmlRefPointer<ExecutableCompilationUnit> FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t)
{
QString arguments;
QString body;
@@ -273,14 +273,15 @@ QQmlRefPointer<CompiledData::CompilationUnit> FunctionCtor::parse(ExecutionEngin
if (engine->hasException)
return nullptr;
- return cg.generateCompilationUnit();
+ return ExecutableCompilationUnit::create(cg.generateCompilationUnit());
}
ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *engine = f->engine();
- QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Function);
+ QQmlRefPointer<ExecutableCompilationUnit> compilationUnit
+ = parse(engine, argv, argc, Type_Function);
if (engine->hasException)
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 4fee26f341..c99cad8e33 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -244,7 +244,7 @@ protected:
Type_Function,
Type_Generator
};
- static QQmlRefPointer<CompiledData::CompilationUnit> parse(ExecutionEngine *engine, const Value *argv, int argc, Type t = Type_Function);
+ static QQmlRefPointer<ExecutableCompilationUnit> parse(ExecutionEngine *engine, const Value *argv, int argc, Type t = Type_Function);
};
struct FunctionPrototype: FunctionObject
diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp
index 14caa6953f..4eee6f4338 100644
--- a/src/qml/jsruntime/qv4generatorobject.cpp
+++ b/src/qml/jsruntime/qv4generatorobject.cpp
@@ -58,7 +58,7 @@ ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObje
{
ExecutionEngine *engine = f->engine();
- QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Generator);
+ QQmlRefPointer<ExecutableCompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Generator);
if (engine->hasException)
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 3c732bc555..c0885a418c 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -72,13 +72,17 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_resultObject.set(v4, resultValue(v4));
#if QT_CONFIG(qml_network)
- m_network = engine->v8Engine->networkAccessManager();
+ if (QQmlEngine *qmlEngine = engine->qmlEngine()) {
+ m_network = qmlEngine->networkAccessManager();
- QNetworkRequest request;
- request.setUrl(url);
+ QNetworkRequest request;
+ request.setUrl(url);
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ } else {
+ finished();
+ }
#else
finished();
#endif
@@ -197,7 +201,7 @@ void QV4Include::finished()
}
/*
- Documented in qv8engine.cpp
+ Documented in qv4engine.cpp
*/
QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
{
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index f2e0afd797..94bf1a98ae 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -54,11 +54,8 @@
#include "qv4runtime_p.h"
#include "qv4engine_p.h"
#include "qv4context_p.h"
-
-#if !defined(V4_BOOTSTRAP)
#include "qv4object_p.h"
#include "qv4internalclass_p.h"
-#endif
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index d85b30a056..4f22dc7330 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -54,7 +54,6 @@
#include "qv4value_p.h"
#include "qv4enginebase_p.h"
#include <private/qv4heap_p.h>
-#include <private/qv4writebarrier_p.h>
#include <private/qv4vtable_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index f327c85001..ffebe1b5da 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -72,8 +72,8 @@ Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberD
// The above code can overflow in a number of interesting ways. All of those are unsigned,
// and therefore defined behavior. Still, apply some sane bounds.
- if (alloc > std::numeric_limits<int>::max())
- alloc = std::numeric_limits<int>::max();
+ if (alloc > size_t(std::numeric_limits<int>::max()))
+ alloc = size_t(std::numeric_limits<int>::max());
Heap::MemberData *m;
if (old) {
diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp
index 237ada8321..08a1900383 100644
--- a/src/qml/jsruntime/qv4module.cpp
+++ b/src/qml/jsruntime/qv4module.cpp
@@ -52,7 +52,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Module);
-void Heap::Module::init(ExecutionEngine *engine, CompiledData::CompilationUnit *moduleUnit)
+void Heap::Module::init(ExecutionEngine *engine, ExecutableCompilationUnit *moduleUnit)
{
Object::init();
@@ -106,7 +106,7 @@ void Module::evaluate()
return;
d()->evaluated = true;
- CompiledData::CompilationUnit *unit = d()->unit;
+ ExecutableCompilationUnit *unit = d()->unit;
unit->evaluateModuleRequests();
diff --git a/src/qml/jsruntime/qv4module_p.h b/src/qml/jsruntime/qv4module_p.h
index dca0678fe9..aabb2e005e 100644
--- a/src/qml/jsruntime/qv4module_p.h
+++ b/src/qml/jsruntime/qv4module_p.h
@@ -60,7 +60,7 @@ namespace QV4 {
namespace Heap {
#define ModuleMembers(class, Member) \
- Member(class, NoMark, CompiledData::CompilationUnit *, unit) \
+ Member(class, NoMark, ExecutableCompilationUnit *, unit) \
Member(class, Pointer, CallContext *, scope) \
Member(class, HeapValue, HeapValue, self) \
Member(class, NoMark, bool, evaluated)
@@ -68,7 +68,7 @@ namespace Heap {
DECLARE_EXPORTED_HEAP_OBJECT(Module, Object) {
DECLARE_MARKOBJECTS(Module)
- void init(ExecutionEngine *engine, CompiledData::CompilationUnit *moduleUnit);
+ void init(ExecutionEngine *engine, ExecutableCompilationUnit *moduleUnit);
};
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 206b410cf4..89161433ed 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -93,7 +93,7 @@ void Heap::Object::setUsedAsProto()
internalClass.set(internalClass->engine, internalClass->asProtoClass());
}
-ReturnedValue Object::getValueAccessor(const Value &thisObject, const Value &v, PropertyAttributes attrs)
+ReturnedValue Object::getValueAccessor(const Value *thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
return v.asReturnedValue();
@@ -103,7 +103,8 @@ ReturnedValue Object::getValueAccessor(const Value &thisObject, const Value &v,
Scope scope(f->engine());
JSCallData jsCallData(scope);
- *jsCallData->thisObject = thisObject;
+ if (thisObject)
+ *jsCallData->thisObject = *thisObject;
return f->call(jsCallData);
}
@@ -415,7 +416,7 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
if (o->arrayData && o->arrayData->getProperty(index, pd, &attrs)) {
if (hasProperty)
*hasProperty = true;
- return Object::getValue(*receiver, pd->value, attrs);
+ return Object::getValue(receiver, pd->value, attrs);
}
if (o->internalClass->vtable->type == Type_StringObject) {
ScopedString str(scope, static_cast<Heap::StringObject *>(o)->getIndex(index));
@@ -436,7 +437,7 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
if (idx.isValid()) {
if (hasProperty)
*hasProperty = true;
- return Object::getValue(*receiver, *o->propertyData(idx.index), idx.attrs);
+ return Object::getValue(receiver, *o->propertyData(idx.index), idx.attrs);
}
o = o->prototype();
if (!o || o->internalClass->vtable->get != Object::virtualGet)
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 38055ef407..f3375929a3 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -185,22 +185,22 @@ struct Q_QML_EXPORT Object: Managed {
//
// helpers
//
- static ReturnedValue getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs) {
+ static ReturnedValue getValue(const Value *thisObject, const Value &v, PropertyAttributes attrs) {
if (attrs.isData())
return v.asReturnedValue();
return getValueAccessor(thisObject, v, attrs);
}
ReturnedValue getValue(const Value &v, PropertyAttributes attrs) const {
- return getValue(*this, v, attrs);
+ return getValue(this, v, attrs);
}
ReturnedValue getValueByIndex(uint propertyIndex) const {
PropertyAttributes attrs = internalClass()->propertyData.at(propertyIndex);
const Value *v = propertyData(propertyIndex);
if (!attrs.isAccessor())
return v->asReturnedValue();
- return getValueAccessor(*this, *v, attrs);
+ return getValueAccessor(this, *v, attrs);
}
- static ReturnedValue getValueAccessor(const Value &thisObject, const Value &v, PropertyAttributes attrs);
+ static ReturnedValue getValueAccessor(const Value *thisObject, const Value &v, PropertyAttributes attrs);
bool putValue(uint memberIndex, PropertyAttributes attrs, const Value &value);
@@ -543,13 +543,11 @@ inline const ArrayObject *Value::as() const {
return isManaged() && m()->internalClass->vtable->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr;
}
-#ifndef V4_BOOTSTRAP
template<>
inline ReturnedValue value_convert<Object>(ExecutionEngine *e, const Value &v)
{
return v.toObject(e)->asReturnedValue();
}
-#endif
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index e9515b5b68..8707305dc2 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -74,7 +74,7 @@ struct ObjectCtor: FunctionObject
static ReturnedValue virtualCall(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc);
};
-struct ObjectPrototype: Object
+struct Q_QML_PRIVATE_EXPORT ObjectPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index b337243204..26e1074fe3 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -49,7 +49,7 @@ namespace Profiling {
FunctionLocation FunctionCall::resolveLocation() const
{
return FunctionLocation(m_function->name()->toQString(),
- m_function->compilationUnit->fileName(),
+ m_function->executableCompilationUnit()->fileName(),
m_function->compiledFunction->location.line,
m_function->compiledFunction->location.column);
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 8461384e9a..ccf7c9210d 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -144,19 +144,19 @@ public:
FunctionCall(Function *function, qint64 start, qint64 end) :
m_function(function), m_start(start), m_end(end)
- { m_function->compilationUnit->addref(); }
+ { m_function->executableCompilationUnit()->addref(); }
FunctionCall(const FunctionCall &other) :
m_function(other.m_function), m_start(other.m_start), m_end(other.m_end)
- { m_function->compilationUnit->addref(); }
+ { m_function->executableCompilationUnit()->addref(); }
~FunctionCall()
- { m_function->compilationUnit->release(); }
+ { m_function->executableCompilationUnit()->release(); }
FunctionCall &operator=(const FunctionCall &other) {
if (&other != this) {
- other.m_function->compilationUnit->addref();
- m_function->compilationUnit->release();
+ other.m_function->executableCompilationUnit()->addref();
+ m_function->executableCompilationUnit()->release();
m_function = other.m_function;
m_start = other.m_start;
m_end = other.m_end;
@@ -189,22 +189,22 @@ public:
SentMarker(const SentMarker &other) : m_function(other.m_function)
{
if (m_function)
- m_function->compilationUnit->addref();
+ m_function->executableCompilationUnit()->addref();
}
~SentMarker()
{
if (m_function)
- m_function->compilationUnit->release();
+ m_function->executableCompilationUnit()->release();
}
SentMarker &operator=(const SentMarker &other)
{
if (&other != this) {
if (m_function)
- m_function->compilationUnit->release();
+ m_function->executableCompilationUnit()->release();
m_function = other.m_function;
- m_function->compilationUnit->addref();
+ m_function->executableCompilationUnit()->addref();
}
return *this;
}
@@ -213,7 +213,7 @@ public:
{
Q_ASSERT(m_function == nullptr);
m_function = function;
- m_function->compilationUnit->addref();
+ m_function->executableCompilationUnit()->addref();
}
bool isValid() const
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e81c90dd1a..095f27279f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -763,6 +763,8 @@ struct QObjectWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
~QObjectWrapperOwnPropertyKeyIterator() override = default;
PropertyKey next(const QV4::Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+private:
+ QSet<QByteArray> m_alreadySeen;
};
PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd, PropertyAttributes *attrs)
@@ -803,6 +805,11 @@ PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Pro
++propertyIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
+ // filter out duplicates due to overloads:
+ if (m_alreadySeen.contains(method.name()))
+ continue;
+ else
+ m_alreadySeen.insert(method.name());
ExecutionEngine *thatEngine = that->engine();
Scope scope(thatEngine);
ScopedString methodName(scope, thatEngine->newString(QString::fromUtf8(method.name())));
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 5bd25dcbec..64aba1d85c 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -198,13 +198,6 @@ QString RegExpObject::toString() const
return p;
}
-QString RegExpObject::source() const
-{
- Scope scope(engine());
- ScopedValue s(scope, get(scope.engine->id_source()));
- return s->toQString();
-}
-
ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *str)
{
QString s = str->toQString();
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 04b533e49d..b94889e9f0 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -101,7 +101,7 @@ DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) {
}
-struct RegExpObject: Object {
+struct Q_QML_PRIVATE_EXPORT RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
V4_INTERNALCLASS(RegExpObject)
@@ -145,7 +145,12 @@ struct RegExpObject: Object {
QRegularExpression toQRegularExpression() const;
#endif
QString toString() const;
- QString source() const;
+ QString source() const
+ {
+ Scope scope(engine());
+ ScopedValue s(scope, get(scope.engine->id_source()));
+ return s->toQString();
+ }
Heap::RegExp *value() const { return d()->value; }
uint flags() const { return d()->value->flags; }
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index e95dfa775f..478114a38a 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -38,9 +38,9 @@
****************************************************************************/
#include "qv4global_p.h"
-#include "qv4engine_p.h"
#include "qv4runtime_p.h"
#ifndef V4_BOOTSTRAP
+#include "qv4engine_p.h"
#include "qv4object_p.h"
#include "qv4objectproto_p.h"
#include "qv4globalobject_p.h"
@@ -224,6 +224,11 @@ void RuntimeCounters::count(const char *func, uint tag1, uint tag2)
#ifndef V4_BOOTSTRAP
+static QV4::Lookup *runtimeLookup(Function *f, uint i)
+{
+ return f->executableCompilationUnit()->runtimeLookups + i;
+}
+
void RuntimeHelpers::numberToString(QString *result, double num, int radix)
{
Q_ASSERT(result);
@@ -314,7 +319,8 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
ReturnedValue Runtime::Closure::call(ExecutionEngine *engine, int functionId)
{
- QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->currentStackFrame->v4Function->executableCompilationUnit()
+ ->runtimeFunctions[functionId];
Q_ASSERT(clos);
ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context);
if (clos->isGenerator())
@@ -620,7 +626,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
ReturnedValue Runtime::GetTemplateObject::call(Function *function, int index)
{
- return function->compilationUnit->templateObjectAt(index)->asReturnedValue();
+ return function->executableCompilationUnit()->templateObjectAt(index)->asReturnedValue();
}
void Runtime::StoreProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
@@ -1077,33 +1083,33 @@ void Runtime::StoreSuperProperty::call(ExecutionEngine *engine, const Value &pro
ReturnedValue Runtime::LoadGlobalLookup::call(ExecutionEngine *engine, Function *f, int index)
{
- Lookup *l = f->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(f, index);
return l->globalGetter(l, engine);
}
ReturnedValue Runtime::LoadQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index)
{
- Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index);
return l->qmlContextPropertyGetter(l, engine, nullptr);
}
ReturnedValue Runtime::GetLookup::call(ExecutionEngine *engine, Function *f, const Value &base, int index)
{
- Lookup *l = f->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(f, index);
return l->getter(l, engine, base);
}
void Runtime::SetLookupSloppy::call(Function *f, const Value &base, int index, const Value &value)
{
ExecutionEngine *engine = f->internalClass->engine;
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = runtimeLookup(f, index);
l->setter(l, engine, const_cast<Value &>(base), value);
}
void Runtime::SetLookupStrict::call(Function *f, const Value &base, int index, const Value &value)
{
ExecutionEngine *engine = f->internalClass->engine;
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = runtimeLookup(f, index);
if (!l->setter(l, engine, const_cast<Value &>(base), value))
engine->throwTypeError();
}
@@ -1175,8 +1181,14 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y)
if (x.isNumber())
return y.isNumber() && x.asDouble() == y.asDouble();
- if (x.isManaged())
+ if (x.isManaged()) {
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+ return false;
+#else
return y.isManaged() && x.cast<Managed>()->isEqualTo(y.cast<Managed>());
+#endif
+ }
return false;
}
@@ -1360,12 +1372,13 @@ static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engin
ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc)
{
Scope scope(engine);
- Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index);
Value function = Value::fromReturnedValue(l->globalGetter(l, engine));
Value thisObject = Value::undefinedValue();
- if (!function.isFunctionObject())
+ if (!function.isFunctionObject()) {
return throwPropertyIsNotAFunctionTypeError(engine, &thisObject,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString());
+ }
return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc);
}
@@ -1375,11 +1388,12 @@ ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engin
{
Scope scope(engine);
ScopedValue thisObject(scope);
- Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index);
Value function = Value::fromReturnedValue(l->qmlContextPropertyGetter(l, engine, thisObject));
- if (!function.isFunctionObject())
+ if (!function.isFunctionObject()) {
return throwPropertyIsNotAFunctionTypeError(engine, thisObject,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString());
+ }
return static_cast<FunctionObject &>(function).call(thisObject, argv, argc);
}
@@ -1414,9 +1428,11 @@ ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Va
if (engine->hasException)
return Encode::undefined();
- if (!f)
- return throwPropertyIsNotAFunctionTypeError(engine, thisObject,
- engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString());
+ if (!f) {
+ return throwPropertyIsNotAFunctionTypeError(
+ engine, thisObject, engine->currentStackFrame->v4Function->compilationUnit
+ ->runtimeStrings[nameIndex]->toQString());
+ }
return f->call(thisObject, argv, argc);
}
@@ -1425,7 +1441,9 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &
{
const Value *base = &baseRef;
Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(
+ scope,
+ engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject lookupObject(scope, base);
if (!lookupObject) {
@@ -1463,7 +1481,7 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &
ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc)
{
- Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index);
// ok to have the value on the stack here
Value f = Value::fromReturnedValue(l->getter(l, engine, base));
@@ -1783,7 +1801,8 @@ ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId,
if (arg != ObjectLiteralArgument::Value) {
Q_ASSERT(args[2].isInteger());
int functionId = args[2].integerValue();
- QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->currentStackFrame->v4Function->executableCompilationUnit()
+ ->runtimeFunctions[functionId];
Q_ASSERT(clos);
PropertyKey::FunctionNamePrefix prefix = PropertyKey::None;
@@ -1827,7 +1846,8 @@ ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId,
ReturnedValue Runtime::CreateClass::call(ExecutionEngine *engine, int classIndex,
const Value &superClass, Value computedNames[])
{
- const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit;
+ const QV4::ExecutableCompilationUnit *unit
+ = engine->currentStackFrame->v4Function->executableCompilationUnit();
const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex);
Scope scope(engine);
@@ -2170,6 +2190,7 @@ ReturnedValue Runtime::LessEqual::call(const Value &left, const Value &right)
return Encode(r);
}
+#ifndef V4_BOOTSTRAP
struct LazyScope
{
ExecutionEngine *engine = nullptr;
@@ -2189,6 +2210,7 @@ struct LazyScope
**scopedValue = value;
}
};
+#endif
Bool Runtime::CompareEqual::call(const Value &left, const Value &right)
{
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 72af90d1dc..349099f8d5 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -52,8 +52,6 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4context_p.h"
-#include "qv4engine_p.h"
#include "qv4math_p.h"
#include "qv4runtimeapi_p.h"
#include <QtCore/qnumeric.h>
diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp
index 9866966936..99d0de5ec6 100644
--- a/src/qml/jsruntime/qv4runtimecodegen.cpp
+++ b/src/qml/jsruntime/qv4runtimecodegen.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qv4engine_p.h"
#include "qv4runtimecodegen_p.h"
#include "qv4compilerscanfunctions_p.h"
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 6cb2e95cdc..ee7f4dff0b 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -61,7 +61,7 @@
using namespace QV4;
-Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer<CompiledData::CompilationUnit> &compilationUnit)
+Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer<ExecutableCompilationUnit> &compilationUnit)
: line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
, compilationUnit(compilationUnit), vmFunction(nullptr), parseAsBinding(true)
{
@@ -133,7 +133,7 @@ void Script::parse()
if (v4->hasException)
return;
- compilationUnit = cg.generateCompilationUnit();
+ compilationUnit = QV4::ExecutableCompilationUnit::create(cg.generateCompilationUnit());
vmFunction = compilationUnit->linkToEngine(v4);
}
@@ -172,10 +172,11 @@ Function *Script::function()
return vmFunction;
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator,
- const QString &fileName, const QString &finalUrl, const QString &source,
- QList<QQmlError> *reportedErrors,
- QV4::Compiler::ContextType contextType)
+QV4::CompiledData::CompilationUnit Script::precompile(
+ QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine,
+ Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl,
+ const QString &source, QList<QQmlError> *reportedErrors,
+ QV4::Compiler::ContextType contextType)
{
using namespace QV4::Compiler;
using namespace QQmlJS::AST;
@@ -219,8 +220,9 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo
QQmlMetaType::CachedUnitLookupError cacheError = QQmlMetaType::CachedUnitLookupError::NoError;
if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(originalUrl, &cacheError)) {
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> jsUnit;
- jsUnit.adopt(new QV4::CompiledData::CompilationUnit(cachedUnit));
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> jsUnit
+ = QV4::ExecutableCompilationUnit::create(
+ QV4::CompiledData::CompilationUnit(cachedUnit));
return new QV4::Script(engine, qmlContext, jsUnit);
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index a1e9b83a8b..aecedea701 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -80,7 +80,7 @@ struct Q_QML_EXPORT Script {
if (qml)
qmlContext.set(engine, *qml);
}
- Script(ExecutionEngine *engine, QmlContext *qml, const QQmlRefPointer<CompiledData::CompilationUnit> &compilationUnit);
+ Script(ExecutionEngine *engine, QmlContext *qml, const QQmlRefPointer<ExecutableCompilationUnit> &compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -92,7 +92,7 @@ struct Q_QML_EXPORT Script {
bool parsed;
QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Eval;
QV4::PersistentValue qmlContext;
- QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<ExecutableCompilationUnit> compilationUnit;
Function *vmFunction;
bool parseAsBinding;
@@ -101,8 +101,10 @@ struct Q_QML_EXPORT Script {
Function *function();
- static QQmlRefPointer<CompiledData::CompilationUnit> precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator,
- const QString &fileName, const QString &finalUrl, const QString &source,
+ static QV4::CompiledData::CompilationUnit precompile(
+ QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine,
+ Compiler::JSUnitGenerator *unitGenerator, const QString &fileName,
+ const QString &finalUrl, const QString &source,
QList<QQmlError> *reportedErrors = nullptr,
QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Global);
static Script *createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl, QString *error);
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index da71215bed..886dfaa521 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct SequencePrototype : public QV4::Object
+struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object
{
V4_PROTOTYPE(arrayPrototype)
void init();
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
index 44cfef9173..bf689a74bc 100644
--- a/src/qml/jsruntime/qv4stackframe_p.h
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -52,63 +52,13 @@
#include <private/qv4context_p.h>
#include <private/qv4enginebase_p.h>
-#ifndef V4_BOOTSTRAP
+#include <private/qv4calldata_p.h>
#include <private/qv4function_p.h>
-#endif
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct CallData
-{
- enum Offsets {
- Function = 0,
- Context = 1,
- Accumulator = 2,
- This = 3,
- NewTarget = 4,
- Argc = 5,
-
- LastOffset = Argc,
- OffsetCount = LastOffset + 1
- };
-
- Value function;
- Value context;
- Value accumulator;
- Value thisObject;
- Value newTarget;
- Value _argc;
-
- int argc() const {
- Q_ASSERT(_argc.isInteger());
- return _argc.int_32();
- }
-
- void setArgc(int argc) {
- Q_ASSERT(argc >= 0);
- _argc.setInt_32(argc);
- }
-
- inline ReturnedValue argument(int i) const {
- return i < argc() ? args[i].asReturnedValue() : Value::undefinedValue().asReturnedValue();
- }
-
- Value args[1];
-
- static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
-};
-
-Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
-Q_STATIC_ASSERT(offsetof(CallData, function ) == CallData::Function * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, context ) == CallData::Context * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, accumulator) == CallData::Accumulator * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, thisObject ) == CallData::This * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, newTarget ) == CallData::NewTarget * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, _argc ) == CallData::Argc * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, args ) == 6 * sizeof(Value));
-
struct Q_QML_EXPORT CppStackFrame {
EngineBase *engine;
Value *savedStackTop;
@@ -155,7 +105,6 @@ struct Q_QML_EXPORT CppStackFrame {
engine->jsStackTop = savedStackTop;
}
-#ifndef V4_BOOTSTRAP
static uint requiredJSStackFrameSize(uint nRegisters) {
return CallData::HeaderSize() + nRegisters;
}
@@ -198,7 +147,6 @@ struct Q_QML_EXPORT CppStackFrame {
*v = Value::emptyValue().asReturnedValue();
}
}
-#endif
QString source() const;
QString function() const;
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 68d65f2e24..223f4a4769 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -39,19 +39,15 @@
#include "qv4string_p.h"
#include "qv4value_p.h"
-#ifndef V4_BOOTSTRAP
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
-#endif
#include <QtCore/QHash>
#include <QtCore/private/qnumeric_p.h>
using namespace QV4;
-#ifndef V4_BOOTSTRAP
-
void Heap::StringOrSymbol::markObjects(Heap::Base *that, MarkStack *markStack)
{
StringOrSymbol *s = static_cast<StringOrSymbol *>(that);
@@ -254,10 +250,3 @@ qint64 String::virtualGetLength(const Managed *m)
{
return static_cast<const String *>(m)->d()->length();
}
-
-#endif // V4_BOOTSTRAP
-
-uint String::toArrayIndex(const QString &str)
-{
- return QV4::String::toArrayIndex(str.constData(), str.constData() + str.length());
-}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index fbd4f5f550..7888809490 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -54,6 +54,7 @@
#include "qv4managed_p.h"
#include <QtCore/private/qnumeric_p.h>
#include "qv4enginebase_p.h"
+#include "qv4stringtoarrayindex_p.h"
QT_BEGIN_NAMESPACE
@@ -104,7 +105,6 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base
struct Q_QML_PRIVATE_EXPORT String : StringOrSymbol {
static void markObjects(Heap::Base *that, MarkStack *markStack);
-#ifndef V4_BOOTSTRAP
const VTable *vtable() const {
return internalClass->vtable;
}
@@ -140,11 +140,9 @@ struct Q_QML_PRIVATE_EXPORT String : StringOrSymbol {
private:
static void append(const String *data, QChar *ch);
-#endif
};
Q_STATIC_ASSERT(std::is_trivial< String >::value);
-#ifndef V4_BOOTSTRAP
struct ComplexString : String {
void init(String *l, String *n);
void init(String *ref, int from, int len);
@@ -162,12 +160,10 @@ inline
int String::length() const {
return text ? text->size : static_cast<const ComplexString *>(this)->len;
}
-#endif
}
struct Q_QML_PRIVATE_EXPORT StringOrSymbol : public Managed {
-#ifndef V4_BOOTSTRAP
V4_MANAGED(StringOrSymbol, Managed)
V4_NEEDS_DESTROY
enum {
@@ -184,11 +180,9 @@ public:
inline QString toQString() const {
return d()->toQString();
}
-#endif
};
struct Q_QML_PRIVATE_EXPORT String : public StringOrSymbol {
-#ifndef V4_BOOTSTRAP
V4_MANAGED(String, StringOrSymbol)
Q_MANAGED_TYPE(String)
V4_INTERNALCLASS(String)
@@ -239,43 +233,13 @@ struct Q_QML_PRIVATE_EXPORT String : public StringOrSymbol {
protected:
static bool virtualIsEqualTo(Managed *that, Managed *o);
static qint64 virtualGetLength(const Managed *m);
-#endif
-
-public:
- static uint toArrayIndex(const QString &str);
-
-private:
- static inline uint toUInt(const QChar *ch) { return ch->unicode(); }
- static inline uint toUInt(const char *ch) { return static_cast<unsigned char>(*ch); }
-
- template <typename T>
- static inline uint toArrayIndex(const T *ch, const T *end)
- {
- uint i = toUInt(ch) - '0';
- if (i > 9)
- return UINT_MAX;
- ++ch;
- // reject "01", "001", ...
- if (i == 0 && ch != end)
- return UINT_MAX;
-
- while (ch < end) {
- uint x = toUInt(ch) - '0';
- if (x > 9)
- return UINT_MAX;
- if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i)) // i = i * 10 + x
- return UINT_MAX;
- ++ch;
- }
- return i;
- }
public:
template <typename T>
static inline uint calculateHashValue(const T *ch, const T* end, uint *subtype)
{
// array indices get their number as hash value
- uint h = toArrayIndex(ch, end);
+ uint h = stringToArrayIndex(ch, end);
if (h != UINT_MAX) {
if (subtype)
*subtype = Heap::StringOrSymbol::StringType_ArrayIndex;
@@ -283,17 +247,16 @@ public:
}
while (ch < end) {
- h = 31 * h + toUInt(ch);
+ h = 31 * h + charToUInt(ch);
++ch;
}
if (subtype)
- *subtype = (toUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
+ *subtype = (charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
return h;
}
};
-#ifndef V4_BOOTSTRAP
struct ComplexString : String {
typedef QV4::Heap::ComplexString Data;
QV4::Heap::ComplexString *d_unchecked() const { return static_cast<QV4::Heap::ComplexString *>(m()); }
@@ -332,8 +295,6 @@ inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
{
return v.toString(e)->asReturnedValue();
}
-#endif
-
}
diff --git a/src/qml/jsruntime/qv4stringtoarrayindex_p.h b/src/qml/jsruntime/qv4stringtoarrayindex_p.h
new file mode 100644
index 0000000000..61bd988d1e
--- /dev/null
+++ b/src/qml/jsruntime/qv4stringtoarrayindex_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4STRINGTOARRAYINDEX_P_H
+#define QV4STRINGTOARRAYINDEX_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/private/qnumeric_p.h>
+#include <QtCore/qstring.h>
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+inline uint charToUInt(const QChar *ch) { return ch->unicode(); }
+inline uint charToUInt(const char *ch) { return static_cast<unsigned char>(*ch); }
+
+template <typename T>
+uint stringToArrayIndex(const T *ch, const T *end)
+{
+ uint i = charToUInt(ch) - '0';
+ if (i > 9)
+ return std::numeric_limits<uint>::max();
+ ++ch;
+ // reject "01", "001", ...
+ if (i == 0 && ch != end)
+ return std::numeric_limits<uint>::max();
+
+ while (ch < end) {
+ uint x = charToUInt(ch) - '0';
+ if (x > 9)
+ return std::numeric_limits<uint>::max();
+ if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i)) // i = i * 10 + x
+ return std::numeric_limits<uint>::max();
+ ++ch;
+ }
+ return i;
+}
+
+inline uint stringToArrayIndex(const QString &str)
+{
+ return stringToArrayIndex(str.constData(), str.constData() + str.length());
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4STRINGTOARRAYINDEX_P_H
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index cbc153bb86..82cf11f148 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -36,11 +36,11 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <qv4engine_p.h>
+
#include <qv4runtime_p.h>
-#include <qv4string_p.h>
#include <qv4propertykey_p.h>
#ifndef V4_BOOTSTRAP
+#include <qv4string_p.h>
#include <qv4symbol_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
@@ -248,7 +248,6 @@ QV4::PropertyKey Value::toPropertyKey(ExecutionEngine *e) const
ScopedStringOrSymbol s(scope, v);
return s->toPropertyKey();
}
-#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
if (_val == other._val)
@@ -285,7 +284,6 @@ bool Value::sameValueZero(Value other) const {
return false;
}
-#ifndef V4_BOOTSTRAP
Heap::String *Value::toString(ExecutionEngine *e, Value val)
{
return RuntimeHelpers::convertToString(e, val);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index ec44f42933..c6322fb504 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -65,6 +65,8 @@
#include <private/qv4baselinejit_p.h>
#endif
+#include <qtqml_tracepoints_p.h>
+
#undef COUNT_INSTRUCTIONS
enum { ShowWhenDeoptimiationHappens = 0 };
@@ -422,6 +424,10 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
CHECK_STACK_LIMITS(engine);
Function *function = frame->v4Function;
+ Q_TRACE_SCOPE(QQmlV4_function_call, engine, function->name()->toQString(),
+ function->compilationUnit->fileName(),
+ function->compiledFunction->location.line,
+ function->compiledFunction->location.column);
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
@@ -559,14 +565,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadGlobalLookup)
STORE_IP();
- QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
acc = l->globalGetter(l, engine);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadGlobalLookup)
MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
STORE_IP();
- QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
acc = l->qmlContextPropertyGetter(l, engine, nullptr);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadQmlContextPropertyLookup)
@@ -610,7 +616,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
STORE_IP();
STORE_ACC();
- QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
if (accumulator.isNullOrUndefined()) {
QString message = QStringLiteral("Cannot read property '%1' of %2")
@@ -634,7 +640,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(SetLookup)
STORE_IP();
STORE_ACC();
- QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
if (!l->setter(l, engine, STACK_VALUE(base), accumulator) && function->isStrict())
engine->throwTypeError();
CHECK_EXCEPTION;
@@ -716,7 +722,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(CallPropertyLookup)
STORE_IP();
- Lookup *l = function->compilationUnit->runtimeLookups + lookupIndex;
+ Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
if (stack[base].isNullOrUndefined()) {
QString message = QStringLiteral("Cannot call method '%1' of %2")
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 34d334a24d..9288d3e3b6 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -63,6 +63,7 @@
#include "qv4profiling_p.h"
#include "qv4mapobject_p.h"
#include "qv4setobject_p.h"
+#include "qv4writebarrier_p.h"
//#define MM_STATS
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
index 8b04aa6cb1..c65cfc0269 100644
--- a/src/qml/memory/qv4writebarrier_p.h
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -51,7 +51,6 @@
//
#include <private/qv4global_p.h>
-#include <private/qv4enginebase_p.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +59,7 @@ QT_BEGIN_NAMESPACE
#define WRITEBARRIER(x) (1/WRITEBARRIER_##x == 1)
namespace QV4 {
+struct EngineBase;
namespace WriteBarrier {
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index ca3282556e..5cb51e0d03 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -4,6 +4,9 @@ QT = core-private
qtConfig(qml-network): \
QT += network
+TRACEPOINT_PROVIDER = $$PWD/qtqml.tracepoints
+CONFIG += qt_tracepoints
+
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 656c7dd515..7fb15af570 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -335,7 +335,7 @@ protected:
class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> {
public:
- QQmlTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+ QQmlTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
setCompilationUnit(compilationUnit);
m_binding = binding;
@@ -356,7 +356,7 @@ public:
if (!isAddedToObject() || hasError())
return;
- const QString result = m_binding->valueAsString(m_compilationUnit.data());
+ const QString result = m_compilationUnit->bindingValueAsString(m_binding);
Q_ASSERT(targetObject());
@@ -378,7 +378,7 @@ private:
const QV4::CompiledData::Binding *m_binding;
};
-QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
{
QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index f192de4342..85b02dcde4 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -79,7 +79,7 @@ public:
const QString &url = QString(), quint16 lineNumber = 0);
static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
- static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
+ static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
QObject *obj, QQmlContextData *ctxt);
~QQmlBinding() override;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 64d2a064df..04debc0615 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -72,7 +72,7 @@ namespace {
QT_BEGIN_NAMESPACE
-class QQmlComponentExtension : public QV8Engine::Deletable
+class QQmlComponentExtension : public QV4::ExecutionEngine::Deletable
{
public:
QQmlComponentExtension(QV4::ExecutionEngine *v4);
@@ -550,7 +550,8 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
/*!
\internal
*/
-QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::CompiledData::CompilationUnit *compilationUnit, int start, QObject *parent)
+QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit,
+ int start, QObject *parent)
: QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index 20199d0b21..39b6d4526f 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -59,9 +59,7 @@ class QQmlComponentPrivate;
class QQmlComponentAttached;
namespace QV4 {
-namespace CompiledData {
-struct CompilationUnit;
-}
+class ExecutableCompilationUnit;
}
class Q_QML_EXPORT QQmlComponent : public QObject
@@ -128,7 +126,8 @@ protected:
Q_INVOKABLE void incubateObject(QQmlV4Function *);
private:
- QQmlComponent(QQmlEngine *, QV4::CompiledData::CompilationUnit *compilationUnit, int, QObject *parent);
+ QQmlComponent(QQmlEngine *, QV4::ExecutableCompilationUnit *compilationUnit, int,
+ QObject *parent);
Q_DISABLE_COPY(QQmlComponent)
friend class QQmlTypeData;
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 4d9e4c6c15..71275a2cd3 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -105,7 +105,7 @@ public:
qreal progress;
int start;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
struct ConstructionState {
ConstructionState()
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 3710cee162..bd59409475 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -438,23 +438,20 @@ QUrl QQmlContext::resolvedUrl(const QUrl &src)
QUrl QQmlContextData::resolvedUrl(const QUrl &src)
{
- QQmlContextData *ctxt = this;
-
QUrl resolved;
if (src.isRelative() && !src.isEmpty()) {
- if (ctxt) {
- while(ctxt) {
- if (ctxt->url().isValid())
- break;
- else
- ctxt = ctxt->parent;
- }
-
- if (ctxt)
- resolved = ctxt->url().resolved(src);
- else if (engine)
- resolved = engine->baseUrl().resolved(src);
- }
+ QQmlContextData *ctxt = this;
+ do {
+ if (ctxt->url().isValid())
+ break;
+ else
+ ctxt = ctxt->parent;
+ } while (ctxt);
+
+ if (ctxt)
+ resolved = ctxt->url().resolved(src);
+ else if (engine)
+ resolved = engine->baseUrl().resolved(src);
} else {
resolved = src;
}
@@ -845,7 +842,7 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
return QQmlContextPrivate::get(asQQmlContext());
}
-void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex)
+void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
{
typeCompilationUnit = unit;
componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index 7e3cef8e1d..1ddd04c9ff 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -66,7 +66,7 @@
#include <private/qflagpointer_p.h>
#include <private/qqmlguard_p.h>
-#include <private/qv4compileddata_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#include <private/qv4identifier_p.h>
QT_BEGIN_NAMESPACE
@@ -152,12 +152,12 @@ public:
QQmlIncubatorPrivate *incubator;
// Compilation unit for contexts that belong to a compiled type.
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit;
// object index in CompiledData::Unit to component that created this context
int componentObjectIndex;
- void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex);
+ void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex);
// flag indicates whether the context owns the cache (after mutation) or not.
mutable QV4::IdentifierHash propertyNameCache;
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index aa933553a8..c8e1300a1b 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -80,8 +80,8 @@ public:
void clearErrors();
Flags flags() const { return m_flags; }
- virtual void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0;
- virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0;
+ virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0;
+ virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0;
QVector<QQmlCompileError> errors() const { return exceptions; }
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index f4c03fc17c..299476f5c8 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -76,8 +76,8 @@ class QQmlDataExtended;
class QQmlNotifierEndpoint;
namespace QV4 {
+class ExecutableCompilationUnit;
namespace CompiledData {
-struct CompilationUnit;
struct Binding;
}
}
@@ -226,14 +226,14 @@ public:
~DeferredData();
unsigned int deferredIdx;
QMultiHash<int, const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;//Not always the same as the other compilation unit
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;//Not always the same as the other compilation unit
QQmlContextData *context;//Could be either context or outerContext
Q_DISABLE_COPY(DeferredData);
};
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
- void deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, QQmlContextData *);
+ void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, QQmlContextData *);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index bb2b3e462c..f977934b3e 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -87,9 +87,6 @@
#include <private/qqmltimer_p.h>
#endif
#include <private/qqmlplatform_p.h>
-#if QT_CONFIG(qml_worker_script)
-#include <private/qquickworkerscript_p.h>
-#endif
#include <private/qqmlloggingcategory_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
@@ -207,6 +204,7 @@ void QQmlEnginePrivate::defineModule()
qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); // Only available in >= 2.8
+ qmlRegisterType<QQmlBind, 14>(uri, 2, 14, "Binding");
qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3
#if QT_CONFIG(qml_animation)
@@ -239,9 +237,6 @@ void QQmlEnginePrivate::registerQuickTypes()
#endif
qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory");
qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory");
-#if QT_CONFIG(qml_worker_script)
- qmlRegisterType<QQuickWorkerScript>(uri, 2, 0, "WorkerScript");
-#endif
#if QT_CONFIG(qml_locale)
qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
#endif
@@ -950,7 +945,11 @@ void QQmlEnginePrivate::init()
Q_Q(QQmlEngine);
if (baseModulesUninitialized) {
- qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
+
+ // required for the Compiler.
+ qmlRegisterType<QObject>("QML", 1, 0, "QtObject");
+ qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
+
QQmlData::init();
baseModulesUninitialized = false;
}
@@ -963,21 +962,11 @@ void QQmlEnginePrivate::init()
qRegisterMetaType<QList<int> >();
qRegisterMetaType<QQmlBinding*>();
- v8engine()->setEngine(q);
+ q->handle()->setQmlEngine(q);
rootContext = new QQmlContext(q,true);
}
-#if QT_CONFIG(qml_worker_script)
-QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
-{
- Q_Q(QQmlEngine);
- if (!workerScriptEngine)
- workerScriptEngine = new QQuickWorkerScriptEngine(q);
- return workerScriptEngine;
-}
-#endif
-
/*!
\class QQmlEngine
\since 5.0
@@ -1782,7 +1771,7 @@ void QQmlData::NotifyList::layout()
todo = nullptr;
}
-void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *context)
+void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *context)
{
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
@@ -2419,7 +2408,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVe
}
}
-void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
{
compilationUnit->isRegisteredWithEngine = true;
@@ -2429,7 +2418,7 @@ void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::Compila
m_compositeTypes.insert(compilationUnit->metaTypeId, compilationUnit);
}
-void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
{
compilationUnit->isRegisteredWithEngine = false;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 4f7fb79593..3b716683fd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -76,7 +76,6 @@
#include <private/qobject_p.h>
-#include <private/qv8engine_p.h>
#include <private/qjsengine_p.h>
#include <private/qqmldirparser_p.h>
@@ -94,7 +93,6 @@ class QQmlTypeNameCache;
class QQmlComponentAttached;
class QQmlCleanup;
class QQmlDelayedError;
-class QQuickWorkerScriptEngine;
class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
@@ -150,12 +148,10 @@ public:
QQmlDelayedError *erroredBindings;
int inProgressCreations;
- QV8Engine *v8engine() const { return q_func()->handle()->v8Engine; }
QV4::ExecutionEngine *v4engine() const { return q_func()->handle(); }
#if QT_CONFIG(qml_worker_script)
- QQuickWorkerScriptEngine *getWorkerScriptEngine();
- QQuickWorkerScriptEngine *workerScriptEngine;
+ QThread *workerScriptEngine;
#endif
QUrl baseUrl;
@@ -223,8 +219,8 @@ public:
QQmlMetaObject metaObjectForType(int) const;
QQmlPropertyCache *propertyCacheForType(int);
QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1);
- void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
- void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
+ void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
+ void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
@@ -242,7 +238,6 @@ public:
static void warning(QQmlEnginePrivate *, const QQmlError &);
static void warning(QQmlEnginePrivate *, const QList<QQmlError> &);
- inline static QV8Engine *getV8Engine(QQmlEngine *e);
inline static QV4::ExecutionEngine *getV4Engine(QQmlEngine *e);
inline static QQmlEnginePrivate *get(QQmlEngine *e);
inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
@@ -270,7 +265,7 @@ private:
// 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.
- QHash<int, QV4::CompiledData::CompilationUnit *> m_compositeTypes;
+ QHash<int, QV4::ExecutableCompilationUnit *> m_compositeTypes;
static bool s_designerMode;
// These members is protected by the full QQmlEnginePrivate::mutex mutex
@@ -316,8 +311,8 @@ Returns true if the calling thread is the QQmlEngine thread.
*/
bool QQmlEnginePrivate::isEngineThread() const
{
- Q_Q(const QQmlEngine);
- return QThread::currentThread() == q->thread();
+
+ return QThread::currentThread() == q_ptr->thread();
}
/*!
@@ -342,8 +337,6 @@ the instance directly if not.
template<typename T>
void QQmlEnginePrivate::deleteInEngineThread(T *value)
{
- Q_Q(QQmlEngine);
-
Q_ASSERT(value);
if (isEngineThread()) {
delete value;
@@ -359,7 +352,7 @@ void QQmlEnginePrivate::deleteInEngineThread(T *value)
toDeleteInEngineThread.append(i);
mutex.unlock();
if (wasEmpty)
- QCoreApplication::postEvent(q, new QEvent(QEvent::User));
+ QCoreApplication::postEvent(q_ptr, new QEvent(QEvent::User));
}
}
@@ -390,13 +383,6 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersi
return QQmlMetaType::propertyCache(type, minorVersion);
}
-QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
-{
- Q_ASSERT(e);
-
- return e->handle()->v8Engine;
-}
-
QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e)
{
Q_ASSERT(e);
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 53caffe040..136159993a 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -55,7 +55,6 @@
#include <QtCore/QObject>
#include <private/qqmlmetaobject_p.h>
#include <private/qmetaobject_p.h>
-#include <private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index 676ba1a29a..57ec8249cb 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -87,7 +87,7 @@ public:
QPointer<QObject> result;
QQmlGuardedContextData rootContext;
QQmlEnginePrivate *enginePriv;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QScopedPointer<QQmlObjectCreator> creator;
int subComponentToCreate;
QQmlVMEGuard vmeGuard;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 9a3a5218e0..e799267769 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -392,10 +392,10 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext,
return;
m_qmlScope.set(qmlContext->engine(), *qmlContext);
m_v4Function = f;
- setCompilationUnit(m_v4Function->compilationUnit);
+ setCompilationUnit(m_v4Function->executableCompilationUnit());
}
-void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
+void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit)
{
m_compilationUnit = compilationUnit;
}
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 92f2ccbb4a..eecee08062 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -153,7 +153,7 @@ protected:
void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
- void setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
+ void setCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit);
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
@@ -178,7 +178,7 @@ private:
QQmlJavaScriptExpression *m_nextExpression;
QV4::PersistentValue m_qmlScope;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
QV4::Function *m_v4Function;
};
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 2b17037df0..dca13ac8d4 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -662,7 +662,7 @@ LOCALE_STRING_PROPERTY(exponential)
LOCALE_STRING_PROPERTY(amText)
LOCALE_STRING_PROPERTY(pmText)
-class QV4LocaleDataDeletable : public QV8Engine::Deletable
+class QV4LocaleDataDeletable : public QV4::ExecutionEngine::Deletable
{
public:
QV4LocaleDataDeletable(QV4::ExecutionEngine *engine);
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 09df23de51..a5b92d14f7 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -499,7 +499,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit
return QQmlType(priv);
}
-void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlMetaType::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
{
QByteArray name = compilationUnit->rootPropertyCache()->className();
@@ -526,7 +526,7 @@ void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationU
data->qmlLists.insert(lst_type, ptr_type);
}
-void QQmlMetaType::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlMetaType::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
{
int ptr_type = compilationUnit->metaTypeId;
int lst_type = compilationUnit->listMetaTypeId;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 9af982d1c3..911e519cf2 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -61,6 +61,8 @@ class QQmlTypeModule;
class QMutex;
class QQmlError;
+namespace QV4 { class ExecutableCompilationUnit; }
+
class Q_QML_PRIVATE_EXPORT QQmlMetaType
{
public:
@@ -78,8 +80,8 @@ public:
static void unregisterType(int type);
- static void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
- static void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
+ static void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
+ static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
static void registerModule(const char *uri, int versionMajor, int versionMinor);
static bool protectModule(const char *uri, int majVersion);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 26d3b5b6c1..e5f376fd34 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -57,6 +57,8 @@
#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qjsvalue_p.h>
+#include <qtqml_tracepoints_p.h>
+
QT_USE_NAMESPACE
namespace {
@@ -71,7 +73,7 @@ struct ActiveOCRestorer
};
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext,
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext,
QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
@@ -98,7 +100,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, propertyCaches(&compilationUnit->propertyCaches)
@@ -371,7 +373,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
propertyType = QMetaType::Int;
} else {
// ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
- QVariant value = binding->valueAsString(compilationUnit.data());
+ QVariant value = compilationUnit->bindingValueAsString(binding);
bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
Q_ASSERT(ok);
Q_UNUSED(ok);
@@ -404,7 +406,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
switch (propertyType) {
case QMetaType::QVariant: {
if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double n = binding->valueAsNumber(compilationUnit->constants);
+ double n = compilationUnit->bindingValueAsNumber(binding);
if (double(int(n)) == n) {
if (property->isVarProperty()) {
_vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(int(n)));
@@ -436,7 +438,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
}
} else {
- QString stringValue = binding->valueAsString(compilationUnit.data());
+ QString stringValue = compilationUnit->bindingValueAsString(binding);
if (property->isVarProperty()) {
QV4::ScopedString s(scope, v4->newString(stringValue));
_vmeMetaObject->setVMEProperty(property->coreIndex(), s);
@@ -449,25 +451,25 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
case QVariant::String: {
assertOrNull(binding->evaluatesToString());
- QString value = binding->valueAsString(compilationUnit.data());
+ QString value = compilationUnit->bindingValueAsString(binding);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::StringList: {
assertOrNull(binding->evaluatesToString());
- QStringList value(binding->valueAsString(compilationUnit.data()));
+ QStringList value(compilationUnit->bindingValueAsString(binding));
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::ByteArray: {
assertType(QV4::CompiledData::Binding::Type_String);
- QByteArray value(binding->valueAsString(compilationUnit.data()).toUtf8());
+ QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Url: {
assertType(QV4::CompiledData::Binding::Type_String);
- QString string = binding->valueAsString(compilationUnit.data());
+ QString string = compilationUnit->bindingValueAsString(binding);
// Encoded dir-separators defeat QUrl processing - decode them first
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(string));
@@ -479,7 +481,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
case QVariant::UInt: {
assertType(QV4::CompiledData::Binding::Type_Number);
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
uint value = uint(d);
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
@@ -487,7 +489,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
case QVariant::Int: {
assertType(QV4::CompiledData::Binding::Type_Number);
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
int value = int(d);
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
@@ -495,19 +497,19 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
case QMetaType::Float: {
assertType(QV4::CompiledData::Binding::Type_Number);
- float value = float(binding->valueAsNumber(compilationUnit->constants));
+ float value = float(compilationUnit->bindingValueAsNumber(binding));
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Double: {
assertType(QV4::CompiledData::Binding::Type_Number);
- double value = binding->valueAsNumber(compilationUnit->constants);
+ double value = compilationUnit->bindingValueAsNumber(binding);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Color: {
bool ok = false;
- uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ uint colorValue = QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
struct { void *data[4]; } buffer;
if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) {
@@ -518,21 +520,21 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
#if QT_CONFIG(datestring)
case QVariant::Date: {
bool ok = false;
- QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Time: {
bool ok = false;
- QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::DateTime: {
bool ok = false;
- QDateTime value = QQmlStringConverters::dateTimeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QDateTime value = QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok);
// ### VME compatibility :(
{
const qint64 date = value.date().toJulianDay();
@@ -546,42 +548,42 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
#endif // datestring
case QVariant::Point: {
bool ok = false;
- QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok).toPoint();
+ QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::PointF: {
bool ok = false;
- QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Size: {
bool ok = false;
- QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok).toSize();
+ QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::SizeF: {
bool ok = false;
- QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Rect: {
bool ok = false;
- QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok).toRect();
+ QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::RectF: {
bool ok = false;
- QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
assertOrNull(ok);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
@@ -597,7 +599,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
float xp;
float yp;
} vec;
- bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec));
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
assertOrNull(ok);
Q_UNUSED(ok);
property->writeProperty(_qobject, &vec, propertyWriteFlags);
@@ -609,7 +611,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
float yp;
float zy;
} vec;
- bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec));
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
assertOrNull(ok);
Q_UNUSED(ok);
property->writeProperty(_qobject, &vec, propertyWriteFlags);
@@ -622,7 +624,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
float zy;
float wp;
} vec;
- bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec));
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
assertOrNull(ok);
Q_UNUSED(ok);
property->writeProperty(_qobject, &vec, propertyWriteFlags);
@@ -635,7 +637,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
float yp;
float zp;
} vec;
- bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec));
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
assertOrNull(ok);
Q_UNUSED(ok);
property->writeProperty(_qobject, &vec, propertyWriteFlags);
@@ -649,12 +651,12 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
if (property->propType() == qMetaTypeId<QList<qreal> >()) {
assertType(QV4::CompiledData::Binding::Type_Number);
QList<qreal> value;
- value.append(binding->valueAsNumber(compilationUnit->constants));
+ value.append(compilationUnit->bindingValueAsNumber(binding));
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType() == qMetaTypeId<QList<int> >()) {
assertType(QV4::CompiledData::Binding::Type_Number);
- double n = binding->valueAsNumber(compilationUnit->constants);
+ double n = compilationUnit->bindingValueAsNumber(binding);
QList<int> value;
value.append(int(n));
property->writeProperty(_qobject, &value, propertyWriteFlags);
@@ -667,7 +669,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
} else if (property->propType() == qMetaTypeId<QList<QUrl> >()) {
assertType(QV4::CompiledData::Binding::Type_String);
- QString urlString = binding->valueAsString(compilationUnit.data());
+ QString urlString = compilationUnit->bindingValueAsString(binding);
QUrl u = urlString.isEmpty() ? QUrl()
: compilationUnit->finalUrl().resolved(QUrl(urlString));
QList<QUrl> value;
@@ -677,7 +679,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else if (property->propType() == qMetaTypeId<QList<QString> >()) {
assertOrNull(binding->evaluatesToString());
QList<QString> value;
- value.append(binding->valueAsString(compilationUnit.data()));
+ value.append(compilationUnit->bindingValueAsString(binding));
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType() == qMetaTypeId<QJSValue>()) {
@@ -685,7 +687,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
value = QJSValue(binding->valueAsBoolean());
} else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double n = binding->valueAsNumber(compilationUnit->constants);
+ double n = compilationUnit->bindingValueAsNumber(binding);
if (double(int(n)) == n) {
value = QJSValue(int(n));
} else
@@ -693,14 +695,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
value = QJSValue::NullValue;
} else {
- value = QJSValue(binding->valueAsString(compilationUnit.data()));
+ value = QJSValue(compilationUnit->bindingValueAsString(binding));
}
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
// otherwise, try a custom type assignment
- QString stringValue = binding->valueAsString(compilationUnit.data());
+ QString stringValue = compilationUnit->bindingValueAsString(binding);
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType());
Q_ASSERT(converter);
QVariant value = (*converter)(stringValue);
@@ -814,7 +816,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
- QV4::CompiledData::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
+ QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
Q_ASSERT(tr);
QQmlType attachedType = tr->type;
if (!attachedType.isValid()) {
@@ -833,13 +835,14 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
// ### resolve this at compile time
if (bindingProperty && bindingProperty->propType() == qMetaTypeId<QQmlScriptString>()) {
- QQmlScriptString ss(binding->valueAsScriptString(compilationUnit.data()), context->asQQmlContext(), _scopeObject);
+ QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
+ context->asQQmlContext(), _scopeObject);
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;
ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number;
- ss.d.data()->numberValue = binding->valueAsNumber(compilationUnit->constants);
+ ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
QQmlPropertyData::RemoveBindingOnAliasWrite;
@@ -1161,6 +1164,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
{
const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
+ Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
+ QString typeName;
+ Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, typeName);
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
@@ -1174,20 +1180,17 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent);
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit.data(), obj, QStringLiteral("<component>"), context->url()));
+ typeName = QStringLiteral("<component>");
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
} else {
- QV4::CompiledData::ResolvedTypeReference *typeRef
- = resolvedType(obj->inheritedTypeNameIndex);
+ QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType type = typeRef->type;
if (type.isValid()) {
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
+ typeName = type.qmlTypeName();
void *ddataMemory = nullptr;
type.create(&instance, &ddataMemory, sizeof(QQmlData));
@@ -1219,9 +1222,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
Q_ASSERT(typeRef->compilationUnit);
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit.data(), obj, typeRef->compilationUnit->fileName(),
- context->url()));
+ typeName = typeRef->compilationUnit->fileName();
if (typeRef->compilationUnit->unitData()->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1248,6 +1249,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
ddata = QQmlData::get(instance, /*create*/true);
}
+
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
+ compilationUnit.data(), obj, typeName, context->url()));
+ Q_UNUSED(typeName); // only relevant for tracing
+
ddata->lineNumber = obj->location.line;
ddata->columnNumber = obj->location.column;
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 5aca60e2f0..0766e2082e 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -85,7 +85,7 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr);
@@ -104,7 +104,7 @@ public:
QFiniteStack<QPointer<QObject> > &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
- QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
void init(QQmlContextData *parentContext);
@@ -125,7 +125,7 @@ private:
inline QV4::QmlContext *currentQmlContext();
Q_NEVER_INLINE void createQmlContext();
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
}
@@ -141,7 +141,7 @@ private:
QQmlEngine *engine;
QV4::ExecutionEngine *v4;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index fa05b3fe19..ae84803648 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -190,16 +190,13 @@ namespace QQmlPrivate
template<typename T>
class AttachedPropertySelector<T, 1>
{
- static inline QObject *attachedProperties(QObject *obj) {
- return T::qmlAttachedProperties(obj);
- }
template<typename ReturnType>
static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) {
return &ReturnType::staticMetaObject;
}
public:
static inline QQmlAttachedPropertiesFunc func() {
- return &attachedProperties;
+ return QQmlAttachedPropertiesFunc(&T::qmlAttachedProperties);
}
static inline const QMetaObject *metaObject() {
return attachedPropertiesMetaObject(&T::qmlAttachedProperties);
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index bafcba5971..285c34d7fa 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -59,6 +59,7 @@
#include <private/qqmlrefcount_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
+#include <private/qqmlpropertydata_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index a6546ae330..48c4216d54 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -868,7 +868,7 @@ QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int a
QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
{
bool unnamedParameter = false;
- const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
+ const QSet<QString> &illegalNames = engine->illegalNames();
QString parameters;
for (int i = 0; i < parameterNameList.count(); ++i) {
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 926e2810d5..6b4e0a0734 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -178,7 +178,7 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return QQmlType();
- QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
return QQmlMetaType::qmlType(mo);
}
@@ -192,7 +192,7 @@ QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) c
QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return nullptr;
- QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
return compilationUnit->rootPropertyCache().data();
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 457558fb56..1022412292 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -52,6 +52,7 @@
#include <private/qqmlpropertyvalidator_p.h>
#include <private/qqmlpropertycachecreator_p.h>
#include <private/qv4module_p.h>
+#include <private/qqmlirloader_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
@@ -2135,7 +2136,7 @@ const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() cons
return m_scripts;
}
-QV4::CompiledData::CompilationUnit *QQmlTypeData::compilationUnit() const
+QV4::ExecutableCompilationUnit *QQmlTypeData::compilationUnit() const
{
return m_compiledData.data();
}
@@ -2165,7 +2166,7 @@ bool QQmlTypeData::tryLoadFromDiskCache()
if (!v4)
return false;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Compiler::Codegen::createUnitForLoading();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> unit = QV4::ExecutableCompilationUnit::create();
{
QString error;
if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
@@ -2175,7 +2176,7 @@ bool QQmlTypeData::tryLoadFromDiskCache()
}
if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) {
- restoreIR(unit);
+ restoreIR(std::move(*unit));
return true;
}
@@ -2231,8 +2232,9 @@ bool QQmlTypeData::tryLoadFromDiskCache()
return true;
}
-void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
+void QQmlTypeData::createTypeAndPropertyCaches(
+ const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
+ const QV4::ResolvedTypeReferenceMap &resolvedTypeCache)
{
Q_ASSERT(m_compiledData);
m_compiledData->typeNameCache = typeNameCache;
@@ -2243,9 +2245,9 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
QQmlPendingGroupPropertyBindings pendingGroupPropertyBindings;
{
- QQmlPropertyCacheCreator<QV4::CompiledData::CompilationUnit> propertyCacheCreator(&m_compiledData->propertyCaches,
- &pendingGroupPropertyBindings,
- engine, m_compiledData.data(), &m_importCache);
+ QQmlPropertyCacheCreator<QV4::ExecutableCompilationUnit> propertyCacheCreator(
+ &m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine,
+ m_compiledData.data(), &m_importCache);
QQmlCompileError error = propertyCacheCreator.buildMetaObjects();
if (error.isSet()) {
setError(error);
@@ -2253,7 +2255,8 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
}
}
- QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData.data());
+ QQmlPropertyCacheAliasCreator<QV4::ExecutableCompilationUnit> aliasCreator(
+ &m_compiledData->propertyCaches, m_compiledData.data());
aliasCreator.appendAliasPropertiesToMetaObjects();
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
@@ -2345,7 +2348,7 @@ void QQmlTypeData::done()
}
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
- QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
+ QV4::ResolvedTypeReferenceMap resolvedTypeCache;
{
QQmlCompileError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
if (error.isSet()) {
@@ -2356,10 +2359,12 @@ void QQmlTypeData::done()
QQmlEngine *const engine = typeLoader()->engine();
- const auto dependencyHasher = [engine, &resolvedTypeCache, this](QCryptographicHash *hash) {
- if (!resolvedTypeCache.addToHash(hash, engine))
- return false;
- return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine);
+ const auto dependencyHasher = [engine, &resolvedTypeCache, this]() {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ return (resolvedTypeCache.addToHash(&hash, engine)
+ && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash, engine))
+ ? hash.result()
+ : QByteArray();
};
// verify if any dependencies changed if we're using a cache
@@ -2502,11 +2507,11 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data)
void QQmlTypeData::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QmlIR::IRLoader loader(unit, m_document.data());
+ QQmlIRLoader loader(unit, m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
- m_document->javaScriptCompilationUnit.adopt(new QV4::CompiledData::CompilationUnit(unit));
+ m_document->javaScriptCompilationUnit = QV4::CompiledData::CompilationUnit(unit);
continueLoadFromIR();
}
@@ -2515,7 +2520,7 @@ bool QQmlTypeData::loadFromSource()
m_document.reset(new QmlIR::Document(isDebugging()));
m_document->jsModule.sourceTimeStamp = m_backupSourceCode.sourceTimeStamp();
QQmlEngine *qmlEngine = typeLoader()->engine();
- QmlIR::IRBuilder compiler(qmlEngine->handle()->v8Engine->illegalNames());
+ QmlIR::IRBuilder compiler(qmlEngine->handle()->illegalNames());
QString sourceError;
const QString source = m_backupSourceCode.readAll(&sourceError);
@@ -2541,14 +2546,14 @@ bool QQmlTypeData::loadFromSource()
return true;
}
-void QQmlTypeData::restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit)
+void QQmlTypeData::restoreIR(QV4::CompiledData::CompilationUnit &&unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QmlIR::IRLoader loader(unit->unitData(), m_document.data());
+ QQmlIRLoader loader(unit.unitData(), m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
- m_document->javaScriptCompilationUnit = unit;
+ m_document->javaScriptCompilationUnit = std::move(unit);
continueLoadFromIR();
}
@@ -2647,12 +2652,13 @@ QString QQmlTypeData::stringAt(int index) const
}
void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
{
Q_ASSERT(m_compiledData.isNull());
- const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit && m_document->javaScriptCompilationUnit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation;
+ const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit.unitData()
+ && (m_document->javaScriptCompilationUnit.unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation);
QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache, dependencyHasher);
@@ -2771,7 +2777,7 @@ void QQmlTypeData::resolveTypes()
QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache
) const
{
typeNameCache->adopt(new QQmlTypeNameCache(m_importCache));
@@ -2788,7 +2794,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
- QScopedPointer<QV4::CompiledData::ResolvedTypeReference> ref(new QV4::CompiledData::ResolvedTypeReference);
+ QScopedPointer<QV4::ResolvedTypeReference> ref(new QV4::ResolvedTypeReference);
QQmlType qmlType = resolvedType->type;
if (resolvedType->typeData) {
if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) {
@@ -3019,7 +3025,8 @@ QQmlRefPointer<QQmlScriptData> QQmlScriptBlob::scriptData() const
void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
{
if (!disableDiskCache() || forceDiskCache()) {
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Compiler::Codegen::createUnitForLoading();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
+ = QV4::ExecutableCompilationUnit::create();
QString error;
if (unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
initializeFromCompilationUnit(unit);
@@ -3044,11 +3051,12 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
return;
}
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit;
+ QV4::CompiledData::CompilationUnit unit;
if (m_isModule) {
QList<QQmlJS::DiagnosticMessage> diagnostics;
- unit = QV4::ExecutionEngine::compileModule(isDebugging(), urlString(), source, data.sourceTimeStamp(), &diagnostics);
+ unit = QV4::Compiler::Codegen::compileModule(isDebugging(), urlString(), source,
+ data.sourceTimeStamp(), &diagnostics);
QList<QQmlError> errors = QQmlEnginePrivate::qmlErrorFromDiagnostics(urlString(), diagnostics);
if (!errors.isEmpty()) {
setError(errors);
@@ -3063,44 +3071,43 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
irUnit.jsParserEngine.setDirectives(&collector);
QList<QQmlError> errors;
- unit = QV4::Script::precompile(
- &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(),
- source, &errors, QV4::Compiler::ContextType::ScriptImportedByQML);
- // No need to addref on unit, it's initial refcount is 1
+ irUnit.javaScriptCompilationUnit = QV4::Script::precompile(
+ &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(),
+ source, &errors, QV4::Compiler::ContextType::ScriptImportedByQML);
+
source.clear();
if (!errors.isEmpty()) {
setError(errors);
return;
}
- if (!unit) {
- unit.adopt(new QV4::CompiledData::CompilationUnit);
- }
- irUnit.javaScriptCompilationUnit = unit;
QmlIR::QmlUnitGenerator qmlGenerator;
qmlGenerator.generate(irUnit);
+ unit = std::move(irUnit.javaScriptCompilationUnit);
}
+ auto executableUnit = QV4::ExecutableCompilationUnit::create(std::move(unit));
+
if ((!disableDiskCache() || forceDiskCache()) && !isDebugging()) {
QString errorString;
- if (unit->saveToDisk(url(), &errorString)) {
+ if (executableUnit->saveToDisk(url(), &errorString)) {
QString error;
- if (!unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
+ if (!executableUnit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
// ignore error, keep using the in-memory compilation unit.
}
} else {
- qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->fileName() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of"
+ << executableUnit->fileName() << "to disk:" << errorString;
}
}
- initializeFromCompilationUnit(unit);
+ initializeFromCompilationUnit(executableUnit);
}
void QQmlScriptBlob::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit)
{
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
- compilationUnit.adopt(new QV4::CompiledData::CompilationUnit(unit, urlString(), finalUrlString()));
- initializeFromCompilationUnit(compilationUnit);
+ initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create(
+ QV4::CompiledData::CompilationUnit(unit, urlString(), finalUrlString())));
}
void QQmlScriptBlob::done()
@@ -3165,7 +3172,7 @@ void QQmlScriptBlob::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob,
m_scripts << ref;
}
-void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit)
+void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit)
{
Q_ASSERT(!m_scriptData);
m_scriptData.adopt(new QQmlScriptData());
@@ -3175,7 +3182,7 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::Com
m_importCache.setBaseUrl(finalUrl(), finalUrlString());
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> script = m_scriptData->m_precompiledScript;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> script = m_scriptData->m_precompiledScript;
if (!m_isModule) {
QList<QQmlError> errors;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 987e47222d..d87812d48e 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -70,6 +70,7 @@
#include <private/qqmldirparser_p.h>
#include <private/qflagpointer_p.h>
#include <private/qqmlirbuilder_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#include <private/qv4value_p.h>
#include <private/qv4script_p.h>
@@ -453,7 +454,7 @@ public:
const QList<ScriptReference> &resolvedScripts() const;
- QV4::CompiledData::CompilationUnit *compilationUnit() const;
+ QV4::ExecutableCompilationUnit *compilationUnit() const;
// Used by QQmlComponent to get notifications
struct TypeDataCallback {
@@ -477,18 +478,18 @@ protected:
private:
bool tryLoadFromDiskCache();
bool loadFromSource();
- void restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit);
+ void restoreIR(QV4::CompiledData::CompilationUnit &&unit);
void continueLoadFromIR();
void resolveTypes();
QQmlCompileError buildTypeResolutionCaches(
QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache
) const;
void compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
+ const QV4::ResolvedTypeReferenceMap &resolvedTypeCache);
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
TypeReference &ref, int lineNumber = -1, int columnNumber = -1,
bool reportErrors = true,
@@ -512,7 +513,7 @@ private:
QMap<int, TypeReference> m_resolvedTypes;
bool m_typesResolved:1;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compiledData;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compiledData;
QList<TypeDataCallback *> m_callbacks;
@@ -542,7 +543,7 @@ public:
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit() const { return m_precompiledScript; }
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() const { return m_precompiledScript; }
protected:
void clear() override; // From QQmlCleanup
@@ -554,7 +555,7 @@ private:
QQmlContextData *qmlContextDataForContext(QQmlContextData *parentQmlContextData);
bool m_loaded;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_precompiledScript;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_precompiledScript;
QV4::PersistentValue m_value;
};
@@ -587,7 +588,7 @@ protected:
private:
void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
- void initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
+ void initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit);
QList<ScriptReference> m_scripts;
QQmlRefPointer<QQmlScriptData> m_scriptData;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 236daac75c..9db089c330 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -418,7 +418,7 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
return Encode(false);
QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
- CompiledData::CompilationUnit *cu = td->compilationUnit();
+ ExecutableCompilationUnit *cu = td->compilationUnit();
myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
} else {
myQmlType = qenginepriv->metaObjectForType(myTypeId);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index f08005fd20..fce753cd26 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -39,6 +39,7 @@
#include "qqmlvaluetype_p.h"
+#include <QtCore/qmutex.h>
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
#include <private/qmetaobjectbuilder_p.h>
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 5d13415513..2881e71805 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -316,7 +316,7 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine,
QObject *obj,
- const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId)
+ const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit, int qmlObjectId)
: QQmlInterceptorMetaObject(obj, cache),
engine(engine),
ctxt(QQmlData::get(obj, true)->outerContext),
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 2371d70f10..5025987586 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -144,7 +144,7 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId);
+ QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit, int qmlObjectId);
~QQmlVMEMetaObject() override;
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
@@ -226,7 +226,7 @@ public:
// keep a reference to the compilation unit in order to still
// do property access when the context has been invalidated.
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QV4::CompiledData::Object *compiledObject;
};
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index c6b7f2ab3f..b435f8ef66 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -95,7 +95,7 @@ struct QQmlXMLHttpRequestData {
static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
{
- return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
+ return (QQmlXMLHttpRequestData *)v4->xmlHttpRequestData();
}
QQmlXMLHttpRequestData::QQmlXMLHttpRequestData()
@@ -591,7 +591,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
if (d->nodePrototype.isUndefined()) {
ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>());
d->nodePrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->nodePrototype.value();
}
@@ -640,7 +640,7 @@ ReturnedValue Element::prototype(ExecutionEngine *engine)
p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
d->elementPrototype.set(engine, p);
- engine->v8Engine->freezeObject(p);
+ engine->freezeObject(p);
}
return d->elementPrototype.value();
}
@@ -657,7 +657,7 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
d->attrPrototype.set(engine, p);
- engine->v8Engine->freezeObject(p);
+ engine->freezeObject(p);
}
return d->attrPrototype.value();
}
@@ -713,7 +713,7 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
d->characterDataPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->characterDataPrototype.value();
}
@@ -749,7 +749,7 @@ ReturnedValue Text::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
d->textPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->textPrototype.value();
}
@@ -764,7 +764,7 @@ ReturnedValue CDATA::prototype(ExecutionEngine *v4)
ScopedObject pp(scope);
p->setPrototypeUnchecked((pp = Text::prototype(v4)));
d->cdataPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->cdataPrototype.value();
}
@@ -782,7 +782,7 @@ ReturnedValue Document::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, nullptr);
d->documentPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->documentPrototype.value();
}
@@ -1646,7 +1646,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Scope scope(f->engine());
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine);
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->qmlEngine()->networkAccessManager(), scope.engine);
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototypeUnchecked(proto);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 3bc588b50e..4838ef3814 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -47,7 +47,6 @@
#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
#endif
-#include <private/qv8engine_p.h>
#include <private/qqmldelayedcallqueue_p.h>
#include <QFileInfo>
@@ -1684,10 +1683,8 @@ ReturnedValue ConsoleObject::method_time(const FunctionObject *b, const Value *,
if (argc != 1)
THROW_GENERIC_ERROR("console.time(): Invalid arguments");
- QV8Engine *v8engine = scope.engine->v8Engine;
-
QString name = argv[0].toQStringNoThrow();
- v8engine->startTimer(name);
+ scope.engine->startTimer(name);
return QV4::Encode::undefined();
}
@@ -1697,11 +1694,9 @@ ReturnedValue ConsoleObject::method_timeEnd(const FunctionObject *b, const Value
if (argc != 1)
THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments");
- QV8Engine *v8engine = scope.engine->v8Engine;
-
QString name = argv[0].toQStringNoThrow();
bool wasRunning;
- qint64 elapsed = v8engine->stopTimer(name, &wasRunning);
+ qint64 elapsed = scope.engine->stopTimer(name, &wasRunning);
if (wasRunning) {
qDebug("%s: %llims", qPrintable(name), elapsed);
}
@@ -1717,13 +1712,12 @@ ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value *
Scope scope(b);
QV4::ExecutionEngine *v4 = scope.engine;
- QV8Engine *v8engine = scope.engine->v8Engine;
QV4::CppStackFrame *frame = v4->currentStackFrame;
QString scriptName = frame->source();
- int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), 0);
+ int value = v4->consoleCountHelper(scriptName, frame->lineNumber(), 0);
QString message = name + QLatin1String(": ") + QString::number(value);
QMessageLogger(qPrintable(scriptName), frame->lineNumber(),
@@ -1956,7 +1950,8 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
CppStackFrame *frame = scope.engine->currentStackFrame;
// The first non-empty source URL in the call stack determines the translation context.
while (frame && context.isEmpty()) {
- if (CompiledData::CompilationUnit *unit = frame->v4Function->compilationUnit) {
+ if (CompiledData::CompilationUnitBase *baseUnit = frame->v4Function->compilationUnit) {
+ const auto *unit = static_cast<const CompiledData::CompilationUnit *>(baseUnit);
QString fileName = unit->fileName();
QUrl url(unit->fileName());
if (url.isValid() && url.isRelative()) {
@@ -2147,8 +2142,7 @@ function.
*/
ReturnedValue QtObject::method_callLater(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
- QV8Engine *v8engine = b->engine()->v8Engine;
- return v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
+ return b->engine()->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
deleted file mode 100644
index d76344b613..0000000000
--- a/src/qml/qml/v8/qv8engine.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv8engine_p.h"
-
-#if QT_CONFIG(qml_sequence_object)
-#include "qv4sequenceobject_p.h"
-#endif
-
-#include "private/qjsengine_p.h"
-
-#include <private/qqmlbuiltinfunctions_p.h>
-#include <private/qqmllist_p.h>
-#include <private/qqmlengine_p.h>
-#if QT_CONFIG(qml_xml_http_request)
-#include <private/qqmlxmlhttprequest_p.h>
-#endif
-#if QT_CONFIG(qml_locale)
-#include <private/qqmllocale_p.h>
-#endif
-#include <private/qqmlglobal_p.h>
-#include <private/qqmlmemoryprofiler_p.h>
-#include <private/qqmlplatform_p.h>
-#include <private/qjsvalue_p.h>
-#include <private/qqmltypewrapper_p.h>
-#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qqmllistwrapper_p.h>
-#include <private/qv4scopedvalue_p.h>
-
-#include "qv4domerrors_p.h"
-#include "qv4sqlerrors_p.h"
-
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qjsonvalue.h>
-#include <QtCore/qdatetime.h>
-#include <QtCore/qdatastream.h>
-#include <private/qsimd_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4mm_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qv4globalobject_p.h>
-#include <private/qv4regexpobject_p.h>
-#include <private/qv4variantobject_p.h>
-#include <private/qv4script_p.h>
-#include <private/qv4include_p.h>
-#include <private/qv4jsonobject_p.h>
-#include <private/qv4identifiertable_p.h>
-
-Q_DECLARE_METATYPE(QList<int>)
-
-
-// XXX TODO: Need to check all the global functions will also work in a worker script where the
-// QQmlEngine is not available
-QT_BEGIN_NAMESPACE
-
-template <typename ReturnType>
-ReturnType convertJSValueToVariantType(const QJSValue &value)
-{
- return value.toVariant().value<ReturnType>();
-}
-
-static void saveJSValue(QDataStream &stream, const void *data)
-{
- const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
- quint32 isNullOrUndefined = 0;
- if (jsv->isNull())
- isNullOrUndefined |= 0x1;
- if (jsv->isUndefined())
- isNullOrUndefined |= 0x2;
- stream << isNullOrUndefined;
- if (!isNullOrUndefined)
- reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
-}
-
-static void restoreJSValue(QDataStream &stream, void *data)
-{
- QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
-
- quint32 isNullOrUndefined;
- stream >> isNullOrUndefined;
-
- if (isNullOrUndefined & 0x1) {
- *jsv = QJSValue(QJSValue::NullValue);
- } else if (isNullOrUndefined & 0x2) {
- *jsv = QJSValue();
- } else {
- QVariant v;
- v.load(stream);
- QJSValuePrivate::setVariant(jsv, v);
- }
-}
-
-QV8Engine::QV8Engine(QV4::ExecutionEngine *v4)
- : m_engine(nullptr)
- , m_v4Engine(v4)
-#if QT_CONFIG(qml_xml_http_request)
- , m_xmlHttpRequestData(nullptr)
-#endif
-{
-#ifndef Q_OS_WASM // wasm does not have working simd QTBUG-63924
-#ifdef Q_PROCESSOR_X86_32
- if (!qCpuHasFeature(SSE2)) {
- qFatal("This program requires an X86 processor that supports SSE2 extension, at least a Pentium 4 or newer");
- }
-#endif
-#endif
-
- QML_MEMORY_SCOPE_STRING("QV8Engine::QV8Engine");
- qMetaTypeId<QJSValue>();
- qMetaTypeId<QList<int> >();
-
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
- QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
- QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
- QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
- QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
-
- m_delayedCallQueue.init(m_v4Engine);
-
- QV4::QObjectWrapper::initializeBindings(m_v4Engine);
-}
-
-QV8Engine::~QV8Engine()
-{
- qDeleteAll(m_extensionData);
- m_extensionData.clear();
-
-#if QT_CONFIG(qml_xml_http_request)
- qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
- m_xmlHttpRequestData = nullptr;
-#endif
-}
-
-#if QT_CONFIG(qml_network)
-QNetworkAccessManager *QV8Engine::networkAccessManager()
-{
- return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
-}
-#endif
-
-const QSet<QString> &QV8Engine::illegalNames() const
-{
- return m_illegalNames;
-}
-
-void QV8Engine::initializeGlobal()
-{
- QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions);
-
- QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocate<QV4::QtObject>(m_engine));
- m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
-
-#if QT_CONFIG(qml_locale)
- QQmlLocale::registerStringLocaleCompare(m_v4Engine);
- QQmlDateExtension::registerExtension(m_v4Engine);
- QQmlNumberExtension::registerExtension(m_v4Engine);
-#endif
-
-#if QT_CONFIG(qml_xml_http_request)
- qt_add_domexceptions(m_v4Engine);
- m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
-#endif
-
- qt_add_sqlexceptions(m_v4Engine);
-
- {
- for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject->internalClass()->nameMap.at(i).isString()) {
- QV4::PropertyKey id = m_v4Engine->globalObject->internalClass()->nameMap.at(i);
- m_illegalNames.insert(id.toQString());
- }
- }
- }
-}
-
-static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
-{
- if (object->as<QV4::QObjectWrapper>())
- return;
-
- QV4::Scope scope(v4);
-
- bool instanceOfObject = false;
- QV4::ScopedObject p(scope, object->getPrototypeOf());
- while (p) {
- if (p->d() == v4->objectPrototype()->d()) {
- instanceOfObject = true;
- break;
- }
- p = p->getPrototypeOf();
- }
- if (!instanceOfObject)
- return;
-
- QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
- if (object->internalClass() == frozen)
- return;
- object->setInternalClass(frozen);
-
- QV4::ScopedObject o(scope);
- for (uint i = 0; i < frozen->size; ++i) {
- if (!frozen->nameMap.at(i).isStringOrSymbol())
- continue;
- o = *object->propertyData(i);
- if (o)
- freeze_recursive(v4, o);
- }
-}
-
-void QV8Engine::freezeObject(const QV4::Value &value)
-{
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedObject o(scope, value);
- freeze_recursive(m_v4Engine, o);
-}
-
-struct QV8EngineRegistrationData
-{
- QV8EngineRegistrationData() : extensionCount(0) {}
-
- QMutex mutex;
- int extensionCount;
-};
-Q_GLOBAL_STATIC(QV8EngineRegistrationData, registrationData);
-
-QMutex *QV8Engine::registrationMutex()
-{
- return &registrationData()->mutex;
-}
-
-int QV8Engine::registerExtension()
-{
- return registrationData()->extensionCount++;
-}
-
-void QV8Engine::setExtensionData(int index, Deletable *data)
-{
- if (m_extensionData.count() <= index)
- m_extensionData.resize(index + 1);
-
- if (m_extensionData.at(index))
- delete m_extensionData.at(index);
-
- m_extensionData[index] = data;
-}
-
-void QV8Engine::initQmlGlobalObject()
-{
- initializeGlobal();
- freezeObject(*m_v4Engine->globalObject);
-}
-
-void QV8Engine::setEngine(QQmlEngine *engine)
-{
- m_engine = engine;
- initQmlGlobalObject();
-}
-
-void QV8Engine::startTimer(const QString &timerName)
-{
- if (!m_time.isValid())
- m_time.start();
- m_startedTimers[timerName] = m_time.elapsed();
-}
-
-qint64 QV8Engine::stopTimer(const QString &timerName, bool *wasRunning)
-{
- if (!m_startedTimers.contains(timerName)) {
- *wasRunning = false;
- return 0;
- }
- *wasRunning = true;
- qint64 startedAt = m_startedTimers.take(timerName);
- return m_time.elapsed() - startedAt;
-}
-
-int QV8Engine::consoleCountHelper(const QString &file, quint16 line, quint16 column)
-{
- const QString key = file + QString::number(line) + QString::number(column);
- int number = m_consoleCount.value(key, 0);
- number++;
- m_consoleCount.insert(key, number);
- return number;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
deleted file mode 100644
index f9b69cfacc..0000000000
--- a/src/qml/qml/v8/qv8engine_p.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLV8ENGINE_P_H
-#define QQMLV8ENGINE_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/qglobal.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qset.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qstack.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/QElapsedTimer>
-#include <QtCore/QThreadStorage>
-
-#include <QtQml/qjsengine.h>
-#include "private/qintrusivelist_p.h"
-
-
-#include <private/qv4value_p.h>
-#include <private/qv4identifier_p.h>
-#include <private/qv4context_p.h>
-#include <private/qv4stackframe_p.h>
-#include <private/qqmldelayedcallqueue_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
- struct ArrayObject;
- struct ExecutionEngine;
- struct QObjectMethod;
-}
-
-#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
- static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
- { \
- static int extensionId = -1; \
- if (extensionId == -1) { \
- QV8Engine::registrationMutex()->lock(); \
- if (extensionId == -1) \
- extensionId = QV8Engine::registerExtension(); \
- QV8Engine::registrationMutex()->unlock(); \
- } \
- dataclass *rv = (dataclass *)engine->v8Engine->extensionData(extensionId); \
- if (!rv) { \
- rv = new dataclass(engine); \
- engine->v8Engine->setExtensionData(extensionId, rv); \
- } \
- return rv; \
- } \
-
-// 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(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 QQmlV4Function
-{
-public:
- int length() const { return callData->argc(); }
- QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
- QV4::ExecutionEngine *v4engine() const { return e; }
-private:
- friend struct QV4::QObjectMethod;
- QQmlV4Function();
- QQmlV4Function(const QQmlV4Function &);
- QQmlV4Function &operator=(const QQmlV4Function &);
-
- QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
- : callData(callData), retVal(retVal), e(e)
- {
- callData->thisObject = QV4::Encode::undefined();
- }
-
- QV4::CallData *callData;
- QV4::Value *retVal;
- QV4::ExecutionEngine *e;
-};
-
-class QObject;
-class QQmlEngine;
-class QNetworkAccessManager;
-class QQmlContextData;
-
-class Q_QML_PRIVATE_EXPORT QV8Engine
-{
- friend class QJSEngine;
-public:
-// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
- static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; }
-
- QV8Engine(QV4::ExecutionEngine *v4);
- virtual ~QV8Engine();
-
- // This enum should be in sync with QQmlEngine::ObjectOwnership
- enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
-
- struct Deletable {
- virtual ~Deletable() {}
- };
-
- void initQmlGlobalObject();
- void setEngine(QQmlEngine *engine);
- QQmlEngine *engine() { return m_engine; }
- QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
-
-#if QT_CONFIG(qml_xml_http_request)
- void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
-#endif
-
- void freezeObject(const QV4::Value &value);
-
-#if QT_CONFIG(qml_network)
- // Return the network access manager for this engine. By default this returns the network
- // access manager of the QQmlEngine. It is overridden in the case of a threaded v8
- // instance (like in WorkerScript).
- virtual QNetworkAccessManager *networkAccessManager();
-#endif
-
- // Return the list of illegal id names (the names of the properties on the global object)
- const QSet<QString> &illegalNames() const;
-
- static QMutex *registrationMutex();
- static int registerExtension();
-
- inline Deletable *extensionData(int) const;
- void setExtensionData(int, Deletable *);
-
-public:
- // used for console.time(), console.timeEnd()
- void startTimer(const QString &timerName);
- qint64 stopTimer(const QString &timerName, bool *wasRunning);
-
- // used for console.count()
- int consoleCountHelper(const QString &file, quint16 line, quint16 column);
-
-protected:
- QQmlEngine *m_engine;
- QQmlDelayedCallQueue m_delayedCallQueue;
-
- QV4::ExecutionEngine *m_v4Engine;
-
-#if QT_CONFIG(qml_xml_http_request)
- void *m_xmlHttpRequestData;
-#endif
-
- QVector<Deletable *> m_extensionData;
-
- QSet<QString> m_illegalNames;
-
- QElapsedTimer m_time;
- QHash<QString, qint64> m_startedTimers;
-
- QHash<QString, quint32> m_consoleCount;
-
- void initializeGlobal();
-
-private:
- Q_DISABLE_COPY(QV8Engine)
-};
-
-inline QV8Engine::Deletable *QV8Engine::extensionData(int index) const
-{
- if (index < m_extensionData.count())
- return m_extensionData[index];
- else
- return nullptr;
-}
-
-
-QT_END_NAMESPACE
-
-#endif // QQMLV8ENGINE_P_H
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index 4592022939..fbcc47de0c 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,11 +1,9 @@
HEADERS += \
- $$PWD/qv8engine_p.h \
$$PWD/qv4domerrors_p.h \
$$PWD/qv4sqlerrors_p.h \
$$PWD/qqmlbuiltinfunctions_p.h
SOURCES += \
- $$PWD/qv8engine.cpp \
$$PWD/qv4domerrors.cpp \
$$PWD/qv4sqlerrors.cpp \
$$PWD/qqmlbuiltinfunctions.cpp
diff --git a/src/qml/qtqml.tracepoints b/src/qml/qtqml.tracepoints
new file mode 100644
index 0000000000..841748f201
--- /dev/null
+++ b/src/qml/qtqml.tracepoints
@@ -0,0 +1,14 @@
+{
+namespace QV4 {
+class ExecutionEngine;
+namespace CompiledData {
+class CompilationUnit;
+class Object;
+} // CompiledData
+} // QV4
+}
+
+QQmlObjectCreator_createInstance_entry(const QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Object *object, const QUrl &url)
+QQmlObjectCreator_createInstance_exit(const QString &typeName)
+QQmlV4_function_call_entry(const QV4::ExecutionEngine *engine, const QString &function, const QString &fileName, int line, int column)
+QQmlV4_function_call_exit()
diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h
index a111f72e81..3e275c6359 100644
--- a/src/qml/qtqmlglobal.h
+++ b/src/qml/qtqmlglobal.h
@@ -54,6 +54,8 @@
# define QT_FEATURE_qml_debug -1
# define QT_FEATURE_qml_sequence_object 1
# define QT_FEATURE_qml_jit -1
+# define QT_FEATURE_qml_worker_script -1
+# define QT_FEATURE_qml_xml_http_request -1
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 513f7f2997..1ba015f796 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -43,6 +43,8 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlmetatype_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+#include <private/qv4persistent_p.h>
#include <qqmlengine.h>
#include <qqmlcontext.h>
@@ -60,7 +62,21 @@ QT_BEGIN_NAMESPACE
class QQmlBindPrivate : public QObjectPrivate
{
public:
- QQmlBindPrivate() : obj(nullptr), componentComplete(true), delayed(false), pendingEval(false) {}
+ QQmlBindPrivate()
+ : obj(nullptr)
+ , prevBind(QQmlAbstractBinding::Ptr())
+ , prevIsVariant(false)
+ , componentComplete(true)
+ , delayed(false)
+ , pendingEval(false)
+ , restoreBinding(true)
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ , restoreValue(false)
+ , restoreModeExplicit(false)
+#else
+ , restoreValue(true)
+#endif
+ {}
~QQmlBindPrivate() { }
QQmlNullableValue<bool> when;
@@ -69,11 +85,20 @@ public:
QQmlNullableValue<QVariant> value;
QQmlProperty prop;
QQmlAbstractBinding::Ptr prevBind;
+ QV4::PersistentValue v4Value;
+ QVariant prevValue;
+ bool prevIsVariant:1;
bool componentComplete:1;
bool delayed:1;
bool pendingEval:1;
+ bool restoreBinding:1;
+ bool restoreValue:1;
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ bool restoreModeExplicit:1;
+#endif
void validate(QObject *binding) const;
+ void clearPrev();
};
void QQmlBindPrivate::validate(QObject *binding) const
@@ -323,6 +348,57 @@ void QQmlBind::setDelayed(bool delayed)
eval();
}
+/*!
+ \qmlproperty enumeration QtQml::Binding::restoreMode
+ \since 5.14
+
+ This property can be used to describe if and how the original value should
+ be restored when the binding is disabled.
+
+ The possible values are:
+ \list
+ \li Binding.RestoreNone The original value is not restored at all
+ \li Binding.RestoreBinding The original value is restored if it was another
+ binding. In that case the old binding is in effect again.
+ \li Binding.RestoreValue The original value is restored if it was a plain
+ value rather than a binding.
+ \li Binding.RestoreBindingOrValue The original value is always restored.
+ \list
+
+ \warning The default value is Binding.RestoreBinding. This will change in
+ Qt 5.15 to Binding.RestoreBindingOrValue.
+
+ If you rely on any specific behavior regarding the restoration of plain
+ values when bindings get disabled you should migrate to explicitly set the
+ restoreMode.
+
+ Reliance on a restoreMode that doesn't restore the previous binding or value
+ for a specific property results in a run-time warning.
+*/
+QQmlBind::RestorationMode QQmlBind::restoreMode() const
+{
+ Q_D(const QQmlBind);
+ unsigned result = RestoreNone;
+ if (d->restoreValue)
+ result |= RestoreValue;
+ if (d->restoreBinding)
+ result |= RestoreBinding;
+ return RestorationMode(result);
+}
+
+void QQmlBind::setRestoreMode(RestorationMode newMode)
+{
+ Q_D(QQmlBind);
+ if (newMode != restoreMode()) {
+ d->restoreValue = (newMode & RestoreValue);
+ d->restoreBinding = (newMode & RestoreBinding);
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ d->restoreModeExplicit = true;
+#endif
+ emit restoreModeChanged();
+ }
+}
+
void QQmlBind::setTarget(const QQmlProperty &p)
{
Q_D(QQmlBind);
@@ -358,6 +434,14 @@ void QQmlBind::prepareEval()
}
}
+void QQmlBindPrivate::clearPrev()
+{
+ prevBind = nullptr;
+ v4Value.clear();
+ prevValue.clear();
+ prevIsVariant = false;
+}
+
void QQmlBind::eval()
{
Q_D(QQmlBind);
@@ -369,16 +453,64 @@ void QQmlBind::eval()
if (!d->when) {
//restore any previous binding
if (d->prevBind) {
- QQmlAbstractBinding::Ptr p = d->prevBind;
- d->prevBind = nullptr;
- QQmlPropertyPrivate::setBinding(p.data());
+ if (d->restoreBinding) {
+ QQmlAbstractBinding::Ptr p = d->prevBind;
+ d->clearPrev(); // Do that before setBinding(), as setBinding() may recurse.
+ QQmlPropertyPrivate::setBinding(p.data());
+ }
+ } else if (!d->v4Value.isEmpty()) {
+ if (d->restoreValue) {
+ auto propPriv = QQmlPropertyPrivate::get(d->prop);
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
+ Q_ASSERT(vmemo);
+ vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef());
+ d->clearPrev();
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ } else if (!d->restoreModeExplicit) {
+ qmlWarning(this)
+ << "Not restoring previous value because restoreMode has not been set."
+ << "This behavior is deprecated."
+ << "In Qt < 5.15 the default is Binding.RestoreBinding."
+ << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue.";
+#endif
+ }
+ } else if (d->prevIsVariant) {
+ if (d->restoreValue) {
+ d->prop.write(d->prevValue);
+ d->clearPrev();
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+ } else if (!d->restoreModeExplicit) {
+ qmlWarning(this)
+ << "Not restoring previous value because restoreMode has not been set."
+ << "This behavior is deprecated."
+ << "In Qt < 5.15 the default is Binding.RestoreBinding."
+ << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue.";
+#endif
+ }
}
return;
}
//save any set binding for restoration
- if (!d->prevBind)
+ if (!d->prevBind && d->v4Value.isEmpty() && !d->prevIsVariant) {
+ // try binding first
d->prevBind = QQmlPropertyPrivate::binding(d->prop);
+
+ if (!d->prevBind) { // nope, try a V4 value next
+ auto propPriv = QQmlPropertyPrivate::get(d->prop);
+ auto propData = propPriv->core;
+ if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
+ Q_ASSERT(vmemo);
+ auto retVal = vmemo->vmeProperty(propData.coreIndex());
+ d->v4Value = QV4::PersistentValue(vmemo->engine, retVal);
+ } else { // nope, use the meta object to get a QVariant
+ d->prevValue = d->prop.read();
+ d->prevIsVariant = true;
+ }
+ }
+ }
+
QQmlPropertyPrivate::removeBinding(d->prop);
}
diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h
index 5bf9ef85c6..22007a3d25 100644
--- a/src/qml/types/qqmlbind_p.h
+++ b/src/qml/types/qqmlbind_p.h
@@ -60,6 +60,15 @@ QT_BEGIN_NAMESPACE
class QQmlBindPrivate;
class Q_AUTOTEST_EXPORT QQmlBind : public QObject, public QQmlPropertyValueSource, public QQmlParserStatus
{
+public:
+ enum RestorationMode {
+ RestoreNone = 0x0,
+ RestoreBinding = 0x1,
+ RestoreValue = 0x2,
+ RestoreBindingOrValue = RestoreBinding | RestoreValue
+ };
+
+private:
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlBind)
Q_INTERFACES(QQmlParserStatus)
@@ -69,6 +78,9 @@ class Q_AUTOTEST_EXPORT QQmlBind : public QObject, public QQmlPropertyValueSourc
Q_PROPERTY(QVariant value READ value WRITE setValue)
Q_PROPERTY(bool when READ when WRITE setWhen)
Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8)
+ Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode
+ NOTIFY restoreModeChanged REVISION 14)
+ Q_ENUM(RestorationMode)
public:
QQmlBind(QObject *parent=nullptr);
@@ -89,6 +101,12 @@ public:
bool delayed() const;
void setDelayed(bool);
+ RestorationMode restoreMode() const;
+ void setRestoreMode(RestorationMode);
+
+Q_SIGNALS:
+ void restoreModeChanged();
+
protected:
void setTarget(const QQmlProperty &) override;
void classBegin() override;
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index f601087690..8ec754a9df 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -66,7 +66,7 @@ public:
bool ignoreUnknownSignals;
bool componentcomplete;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding *> bindings;
};
@@ -231,7 +231,7 @@ void QQmlConnections::setIgnoreUnknownSignals(bool ignore)
d->ignoreUnknownSignals = ignore;
}
-void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
+void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
for (int ii = 0; ii < props.count(); ++ii) {
const QV4::CompiledData::Binding *binding = props.at(ii);
@@ -256,7 +256,7 @@ void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer<QV4::CompiledDat
}
}
-void QQmlConnectionsParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlConnectionsParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlConnectionsPrivate *p =
static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index bd03d7e152..f6ad1eb46c 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -98,8 +98,8 @@ private:
class QQmlConnectionsParser : public QQmlCustomParser
{
public:
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
- void applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
+ void applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index ba11271d66..c50273071b 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -8,13 +8,6 @@ HEADERS += \
$$PWD/qqmlconnections_p.h \
$$PWD/qqmlmodelindexvaluetype_p.h
-qtConfig(qml-worker-script) {
- SOURCES += \
- $$PWD/qquickworkerscript.cpp
- HEADERS += \
- $$PWD/qquickworkerscript_p.h
-}
-
qtConfig(qml-animation) {
SOURCES += \
$$PWD/qqmltimer.cpp
diff --git a/src/qmlmodels/configure.json b/src/qmlmodels/configure.json
index 2aa8a50e69..bfe7d538ec 100644
--- a/src/qmlmodels/configure.json
+++ b/src/qmlmodels/configure.json
@@ -6,6 +6,12 @@
],
"features": {
+ "qml-object-model" : {
+ "label": "QML list model",
+ "purpose": "Provides the ObjectModel and Instantiator QML types.",
+ "section": "QML",
+ "output": [ "privateFeature" ]
+ },
"qml-list-model": {
"label": "QML list model",
"purpose": "Provides the ListModel QML type.",
@@ -16,6 +22,13 @@
"label": "QML delegate model",
"purpose": "Provides the DelegateModel QML type.",
"section": "QML",
+ "condition": "features.qml-object-model",
+ "output": [ "privateFeature" ]
+ },
+ "qml-table-model": {
+ "label": "QML table model",
+ "purpose": "Provides the TableModel QML type.",
+ "section": "QML",
"output": [ "privateFeature" ]
}
},
diff --git a/src/qmlmodels/qmlmodels.pro b/src/qmlmodels/qmlmodels.pro
index 84f87f8bb1..7d1d9bdf67 100644
--- a/src/qmlmodels/qmlmodels.pro
+++ b/src/qmlmodels/qmlmodels.pro
@@ -5,30 +5,36 @@ DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FORE
HEADERS += \
$$PWD/qqmlchangeset_p.h \
- $$PWD/qqmlinstantiator_p.h \
- $$PWD/qqmlinstantiator_p_p.h \
- $$PWD/qqmllistaccessor_p.h \
- $$PWD/qqmllistcompositor_p.h \
$$PWD/qqmlmodelsmodule_p.h \
- $$PWD/qqmlobjectmodel_p.h \
- $$PWD/qqmltableinstancemodel_p.h \
- $$PWD/qqmltablemodel_p.h \
- $$PWD/qqmltablemodelcolumn_p.h \
- $$PWD/qquickpackage_p.h \
$$PWD/qtqmlmodelsglobal_p.h \
- $$PWD/qtqmlmodelsglobal.h \
+ $$PWD/qtqmlmodelsglobal.h
SOURCES += \
$$PWD/qqmlchangeset.cpp \
- $$PWD/qqmlinstantiator.cpp \
- $$PWD/qqmllistaccessor.cpp \
- $$PWD/qqmllistcompositor.cpp \
- $$PWD/qqmlmodelsmodule.cpp \
- $$PWD/qqmlobjectmodel.cpp \
- $$PWD/qqmltableinstancemodel.cpp \
- $$PWD/qqmltablemodel.cpp \
- $$PWD/qqmltablemodelcolumn.cpp \
- $$PWD/qquickpackage.cpp
+ $$PWD/qqmlmodelsmodule.cpp
+
+qtConfig(qml-object-model) {
+ SOURCES += \
+ $$PWD/qqmlinstantiator.cpp \
+ $$PWD/qqmlobjectmodel.cpp
+
+ HEADERS += \
+ $$PWD/qqmlinstantiator_p.h \
+ $$PWD/qqmlinstantiator_p_p.h \
+ $$PWD/qqmlobjectmodel_p.h
+}
+
+qtConfig(qml-table-model) {
+ SOURCES += \
+ $$PWD/qqmltableinstancemodel.cpp \
+ $$PWD/qqmltablemodel.cpp \
+ $$PWD/qqmltablemodelcolumn.cpp
+
+ HEADERS += \
+ $$PWD/qqmltableinstancemodel_p.h \
+ $$PWD/qqmltablemodel_p.h \
+ $$PWD/qqmltablemodelcolumn_p.h
+}
qtConfig(qml-list-model) {
SOURCES += \
@@ -45,13 +51,19 @@ qtConfig(qml-delegate-model) {
SOURCES += \
$$PWD/qqmladaptormodel.cpp \
$$PWD/qqmldelegatemodel.cpp \
- $$PWD/qqmldelegatecomponent.cpp
+ $$PWD/qqmldelegatecomponent.cpp \
+ $$PWD/qqmllistaccessor.cpp \
+ $$PWD/qqmllistcompositor.cpp \
+ $$PWD/qquickpackage.cpp
HEADERS += \
$$PWD/qqmladaptormodel_p.h \
$$PWD/qqmldelegatemodel_p.h \
$$PWD/qqmldelegatemodel_p_p.h \
- $$PWD/qqmldelegatecomponent_p.h
+ $$PWD/qqmldelegatecomponent_p.h \
+ $$PWD/qqmllistaccessor_p.h \
+ $$PWD/qqmllistcompositor_p.h \
+ $$PWD/qquickpackage_p.h
}
load(qt_module)
diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp
index f991ae0a69..0bc67e1aad 100644
--- a/src/qmlmodels/qqmladaptormodel.cpp
+++ b/src/qmlmodels/qqmladaptormodel.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-class QQmlAdaptorModelEngineData : public QV8Engine::Deletable
+class QQmlAdaptorModelEngineData : public QV4::ExecutionEngine::Deletable
{
public:
QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4);
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 742c164508..2216e5fb50 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -123,7 +123,7 @@ DEFINE_OBJECT_VTABLE(QV4::DelegateModelGroupFunction);
-class QQmlDelegateModelEngineData : public QV8Engine::Deletable
+class QQmlDelegateModelEngineData : public QV4::ExecutionEngine::Deletable
{
public:
QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4);
diff --git a/src/qmlmodels/qqmlinstantiator_p.h b/src/qmlmodels/qqmlinstantiator_p.h
index 8b00a1e033..87accc304f 100644
--- a/src/qmlmodels/qqmlinstantiator_p.h
+++ b/src/qmlmodels/qqmlinstantiator_p.h
@@ -55,6 +55,8 @@
#include <QtQml/qqmlparserstatus.h>
#include <QtQmlModels/private/qtqmlmodelsglobal_p.h>
+QT_REQUIRE_CONFIG(qml_object_model);
+
QT_BEGIN_NAMESPACE
class QQmlInstantiatorPrivate;
diff --git a/src/qmlmodels/qqmlinstantiator_p_p.h b/src/qmlmodels/qqmlinstantiator_p_p.h
index bf153d8723..33cc2613e5 100644
--- a/src/qmlmodels/qqmlinstantiator_p_p.h
+++ b/src/qmlmodels/qqmlinstantiator_p_p.h
@@ -57,6 +57,8 @@
#include <private/qqmlchangeset_p.h>
#include <private/qqmlobjectmodel_p.h>
+QT_REQUIRE_CONFIG(qml_object_model);
+
QT_BEGIN_NAMESPACE
class Q_QMLMODELS_PRIVATE_EXPORT QQmlInstantiatorPrivate : public QObjectPrivate
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index 5b5bcd8464..c1684d955c 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -314,7 +314,7 @@ QString StringOrTranslation::toString(const QQmlListModel *owner) const
}
if (!owner)
return QString();
- return d.asT2()->valueAsString(owner->m_compilationUnit.data());
+ return owner->m_compilationUnit->bindingValueAsString(d.asT2());
}
QString StringOrTranslation::asString() const
@@ -2676,7 +2676,7 @@ void QQmlListModel::sync()
qmlWarning(this) << "List sync() can only be called from a WorkerScript";
}
-bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
const quint32 targetObjectIndex = binding->value.objectIndex;
@@ -2707,7 +2707,7 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::CompiledData:
return false;
}
} else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
+ QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) {
QByteArray script = scriptStr.toUtf8();
bool ok;
@@ -2722,7 +2722,9 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::CompiledData:
return true;
}
-bool QQmlListModelParser::applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
+bool QQmlListModelParser::applyProperty(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
{
const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex);
@@ -2759,15 +2761,15 @@ bool QQmlListModelParser::applyProperty(const QQmlRefPointer<QV4::CompiledData::
if (binding->isTranslationBinding()) {
value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
} else if (binding->evaluatesToString()) {
- value = binding->valueAsString(compilationUnit.data());
+ value = compilationUnit->bindingValueAsString(binding);
} else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- value = binding->valueAsNumber(compilationUnit->constants);
+ value = compilationUnit->bindingValueAsNumber(binding);
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
value = binding->valueAsBoolean();
} else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
value = QVariant::fromValue(nullptr);
} else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
+ QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
if (definesEmptyList(scriptStr)) {
const ListLayout::Role &role = model->getOrCreateListRole(elementName);
ListModel *emptyModel = new ListModel(role.subLayout, nullptr);
@@ -2802,7 +2804,7 @@ bool QQmlListModelParser::applyProperty(const QQmlRefPointer<QV4::CompiledData::
return roleSet;
}
-void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
listElementTypeName = QString(); // unknown
@@ -2817,7 +2819,7 @@ void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData:
}
}
-void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h
index 4aabd790a5..10d67c1c6f 100644
--- a/src/qmlmodels/qqmllistmodel_p.h
+++ b/src/qmlmodels/qqmllistmodel_p.h
@@ -137,7 +137,7 @@ private:
mutable QQmlListModelWorkerAgent *m_agent;
mutable QV4::ExecutionEngine *m_engine;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
bool m_mainThread;
bool m_primary;
@@ -188,13 +188,13 @@ public:
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
private:
- bool verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
+ bool verifyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
// returns true if a role was set
- bool applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex);
+ bool applyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex);
static bool definesEmptyList(const QString &);
diff --git a/src/qmlmodels/qqmllistmodelworkeragent_p.h b/src/qmlmodels/qqmllistmodelworkeragent_p.h
index f79c0c557a..1ef27cea3f 100644
--- a/src/qmlmodels/qqmllistmodelworkeragent_p.h
+++ b/src/qmlmodels/qqmllistmodelworkeragent_p.h
@@ -57,7 +57,7 @@
#include <QMutex>
#include <QWaitCondition>
-#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
QT_REQUIRE_CONFIG(qml_list_model);
diff --git a/src/qmlmodels/qqmlmodelsmodule.cpp b/src/qmlmodels/qqmlmodelsmodule.cpp
index 989fec9b7d..2db5dd834f 100644
--- a/src/qmlmodels/qqmlmodelsmodule.cpp
+++ b/src/qmlmodels/qqmlmodelsmodule.cpp
@@ -39,19 +39,26 @@
#include "qqmlmodelsmodule_p.h"
#include <private/qtqmlmodelsglobal_p.h>
+
+#if QT_CONFIG(itemmodel)
#include <QtCore/qitemselectionmodel.h>
+#endif
#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
#endif
#if QT_CONFIG(qml_delegate_model)
#include <private/qqmldelegatemodel_p.h>
#include <private/qqmldelegatecomponent_p.h>
+#include <private/qquickpackage_p.h>
#endif
+#if QT_CONFIG(qml_object_model)
#include <private/qqmlobjectmodel_p.h>
+#include <private/qqmlinstantiator_p.h>
+#endif
+#if QT_CONFIG(qml_table_model)
#include <private/qqmltablemodel_p.h>
#include <private/qqmltablemodelcolumn_p.h>
-#include <private/qqmlinstantiator_p.h>
-#include <private/qquickpackage_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -60,8 +67,10 @@ QT_BEGIN_NAMESPACE
void QQmlModelsModule::registerQmlTypes()
{
// Don't add anything here. These are only for backwards compatibility.
+#if QT_CONFIG(qml_object_model)
qmlRegisterType<QQmlInstantiator>("QtQml", 2, 1, "Instantiator"); // Only available in >= 2.1
qmlRegisterType<QQmlInstanceModel>();
+#endif
}
void QQmlModelsModule::registerQuickTypes()
@@ -70,18 +79,20 @@ void QQmlModelsModule::registerQuickTypes()
const char uri[] = "QtQuick";
+#if QT_CONFIG(qml_object_model)
qmlRegisterType<QQmlInstantiator>(uri, 2, 1, "Instantiator");
qmlRegisterType<QQmlInstanceModel>();
+ qmlRegisterType<QQmlObjectModel>(uri, 2, 0, "VisualItemModel");
+#endif
#if QT_CONFIG(qml_list_model)
qmlRegisterType<QQmlListElement>(uri, 2, 0, "ListElement");
qmlRegisterCustomType<QQmlListModel>(uri, 2, 0, "ListModel", new QQmlListModelParser);
#endif
- qmlRegisterType<QQuickPackage>(uri, 2, 0, "Package");
#if QT_CONFIG(qml_delegate_model)
qmlRegisterType<QQmlDelegateModel>(uri, 2, 0, "VisualDataModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 0, "VisualDataGroup");
+ qmlRegisterType<QQuickPackage>(uri, 2, 0, "Package");
#endif
- qmlRegisterType<QQmlObjectModel>(uri, 2, 0, "VisualItemModel");
}
#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -97,15 +108,17 @@ void QQmlModelsModule::defineModule()
#if QT_CONFIG(qml_delegate_model)
qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
+ qmlRegisterType<QQuickPackage>(uri, 2, 14, "Package");
#endif
+#if QT_CONFIG(qml_object_model)
qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
-
- qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
-
- qmlRegisterType<QQuickPackage>(uri, 2, 14, "Package");
qmlRegisterType<QQmlInstantiator>(uri, 2, 14, "Instantiator");
qmlRegisterType<QQmlInstanceModel>();
+#endif
+#if QT_CONFIG(itemmodel)
+ qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
+#endif
}
void QQmlModelsModule::defineLabsModule()
@@ -117,8 +130,10 @@ void QQmlModelsModule::defineLabsModule()
qmlRegisterType<QQmlDelegateChooser>(uri, 1, 0, "DelegateChooser");
qmlRegisterType<QQmlDelegateChoice>(uri, 1, 0, "DelegateChoice");
#endif
+#if QT_CONFIG(qml_table_model)
qmlRegisterType<QQmlTableModel>(uri, 1, 0, "TableModel");
qmlRegisterType<QQmlTableModelColumn>(uri, 1, 0, "TableModelColumn");
+#endif
}
QT_END_NAMESPACE
diff --git a/src/qmlmodels/qqmlobjectmodel_p.h b/src/qmlmodels/qqmlobjectmodel_p.h
index 99bfd86269..78a5615ae2 100644
--- a/src/qmlmodels/qqmlobjectmodel_p.h
+++ b/src/qmlmodels/qqmlobjectmodel_p.h
@@ -56,6 +56,8 @@
#include <QtQml/qqml.h>
#include <QtCore/qobject.h>
+QT_REQUIRE_CONFIG(qml_object_model);
+
QT_BEGIN_NAMESPACE
class QObject;
diff --git a/src/qmlmodels/qqmltableinstancemodel_p.h b/src/qmlmodels/qqmltableinstancemodel_p.h
index 20331df5cc..ce5a37bc98 100644
--- a/src/qmlmodels/qqmltableinstancemodel_p.h
+++ b/src/qmlmodels/qqmltableinstancemodel_p.h
@@ -54,6 +54,8 @@
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
#include <QtQmlModels/private/qqmldelegatemodel_p_p.h>
+QT_REQUIRE_CONFIG(qml_table_model);
+
QT_BEGIN_NAMESPACE
class QQmlTableInstanceModel;
diff --git a/src/qmlmodels/qqmltablemodel_p.h b/src/qmlmodels/qqmltablemodel_p.h
index 114b162e5c..b3c0cc2848 100644
--- a/src/qmlmodels/qqmltablemodel_p.h
+++ b/src/qmlmodels/qqmltablemodel_p.h
@@ -59,6 +59,8 @@
#include <QtQml/QJSValue>
#include <QtQml/QQmlListProperty>
+QT_REQUIRE_CONFIG(qml_table_model);
+
QT_BEGIN_NAMESPACE
class Q_QMLMODELS_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel, public QQmlParserStatus
diff --git a/src/qmlmodels/qqmltablemodelcolumn_p.h b/src/qmlmodels/qqmltablemodelcolumn_p.h
index d125f8bb16..0b6478ce38 100644
--- a/src/qmlmodels/qqmltablemodelcolumn_p.h
+++ b/src/qmlmodels/qqmltablemodelcolumn_p.h
@@ -56,6 +56,8 @@
#include <QtQmlModels/private/qtqmlmodelsglobal_p.h>
#include <QtQml/qjsvalue.h>
+QT_REQUIRE_CONFIG(qml_table_model);
+
QT_BEGIN_NAMESPACE
class Q_QMLMODELS_PRIVATE_EXPORT QQmlTableModelColumn : public QObject
diff --git a/src/qmlmodels/qquickpackage_p.h b/src/qmlmodels/qquickpackage_p.h
index 122c7fcb30..97f7818fee 100644
--- a/src/qmlmodels/qquickpackage_p.h
+++ b/src/qmlmodels/qquickpackage_p.h
@@ -52,6 +52,9 @@
//
#include <qqml.h>
+#include <QtQmlModels/private/qtqmlmodelsglobal_p.h>
+
+QT_REQUIRE_CONFIG(qml_delegate_model);
QT_BEGIN_NAMESPACE
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 9cddf61543..6aff7af0e7 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -70,6 +70,7 @@
#include <QtQml/QQmlFileSelector>
#include <private/qqmlcomponent_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#ifdef QT_QMLTEST_WITH_WIDGETS
#include <QtWidgets/QApplication>
@@ -290,7 +291,8 @@ public:
m_errors += component.errors();
if (component.isReady()) {
- QQmlRefPointer<CompilationUnit> rootCompilationUnit = QQmlComponentPrivate::get(&component)->compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> rootCompilationUnit
+ = QQmlComponentPrivate::get(&component)->compilationUnit;
TestCaseEnumerationResult result = enumerateTestCases(rootCompilationUnit.data());
m_testCases = result.testCases + result.finalizedPartialTestCases();
m_errors += result.errors;
@@ -330,7 +332,8 @@ private:
}
};
- TestCaseEnumerationResult enumerateTestCases(CompilationUnit *compilationUnit, const Object *object = nullptr)
+ TestCaseEnumerationResult enumerateTestCases(QV4::ExecutableCompilationUnit *compilationUnit,
+ const Object *object = nullptr)
{
QQmlType testCaseType;
for (quint32 i = 0, count = compilationUnit->importCount(); i < count; ++i) {
@@ -353,7 +356,9 @@ private:
if (!object) // Start at root of compilation unit if not enumerating a specific child
object = compilationUnit->objectAt(0);
- if (CompilationUnit *superTypeUnit = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)->compilationUnit.data()) {
+ if (QV4::ExecutableCompilationUnit *superTypeUnit
+ = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)
+ ->compilationUnit.data()) {
// We have a non-C++ super type, which could indicate we're a subtype of a TestCase
if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl())
result.isTestCase = true;
diff --git a/src/qmlworkerscript/qmlworkerscript.pro b/src/qmlworkerscript/qmlworkerscript.pro
new file mode 100644
index 0000000000..908caa4ed4
--- /dev/null
+++ b/src/qmlworkerscript/qmlworkerscript.pro
@@ -0,0 +1,20 @@
+TARGET = QtQmlWorkerScript
+QT = core-private qml-private
+
+DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FOREACH
+
+HEADERS += \
+ qqmlworkerscriptmodule_p.h \
+ qquickworkerscript_p.h \
+ qtqmlworkerscriptglobal.h \
+ qtqmlworkerscriptglobal_p.h \
+ qv4serialize_p.h
+
+SOURCES += \
+ qqmlworkerscriptmodule.cpp \
+ qquickworkerscript.cpp \
+ qv4serialize.cpp
+
+include(../3rdparty/masm/masm-defs.pri)
+
+load(qt_module)
diff --git a/src/qmlworkerscript/qqmlworkerscriptmodule.cpp b/src/qmlworkerscript/qqmlworkerscriptmodule.cpp
new file mode 100644
index 0000000000..98e82dbeba
--- /dev/null
+++ b/src/qmlworkerscript/qqmlworkerscriptmodule.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlworkerscriptmodule_p.h"
+#include "qquickworkerscript_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+
+void QQmlWorkerScriptModule::registerQuickTypes()
+{
+ // Don't add anything here. These are only for backwards compatibility.
+ const char uri[] = "QtQuick";
+ qmlRegisterType<QQuickWorkerScript>(uri, 2, 0, "WorkerScript");
+}
+
+#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+
+void QQmlWorkerScriptModule::defineModule()
+{
+ const char uri[] = "QtQml.WorkerScript";
+ qmlRegisterType<QQuickWorkerScript>(uri, 2, 0, "WorkerScript");
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmlworkerscript/qqmlworkerscriptmodule_p.h b/src/qmlworkerscript/qqmlworkerscriptmodule_p.h
new file mode 100644
index 0000000000..a2efb304c1
--- /dev/null
+++ b/src/qmlworkerscript/qqmlworkerscriptmodule_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLWORKERSCRIPTMODULE_P_H
+#define QQMLWORKERSCRIPTMODULE_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/qtqmlworkerscriptglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QMLWORKERSCRIPT_PRIVATE_EXPORT QQmlWorkerScriptModule
+{
+public:
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ static void registerQuickTypes();
+#endif
+ static void defineModule();
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLWORKERSCRIPTMODULE_P_H
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp
index c081c9e7fc..4da1def5f5 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qmlworkerscript/qquickworkerscript.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qtqmlglobal_p.h"
+#include "qtqmlworkerscriptglobal_p.h"
#include "qquickworkerscript_p.h"
#include <private/qqmlengine_p.h>
#include <private/qqmlexpression_p.h>
@@ -57,7 +57,6 @@
#include "qqmlnetworkaccessmanagerfactory.h"
#endif
-#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
#include <private/qv4value_p.h>
@@ -125,6 +124,15 @@ private:
QQmlError m_error;
};
+struct WorkerScript : public QV4::ExecutionEngine {
+ WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent);
+
+ QQuickWorkerScriptEnginePrivate *p = nullptr;
+ QUrl source;
+ QQuickWorkerScript *owner = nullptr;
+ int id = -1;
+};
+
class QQuickWorkerScriptEnginePrivate : public QObject
{
Q_OBJECT
@@ -140,23 +148,6 @@ public:
QMutex m_lock;
QWaitCondition m_wait;
- struct WorkerScript : public QV8Engine {
- WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent);
- ~WorkerScript() override;
-
-#if QT_CONFIG(qml_network)
- QNetworkAccessManager *networkAccessManager() override;
-#endif
-
- QQuickWorkerScriptEnginePrivate *p = nullptr;
- QUrl source;
- QQuickWorkerScript *owner = nullptr;
-#if QT_CONFIG(qml_network)
- QScopedPointer<QNetworkAccessManager> accessManager;
-#endif
- int id = -1;
- };
-
QHash<int, WorkerScript *> workers;
QV4::ReturnedValue getWorker(WorkerScript *);
@@ -185,7 +176,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4
const QV4::Value *, const QV4::Value *argv, int argc)
{
QV4::Scope scope(b);
- WorkerScript *script = static_cast<WorkerScript *>(scope.engine->v8Engine);
+ WorkerScript *script = static_cast<WorkerScript *>(scope.engine);
QV4::ScopedValue v(scope, argc > 0 ? argv[0] : QV4::Value::undefinedValue());
QByteArray data = QV4::Serialize::serialize(v, scope.engine);
@@ -230,21 +221,20 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
if (!script)
return;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
- QV4::Scope scope(v4);
+ QV4::Scope scope(script);
QV4::ScopedString v(scope);
- QV4::ScopedObject worker(scope, v4->globalObject->get((v = v4->newString(QStringLiteral("WorkerScript")))));
+ QV4::ScopedObject worker(scope, script->globalObject->get((v = script->newString(QStringLiteral("WorkerScript")))));
QV4::ScopedFunctionObject onmessage(scope);
if (worker)
- onmessage = worker->get((v = v4->newString(QStringLiteral("onMessage"))));
+ onmessage = worker->get((v = script->newString(QStringLiteral("onMessage"))));
if (!onmessage)
return;
- QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
+ QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, script));
QV4::JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = v4->global();
+ *jsCallData->thisObject = script->global();
jsCallData->args[0] = value;
onmessage->call(jsCallData);
if (scope.hasException()) {
@@ -264,35 +254,33 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
if (!script)
return;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
-
script->source = url;
if (fileName.endsWith(QLatin1String(".mjs"))) {
- auto moduleUnit = v4->loadModule(url);
+ auto moduleUnit = script->loadModule(url);
if (moduleUnit) {
- if (moduleUnit->instantiate(v4))
+ if (moduleUnit->instantiate(script))
moduleUnit->evaluate();
} else {
- v4->throwError(QStringLiteral("Could not load module file"));
+ script->throwError(QStringLiteral("Could not load module file"));
}
} else {
QString error;
- QV4::Scope scope(v4);
+ QV4::Scope scope(script);
QScopedPointer<QV4::Script> program;
- program.reset(QV4::Script::createFromFileOrCache(v4, /*qmlContext*/nullptr, fileName, url, &error));
+ program.reset(QV4::Script::createFromFileOrCache(script, /*qmlContext*/nullptr, fileName, url, &error));
if (program.isNull()) {
if (!error.isEmpty())
qWarning().nospace() << error;
return;
}
- if (!v4->hasException)
+ if (!script->hasException)
program->run();
}
- if (v4->hasException) {
- QQmlError error = v4->catchExceptionAsQmlError();
+ if (script->hasException) {
+ QQmlError error = script->catchExceptionAsQmlError();
reportScriptException(script, error);
}
}
@@ -389,45 +377,22 @@ QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine()
d->deleteLater();
}
-QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
- : QV8Engine(new QV4::ExecutionEngine)
- , p(parent)
+WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
+ : p(parent)
, id(id)
{
- m_v4Engine->v8Engine = this;
-
initQmlGlobalObject();
- QV4::Scope scope(m_v4Engine);
+ QV4::Scope scope(this);
QV4::ScopedObject api(scope, scope.engine->newObject());
- QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1));
+ QV4::ScopedString name(scope, newString(QStringLiteral("sendMessage")));
+ QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(this, name, QQuickWorkerScriptEnginePrivate::method_sendMessage, 1));
api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage);
- m_v4Engine->globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
-}
-
-QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
-{
- delete m_v4Engine;
-}
-
-#if QT_CONFIG(qml_network)
-QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerScript::networkAccessManager()
-{
- if (!accessManager) {
- if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
- accessManager.reset(p->qmlengine->networkAccessManagerFactory()->create(p));
- } else {
- accessManager.reset(new QNetworkAccessManager(p));
- }
- }
- return accessManager.data();
+ globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
}
-#endif
int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
{
- typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript;
WorkerScript *script = new WorkerScript(d->m_nextId++, d);
script->owner = owner;
@@ -441,8 +406,7 @@ int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
void QQuickWorkerScriptEngine::removeWorkerScript(int id)
{
- QQuickWorkerScriptEnginePrivate::WorkerScript* script = d->workers.value(id);
- if (script) {
+ if (WorkerScript *script = d->workers.value(id)) {
script->owner = nullptr;
QCoreApplication::postEvent(d, new WorkerRemoveEvent(id));
}
@@ -618,7 +582,11 @@ QQuickWorkerScriptEngine *QQuickWorkerScript::engine()
return nullptr;
}
- m_engine = QQmlEnginePrivate::get(engine)->getWorkerScriptEngine();
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ if (enginePrivate->workerScriptEngine == nullptr)
+ enginePrivate->workerScriptEngine = new QQuickWorkerScriptEngine(engine);
+ m_engine = qobject_cast<QQuickWorkerScriptEngine *>(enginePrivate->workerScriptEngine);
+ Q_ASSERT(m_engine);
m_scriptId = m_engine->registerWorkerScript(this);
if (m_source.isValid())
diff --git a/src/qml/types/qquickworkerscript_p.h b/src/qmlworkerscript/qquickworkerscript_p.h
index 87cf2e9754..87cf2e9754 100644
--- a/src/qml/types/qquickworkerscript_p.h
+++ b/src/qmlworkerscript/qquickworkerscript_p.h
diff --git a/src/qmlworkerscript/qtqmlworkerscriptglobal.h b/src/qmlworkerscript/qtqmlworkerscriptglobal.h
new file mode 100644
index 0000000000..be3ea4e12a
--- /dev/null
+++ b/src/qmlworkerscript/qtqmlworkerscriptglobal.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQMLWORKERSCRIPTGLOBAL_H
+#define QTQMLWORKERSCRIPTGLOBAL_H
+
+#include <QtQml/qtqmlglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_STATIC)
+# if defined(QT_BUILD_QMLWORKERSCRIPT_LIB)
+# define Q_QMLWORKERSCRIPT_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QMLWORKERSCRIPT_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define Q_QMLWORKERSCRIPT_EXPORT
+#endif
+
+QT_END_NAMESPACE
+#endif // QTQMLWORKERSCRIPTGLOBAL_H
diff --git a/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h b/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h
new file mode 100644
index 0000000000..34236cd79e
--- /dev/null
+++ b/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQMLWORKERSCRIPTGLOBAL_P_H
+#define QTQMLWORKERSCRIPTGLOBAL_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 <QtQml/private/qtqmlglobal_p.h>
+#include <QtQmlWorkerScript/qtqmlworkerscriptglobal.h>
+
+#define Q_QMLWORKERSCRIPT_PRIVATE_EXPORT Q_QMLWORKERSCRIPT_EXPORT
+#define Q_QMLWORKERSCRIPT_AUTOTEST_EXPORT Q_AUTOTEST_EXPORT
+
+#endif // QTQMLWORKERSCRIPTGLOBAL_P_H
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qmlworkerscript/qv4serialize.cpp
index a5e62d3e35..a5e62d3e35 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qmlworkerscript/qv4serialize.cpp
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qmlworkerscript/qv4serialize_p.h
index c8700c3ca5..c8700c3ca5 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qmlworkerscript/qv4serialize_p.h
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 98e7663c96..b87203c3ef 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -382,6 +382,22 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const
return QString();
}
+void QAccessibleQuickItem::setText(QAccessible::Text textType, const QString &text)
+{
+ if (role() != QAccessible::EditableText)
+ return;
+ if (textType != QAccessible::Value)
+ return;
+
+ if (QTextDocument *doc = textDocument()) {
+ doc->setPlainText(text);
+ return;
+ }
+ auto textPropertyName = "text";
+ if (object()->metaObject()->indexOfProperty(textPropertyName) >= 0)
+ object()->setProperty(textPropertyName, text);
+}
+
void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t)
{
QAccessible::Role r = role();
diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h
index 5375d37bf0..931e995f0f 100644
--- a/src/quick/accessible/qaccessiblequickitem_p.h
+++ b/src/quick/accessible/qaccessiblequickitem_p.h
@@ -83,6 +83,7 @@ public:
QAccessible::State state() const override;
QAccessible::Role role() const override;
QString text(QAccessible::Text) const override;
+ void setText(QAccessible::Text, const QString &text) override;
bool isAccessible() const;
diff --git a/src/quick/configure.json b/src/quick/configure.json
index 70fe6d2129..4098db87aa 100644
--- a/src/quick/configure.json
+++ b/src/quick/configure.json
@@ -113,6 +113,7 @@
"label": "TableView item",
"purpose": "Provides the TableView item.",
"section": "Qt Quick",
+ "condition": "features.qml-table-model",
"output": [
"privateFeature"
]
diff --git a/src/quick/designer/qquickdesignercustomparserobject.cpp b/src/quick/designer/qquickdesignercustomparserobject.cpp
index 50a8b6a25b..841aae5bc3 100644
--- a/src/quick/designer/qquickdesignercustomparserobject.cpp
+++ b/src/quick/designer/qquickdesignercustomparserobject.cpp
@@ -46,12 +46,12 @@ QQuickDesignerCustomParserObject::QQuickDesignerCustomParserObject()
}
-void QQuickDesignerCustomParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &)
+void QQuickDesignerCustomParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &)
{
/* Nothing to do we accept anything */
}
-void QQuickDesignerCustomParser::applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &)
+void QQuickDesignerCustomParser::applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &)
{
/* Nothing to do we accept anything */
}
diff --git a/src/quick/designer/qquickdesignercustomparserobject_p.h b/src/quick/designer/qquickdesignercustomparserobject_p.h
index b38417d102..4da00ea841 100644
--- a/src/quick/designer/qquickdesignercustomparserobject_p.h
+++ b/src/quick/designer/qquickdesignercustomparserobject_p.h
@@ -70,8 +70,8 @@ public:
QQuickDesignerCustomParser()
: QQmlCustomParser(AcceptsAttachedProperties | AcceptsSignalHandlers) {}
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
+ void applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
QT_END_NAMESPACE
diff --git a/src/quick/doc/snippets/pointerHandlers/tapHandlerOnTapped.qml b/src/quick/doc/snippets/pointerHandlers/tapHandlerOnTapped.qml
new file mode 100644
index 0000000000..f556c238da
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/tapHandlerOnTapped.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.12
+
+Rectangle {
+ width: 100
+ height: 100
+
+ TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onTapped: console.log("tapped", eventPoint.event.device.name,
+ "button", eventPoint.event.button,
+ "@", eventPoint.scenePosition)
+ }
+}
+//![0]
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 22fe3df4d0..61b66beff4 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -114,8 +114,14 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEvent
QQuickMultiPointHandler::onGrabChanged(grabber, transition, point);
if (grabber == this && transition == QQuickEventPoint::GrabExclusive && target()) {
// In case the grab got handed over from another grabber, we might not get the Press.
- if (!m_pressedInsideTarget) {
- if (target() != parentItem())
+
+ auto isDescendant = [](QQuickItem *parent, QQuickItem *target) {
+ return (target != parent) && !target->isAncestorOf(parent);
+ };
+ if (m_snapMode == SnapAlways
+ || (m_snapMode == SnapIfPressedOutsideTarget && !m_pressedInsideTarget)
+ || (m_snapMode == SnapAuto && !m_pressedInsideTarget && isDescendant(parentItem(), target()))
+ ) {
m_pressTargetPos = QPointF(target()->width(), target()->height()) / 2;
} else if (m_pressTargetPos.isNull()) {
m_pressTargetPos = targetCentroidPosition();
@@ -123,6 +129,33 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEvent
}
}
+/*!
+ \qmlproperty enumeration QtQuick.DragHandler::snapMode
+
+ This property holds the snap mode.
+
+ The snap mode configures snapping of the \l target item's center to the event point.
+
+ Possible values:
+ \value DragHandler.SnapNever Never snap
+ \value DragHandler.SnapAuto The \l target snaps if the event point was pressed outside of the \l target
+ item \e and the \l target is a descendant of \l parentItem (default)
+ \value DragHandler.SnapWhenPressedOutsideTarget The \l target snaps if the event point was pressed outside of the \l target
+ \value DragHandler.SnapAlways Always snap
+*/
+QQuickDragHandler::SnapMode QQuickDragHandler::snapMode() const
+{
+ return m_snapMode;
+}
+
+void QQuickDragHandler::setSnapMode(QQuickDragHandler::SnapMode mode)
+{
+ if (mode == m_snapMode)
+ return;
+ m_snapMode = mode;
+ emit snapModeChanged();
+}
+
void QQuickDragHandler::onActiveChanged()
{
QQuickMultiPointHandler::onActiveChanged();
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index 748026488a..18c1fd841d 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -62,8 +62,17 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragHandler : public QQuickMultiPointHandler
Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT)
Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT)
Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged)
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
public:
+ enum SnapMode {
+ NoSnap = 0,
+ SnapAuto,
+ SnapIfPressedOutsideTarget,
+ SnapAlways
+ };
+ Q_ENUM(SnapMode)
+
explicit QQuickDragHandler(QQuickItem *parent = nullptr);
void handlePointerEventImpl(QQuickPointerEvent *event) override;
@@ -73,11 +82,14 @@ public:
QVector2D translation() const { return m_translation; }
void setTranslation(const QVector2D &trans);
+ QQuickDragHandler::SnapMode snapMode() const;
+ void setSnapMode(QQuickDragHandler::SnapMode mode);
void enforceConstraints();
Q_SIGNALS:
void translationChanged();
+ void snapModeChanged();
protected:
void onActiveChanged() override;
@@ -97,6 +109,7 @@ private:
QQuickDragAxis m_xAxis;
QQuickDragAxis m_yAxis;
+ QQuickDragHandler::SnapMode m_snapMode = SnapAuto;
bool m_pressedInsideTarget = false;
friend class QQuickDragAxis;
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 081645da71..40a4813527 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -381,35 +381,50 @@ void QQuickTapHandler::updateTimeHeld()
*/
/*!
- \qmlsignal QtQuick::TapHandler::tapped
+ \qmlsignal QtQuick::TapHandler::tapped(EventPoint eventPoint)
This signal is emitted each time the \c parent Item is tapped.
That is, if you press and release a touchpoint or button within a time
period less than \l longPressThreshold, while any movement does not exceed
the drag threshold, then the \c tapped signal will be emitted at the time
- of release.
+ of release. The \c eventPoint signal parameter contains information
+ from the release event about the point that was tapped:
+
+ \snippet pointerHandlers/tapHandlerOnTapped.qml 0
+
+ \note At the time this signal is emitted, \l point has been reset
+ (all coordinates are \c 0).
*/
/*!
- \qmlsignal QtQuick::TapHandler::singleTapped
+ \qmlsignal QtQuick::TapHandler::singleTapped(EventPoint eventPoint)
\since 5.11
This signal is emitted when the \c parent Item is tapped once.
After an amount of time greater than QStyleHints::mouseDoubleClickInterval,
it can be tapped again; but if the time until the next tap is less,
- \l tapCount will increase.
+ \l tapCount will increase. The \c eventPoint signal parameter contains
+ information from the release event about the point that was tapped.
+
+ \note At the time this signal is emitted, \l point has been reset
+ (all coordinates are \c 0).
*/
/*!
- \qmlsignal QtQuick::TapHandler::doubleTapped
+ \qmlsignal QtQuick::TapHandler::doubleTapped(EventPoint eventPoint)
\since 5.11
This signal is emitted when the \c parent Item is tapped twice within a
short span of time (QStyleHints::mouseDoubleClickInterval) and distance
(QPlatformTheme::MouseDoubleClickDistance or
QPlatformTheme::TouchDoubleTapDistance). This signal always occurs after
- \l singleTapped, \l tapped, and \l tapCountChanged.
+ \l singleTapped, \l tapped, and \l tapCountChanged. The \c eventPoint
+ signal parameter contains information from the release event about the
+ point that was tapped.
+
+ \note At the time this signal is emitted, \l point has been reset
+ (all coordinates are \c 0).
*/
/*!
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 58bc12a221..0f104a122f 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -473,7 +473,7 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
return newFont;
}
-class QQuickContext2DEngineData : public QV8Engine::Deletable
+class QQuickContext2DEngineData : public QV4::ExecutionEngine::Deletable
{
public:
QQuickContext2DEngineData(QV4::ExecutionEngine *engine);
@@ -2000,7 +2000,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(const QV4::FunctionO
\since QtQuick 2.11
Returns an array of qreals representing the dash pattern of the line.
- \sa setLineDash()
+ \sa setLineDash(), lineDashOffset
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
{
@@ -2022,7 +2022,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::Fun
/*!
\qmlmethod QtQuick::Context2D::setLineDash(array pattern)
\since QtQuick 2.11
- Sets the dash pattern to the given pattern
+ Sets the dash pattern to the given pattern.
\a pattern a list of numbers that specifies distances to alternately draw a line and a gap.
@@ -2041,7 +2041,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::Fun
\endcode
\endtable
- \sa setLineDash
+ \sa getLineDash(), lineDashOffset
*/
QV4::ReturnedValue QQuickJSContext2DPrototype::method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
{
@@ -2083,8 +2083,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setLineDash(const QV4::Fun
\qmlproperty real QtQuick::Context2D::lineDashOffset
\since QtQuick 2.11
- Holds the current line dash offset
- The default line dash ofset value is 0
+ Holds the current line dash offset.
+ The default line dash offset value is \c 0.
+
+ \sa getLineDash(), setLineDash()
*/
QV4::ReturnedValue QQuickJSContext2D::method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
{
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index 0168c3160c..c150e4efa2 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -390,6 +390,49 @@ QQuickAccessibleAttached::~QQuickAccessibleAttached()
{
}
+void QQuickAccessibleAttached::setRole(QAccessible::Role role)
+{
+ if (role != m_role) {
+ m_role = role;
+ Q_EMIT roleChanged();
+ // There is no way to signify role changes at the moment.
+ // QAccessible::updateAccessibility(parent(), 0, QAccessible::);
+
+ switch (role) {
+ case QAccessible::CheckBox:
+ case QAccessible::RadioButton:
+ if (!m_stateExplicitlySet.focusable)
+ m_state.focusable = true;
+ if (!m_stateExplicitlySet.checkable)
+ m_state.checkable = true;
+ break;
+ case QAccessible::Button:
+ case QAccessible::MenuItem:
+ case QAccessible::PageTab:
+ case QAccessible::SpinBox:
+ case QAccessible::ComboBox:
+ case QAccessible::Terminal:
+ case QAccessible::ScrollBar:
+ if (!m_stateExplicitlySet.focusable)
+ m_state.focusable = true;
+ break;
+ case QAccessible::EditableText:
+ if (!m_stateExplicitlySet.editable)
+ m_state.editable = true;
+ if (!m_stateExplicitlySet.focusable)
+ m_state.focusable = true;
+ break;
+ case QAccessible::StaticText:
+ if (!m_stateExplicitlySet.readOnly) {
+ m_state.readOnly = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
QQuickAccessibleAttached *QQuickAccessibleAttached::qmlAttachedProperties(QObject *obj)
{
return new QQuickAccessibleAttached(obj);
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index 215a1e5db6..f4194ef13d 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -69,6 +69,7 @@ QT_BEGIN_NAMESPACE
bool P() const { return m_state.P ; } \
void set_ ## P(bool arg) \
{ \
+ m_stateExplicitlySet.P = true; \
if (m_state.P == arg) \
return; \
m_state.P = arg; \
@@ -111,35 +112,7 @@ public:
~QQuickAccessibleAttached();
QAccessible::Role role() const { return m_role; }
- void setRole(QAccessible::Role role)
- {
- if (role != m_role) {
- m_role = role;
- Q_EMIT roleChanged();
- // There is no way to signify role changes at the moment.
- // QAccessible::updateAccessibility(parent(), 0, QAccessible::);
-
- switch (role) {
- case QAccessible::CheckBox:
- case QAccessible::RadioButton:
- m_state.focusable = true;
- m_state.checkable = true;
- break;
- case QAccessible::Button:
- case QAccessible::MenuItem:
- case QAccessible::PageTab:
- case QAccessible::EditableText:
- case QAccessible::SpinBox:
- case QAccessible::ComboBox:
- case QAccessible::Terminal:
- case QAccessible::ScrollBar:
- m_state.focusable = true;
- break;
- default:
- break;
- }
- }
- }
+ void setRole(QAccessible::Role role);
QString name() const {
if (m_state.passwordEdit)
return QString();
@@ -241,6 +214,7 @@ private:
QAccessible::Role m_role;
QAccessible::State m_state;
+ QAccessible::State m_stateExplicitlySet;
QString m_name;
QString m_description;
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index bc1f787b81..0cbabaa170 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -221,7 +221,7 @@ QQuickOpenGLShaderEffectCommon::~QQuickOpenGLShaderEffectCommon()
clearSignalMappers(shaderType);
}
-void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType)
+void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QObject *obj, Key::ShaderType shaderType)
{
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
if (signalMappers[shaderType].at(i) == 0)
@@ -229,12 +229,11 @@ void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item,
const UniformData &d = uniformData[shaderType].at(i);
auto mapper = signalMappers[shaderType].at(i);
void *a = mapper;
- QObjectPrivate::disconnect(item, mapper->signalIndex(), &a);
+ QObjectPrivate::disconnect(obj, mapper->signalIndex(), &a);
if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
if (source) {
- if (item->window())
- QQuickItemPrivate::get(source)->derefWindow();
+ QQuickItemPrivate::get(source)->derefWindow();
QObject::disconnect(source, SIGNAL(destroyed(QObject*)), host, SLOT(sourceDestroyed(QObject*)));
}
}
diff --git a/src/quick/items/qquickopenglshadereffect_p.h b/src/quick/items/qquickopenglshadereffect_p.h
index 0c2adadc62..3087c1eb0b 100644
--- a/src/quick/items/qquickopenglshadereffect_p.h
+++ b/src/quick/items/qquickopenglshadereffect_p.h
@@ -89,7 +89,7 @@ struct Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectCommon
~QQuickOpenGLShaderEffectCommon();
- void disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType);
+ void disconnectPropertySignals(QObject *item, Key::ShaderType shaderType);
void connectPropertySignals(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType);
void updateParseLog(bool ignoreAttributes);
void lookThroughShaderCode(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType, const QByteArray &code);
diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp
index f32b32491b..f96ebebcd6 100644
--- a/src/quick/items/qquickopenglshadereffectnode.cpp
+++ b/src/quick/items/qquickopenglshadereffectnode.cpp
@@ -477,11 +477,11 @@ void QQuickOpenGLShaderEffectMaterial::updateTextures() const
}
}
-void QQuickOpenGLShaderEffectMaterial::invalidateTextureProvider(QSGTextureProvider *provider)
+void QQuickOpenGLShaderEffectMaterial::invalidateTextureProvider(const QObject *provider)
{
for (int i = 0; i < textureProviders.size(); ++i) {
if (provider == textureProviders.at(i))
- textureProviders[i] = 0;
+ textureProviders[i] = nullptr;
}
}
@@ -505,10 +505,10 @@ void QQuickOpenGLShaderEffectNode::markDirtyTexture()
Q_EMIT dirtyTexture();
}
-void QQuickOpenGLShaderEffectNode::textureProviderDestroyed(QObject *object)
+void QQuickOpenGLShaderEffectNode::textureProviderDestroyed(const QObject *object)
{
Q_ASSERT(material());
- static_cast<QQuickOpenGLShaderEffectMaterial *>(material())->invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
+ static_cast<QQuickOpenGLShaderEffectMaterial *>(material())->invalidateTextureProvider(object);
}
void QQuickOpenGLShaderEffectNode::preprocess()
diff --git a/src/quick/items/qquickopenglshadereffectnode_p.h b/src/quick/items/qquickopenglshadereffectnode_p.h
index 7c75bb3126..6d68ba87b9 100644
--- a/src/quick/items/qquickopenglshadereffectnode_p.h
+++ b/src/quick/items/qquickopenglshadereffectnode_p.h
@@ -122,7 +122,7 @@ public:
void setProgramSource(const QQuickOpenGLShaderEffectMaterialKey &source);
void updateTextures() const;
- void invalidateTextureProvider(QSGTextureProvider *provider);
+ void invalidateTextureProvider(const QObject *provider);
static void cleanupMaterialCache();
@@ -159,7 +159,7 @@ Q_SIGNALS:
private Q_SLOTS:
void markDirtyTexture();
- void textureProviderDestroyed(QObject *object);
+ void textureProviderDestroyed(const QObject *object);
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index ab79b69c8c..05d9e5e36d 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -795,7 +795,8 @@ bool QQuickShaderEffect::event(QEvent *e)
return QQuickItem::event(e);
}
#endif
- m_impl->handleEvent(e);
+ if (m_impl)
+ m_impl->handleEvent(e);
return QQuickItem::event(e);
}
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 8f5130fc17..9583ef4231 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -305,9 +305,7 @@
\l view, which means that the table's width could be larger or smaller than
the viewport width. As a TableView cannot always know the exact width of
the table without loading all columns in the model, the \c contentWidth is
- usually an estimate based on the columns it has seen so far. This estimate
- is recalculated whenever new columns are flicked into view, which means
- that the content width can change dynamically.
+ usually an estimate based on the initially loaded table.
If you know what the width of the table will be, assign a value to
\c contentWidth, to avoid unnecessary calculations and updates to the
@@ -324,9 +322,7 @@
\c view, which means that the table's height could be larger or smaller than the
viewport height. As a TableView cannot always know the exact height of the
table without loading all rows in the model, the \c contentHeight is
- usually an estimate based on the rows it has seen so far. This estimate is
- recalculated whenever new rows are flicked into view, which means that
- the content height can change dynamically.
+ usually an estimate based on the initially loaded table.
If you know what the height of the table will be, assign a
value to \c contentHeight, to avoid unnecessary calculations and updates to
@@ -616,6 +612,7 @@ void QQuickTableViewPrivate::updateContentWidth()
Q_Q(QQuickTableView);
if (syncHorizontally) {
+ QBoolBlocker fixupGuard(inUpdateContentSize, true);
q->QQuickFlickable::setContentWidth(syncView->contentWidth());
return;
}
@@ -632,6 +629,8 @@ void QQuickTableViewPrivate::updateContentWidth()
const qreal remainingSpacing = columnsRemaining * cellSpacing.width();
const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing;
const qreal estimatedWidth = loadedTableOuterRect.right() + estimatedRemainingWidth;
+
+ QBoolBlocker fixupGuard(inUpdateContentSize, true);
q->QQuickFlickable::setContentWidth(estimatedWidth);
}
@@ -640,6 +639,7 @@ void QQuickTableViewPrivate::updateContentHeight()
Q_Q(QQuickTableView);
if (syncVertically) {
+ QBoolBlocker fixupGuard(inUpdateContentSize, true);
q->QQuickFlickable::setContentHeight(syncView->contentHeight());
return;
}
@@ -656,64 +656,204 @@ void QQuickTableViewPrivate::updateContentHeight()
const qreal remainingSpacing = rowsRemaining * cellSpacing.height();
const qreal estimatedRemainingHeight = remainingRowHeights + remainingSpacing;
const qreal estimatedHeight = loadedTableOuterRect.bottom() + estimatedRemainingHeight;
+
+ QBoolBlocker fixupGuard(inUpdateContentSize, true);
q->QQuickFlickable::setContentHeight(estimatedHeight);
}
-void QQuickTableViewPrivate::enforceTableAtOrigin()
+void QQuickTableViewPrivate::updateExtents()
{
- // Gaps before the first row/column can happen if rows/columns
- // changes size while flicking e.g because of spacing changes or
- // changes to a column maxWidth/row maxHeight. Check for this, and
- // move the whole table rect accordingly.
- bool layoutNeeded = false;
- const qreal flickMargin = 50;
+ // When rows or columns outside the viewport are removed or added, or a rebuild
+ // forces us to guesstimate a new top-left, the edges of the table might end up
+ // out of sync with the edges of the content view. We detect this situation here, and
+ // move the origin to ensure that there will never be gaps at the end of the table.
+ // Normally we detect that the size of the whole table is not going to be equal to the
+ // size of the content view already when we load the last row/column, and especially
+ // before it's flicked completely inside the viewport. For those cases we simply adjust
+ // the origin/endExtent, to give a smooth flicking experience.
+ // But if flicking fast (e.g with a scrollbar), it can happen that the viewport ends up
+ // outside the end of the table in just one viewport update. To avoid a "blink" in the
+ // viewport when that happens, we "move" the loaded table into the viewport to cover it.
+ Q_Q(QQuickTableView);
- const bool noMoreColumns = nextVisibleEdgeIndexAroundLoadedTable(Qt::LeftEdge) == kEdgeIndexAtEnd;
- const bool noMoreRows = nextVisibleEdgeIndexAroundLoadedTable(Qt::TopEdge) == kEdgeIndexAtEnd;
+ bool tableMovedHorizontally = false;
+ bool tableMovedVertically = false;
- if (noMoreColumns) {
- if (!qFuzzyIsNull(loadedTableOuterRect.left())) {
- // There are no more columns, but the table rect
- // is not at origin. So we move it there.
- loadedTableOuterRect.moveLeft(0);
- layoutNeeded = true;
+ const int nextLeftColumn = nextVisibleEdgeIndexAroundLoadedTable(Qt::LeftEdge);
+ const int nextRightColumn = nextVisibleEdgeIndexAroundLoadedTable(Qt::RightEdge);
+ const int nextTopRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::TopEdge);
+ const int nextBottomRow = nextVisibleEdgeIndexAroundLoadedTable(Qt::BottomEdge);
+
+ if (syncHorizontally) {
+ const auto syncView_d = syncView->d_func();
+ origin.rx() = syncView_d->origin.x();
+ endExtent.rwidth() = syncView_d->endExtent.width();
+ hData.markExtentsDirty();
+ } else if (nextLeftColumn == kEdgeIndexAtEnd) {
+ // There are no more columns to load on the left side of the table.
+ // In that case, we ensure that the origin match the beginning of the table.
+ if (loadedTableOuterRect.left() > viewportRect.left()) {
+ // We have a blank area at the left end of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing origin), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ if (loadedTableOuterRect.left() > origin.x()) {
+ const qreal diff = loadedTableOuterRect.left() - origin.x();
+ loadedTableOuterRect.moveLeft(loadedTableOuterRect.left() - diff);
+ loadedTableInnerRect.moveLeft(loadedTableInnerRect.left() - diff);
+ tableMovedHorizontally = true;
+ }
}
- } else {
- if (loadedTableOuterRect.left() <= 0) {
- // The table rect is at origin, or outside. But we still have
- // more visible columns to the left. So we need to make some
- // space so that they can be flicked in.
- loadedTableOuterRect.moveLeft(flickMargin);
- layoutNeeded = true;
+ origin.rx() = loadedTableOuterRect.left();
+ hData.markExtentsDirty();
+ } else if (loadedTableOuterRect.left() <= origin.x() + cellSpacing.width()) {
+ // The table rect is at the origin, or outside, but we still have more
+ // visible columns to the left. So we try to guesstimate how much space
+ // the rest of the columns will occupy, and move the origin accordingly.
+ const int columnsRemaining = nextLeftColumn + 1;
+ const qreal remainingColumnWidths = columnsRemaining * averageEdgeSize.width();
+ const qreal remainingSpacing = columnsRemaining * cellSpacing.width();
+ const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing;
+ origin.rx() = loadedTableOuterRect.left() - estimatedRemainingWidth;
+ hData.markExtentsDirty();
+ } else if (nextRightColumn == kEdgeIndexAtEnd) {
+ // There are no more columns to load on the right side of the table.
+ // In that case, we ensure that the end of the content view match the end of the table.
+ if (loadedTableOuterRect.right() < viewportRect.right()) {
+ // We have a blank area at the right end of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing endExtent), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ const qreal w = qMin(viewportRect.right(), q->contentWidth() + endExtent.width());
+ if (loadedTableOuterRect.right() < w) {
+ const qreal diff = loadedTableOuterRect.right() - w;
+ loadedTableOuterRect.moveRight(loadedTableOuterRect.right() - diff);
+ loadedTableInnerRect.moveRight(loadedTableInnerRect.right() - diff);
+ tableMovedHorizontally = true;
+ }
}
+ endExtent.rwidth() = loadedTableOuterRect.right() - q->contentWidth();
+ hData.markExtentsDirty();
+ } else if (loadedTableOuterRect.right() >= q->contentWidth() + endExtent.width() - cellSpacing.width()) {
+ // The right-most column is outside the end of the content view, and we
+ // still have more visible columns in the model. This can happen if the application
+ // has set a fixed content width.
+ const int columnsRemaining = tableSize.width() - nextRightColumn;
+ const qreal remainingColumnWidths = columnsRemaining * averageEdgeSize.width();
+ const qreal remainingSpacing = columnsRemaining * cellSpacing.width();
+ const qreal estimatedRemainingWidth = remainingColumnWidths + remainingSpacing;
+ const qreal pixelsOutsideContentWidth = loadedTableOuterRect.right() - q->contentWidth();
+ endExtent.rwidth() = pixelsOutsideContentWidth + estimatedRemainingWidth;
+ hData.markExtentsDirty();
}
- if (noMoreRows) {
- if (!qFuzzyIsNull(loadedTableOuterRect.top())) {
- loadedTableOuterRect.moveTop(0);
- layoutNeeded = true;
+ if (syncVertically) {
+ const auto syncView_d = syncView->d_func();
+ origin.ry() = syncView_d->origin.y();
+ endExtent.rheight() = syncView_d->endExtent.height();
+ vData.markExtentsDirty();
+ } else if (nextTopRow == kEdgeIndexAtEnd) {
+ // There are no more rows to load on the top side of the table.
+ // In that case, we ensure that the origin match the beginning of the table.
+ if (loadedTableOuterRect.top() > viewportRect.top()) {
+ // We have a blank area at the top of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing origin), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ if (loadedTableOuterRect.top() > origin.y()) {
+ const qreal diff = loadedTableOuterRect.top() - origin.y();
+ loadedTableOuterRect.moveTop(loadedTableOuterRect.top() - diff);
+ loadedTableInnerRect.moveTop(loadedTableInnerRect.top() - diff);
+ tableMovedVertically = true;
+ }
}
- } else {
- if (loadedTableOuterRect.top() <= 0) {
- loadedTableOuterRect.moveTop(flickMargin);
- layoutNeeded = true;
+ origin.ry() = loadedTableOuterRect.top();
+ vData.markExtentsDirty();
+ } else if (loadedTableOuterRect.top() <= origin.y() + cellSpacing.height()) {
+ // The table rect is at the origin, or outside, but we still have more
+ // visible rows at the top. So we try to guesstimate how much space
+ // the rest of the rows will occupy, and move the origin accordingly.
+ const int rowsRemaining = nextTopRow + 1;
+ const qreal remainingRowHeights = rowsRemaining * averageEdgeSize.height();
+ const qreal remainingSpacing = rowsRemaining * cellSpacing.height();
+ const qreal estimatedRemainingHeight = remainingRowHeights + remainingSpacing;
+ origin.ry() = loadedTableOuterRect.top() - estimatedRemainingHeight;
+ vData.markExtentsDirty();
+ } else if (nextBottomRow == kEdgeIndexAtEnd) {
+ // There are no more rows to load on the bottom side of the table.
+ // In that case, we ensure that the end of the content view match the end of the table.
+ if (loadedTableOuterRect.bottom() < viewportRect.bottom()) {
+ // We have a blank area at the bottom of the viewport. In that case we don't have time to
+ // wait for the viewport to move (after changing endExtent), since that will take an extra
+ // update cycle, which will be visible as a blink. Instead, unless the blank spot is just
+ // us overshooting, we brute force the loaded table inside the already existing viewport.
+ const qreal h = qMin(viewportRect.bottom(), q->contentHeight() + endExtent.height());
+ if (loadedTableOuterRect.bottom() < h) {
+ const qreal diff = loadedTableOuterRect.bottom() - h;
+ loadedTableOuterRect.moveBottom(loadedTableOuterRect.bottom() - diff);
+ loadedTableInnerRect.moveBottom(loadedTableInnerRect.bottom() - diff);
+ tableMovedVertically = true;
+ }
+ }
+ endExtent.rheight() = loadedTableOuterRect.bottom() - q->contentHeight();
+ vData.markExtentsDirty();
+ } else if (loadedTableOuterRect.bottom() >= q->contentHeight() + endExtent.height() - cellSpacing.height()) {
+ // The bottom-most row is outside the end of the content view, and we
+ // still have more visible rows in the model. This can happen if the application
+ // has set a fixed content height.
+ const int rowsRemaining = tableSize.height() - nextBottomRow;
+ const qreal remainingRowHeigts = rowsRemaining * averageEdgeSize.height();
+ const qreal remainingSpacing = rowsRemaining * cellSpacing.height();
+ const qreal estimatedRemainingHeight = remainingRowHeigts + remainingSpacing;
+ const qreal pixelsOutsideContentHeight = loadedTableOuterRect.bottom() - q->contentHeight();
+ endExtent.rheight() = pixelsOutsideContentHeight + estimatedRemainingHeight;
+ vData.markExtentsDirty();
+ }
+
+ if (tableMovedHorizontally || tableMovedVertically) {
+ qCDebug(lcTableViewDelegateLifecycle) << "move table to" << loadedTableOuterRect;
+
+ // relayoutTableItems() will take care of moving the existing
+ // delegate items into the new loadedTableOuterRect.
+ relayoutTableItems();
+
+ // Inform the sync children that they need to rebuild to stay in sync
+ for (auto syncChild : qAsConst(syncChildren)) {
+ auto syncChild_d = syncChild->d_func();
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::ViewportOnly;
+ if (tableMovedHorizontally)
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::CalculateNewTopLeftColumn;
+ if (tableMovedVertically)
+ syncChild_d->scheduledRebuildOptions |= RebuildOption::CalculateNewTopLeftRow;
}
}
- if (layoutNeeded) {
- qCDebug(lcTableViewDelegateLifecycle);
- relayoutTableItems();
+ if (hData.minExtentDirty || vData.minExtentDirty) {
+ qCDebug(lcTableViewDelegateLifecycle) << "move origin and endExtent to:" << origin << endExtent;
+ // updateBeginningEnd() will let the new extents take effect. This will also change the
+ // visualArea of the flickable, which again will cause any attached scrollbars to adjust
+ // the position of the handle. Note the latter will cause the viewport to move once more.
+ updateBeginningEnd();
}
}
void QQuickTableViewPrivate::updateAverageEdgeSize()
{
- const int loadedRowCount = loadedRows.count();
- const int loadedColumnCount = loadedColumns.count();
- const qreal accRowSpacing = (loadedRowCount - 1) * cellSpacing.height();
- const qreal accColumnSpacing = (loadedColumnCount - 1) * cellSpacing.width();
- averageEdgeSize.setHeight((loadedTableOuterRect.height() - accRowSpacing) / loadedRowCount);
- averageEdgeSize.setWidth((loadedTableOuterRect.width() - accColumnSpacing) / loadedColumnCount);
+ if (explicitContentWidth.isValid()) {
+ const qreal accColumnSpacing = (tableSize.width() - 1) * cellSpacing.width();
+ averageEdgeSize.setWidth((explicitContentWidth - accColumnSpacing) / tableSize.width());
+ } else {
+ const qreal accColumnSpacing = (loadedColumns.count() - 1) * cellSpacing.width();
+ averageEdgeSize.setWidth((loadedTableOuterRect.width() - accColumnSpacing) / loadedColumns.count());
+ }
+
+ if (explicitContentHeight.isValid()) {
+ const qreal accRowSpacing = (tableSize.height() - 1) * cellSpacing.height();
+ averageEdgeSize.setHeight((explicitContentHeight - accRowSpacing) / tableSize.height());
+ } else {
+ const qreal accRowSpacing = (loadedRows.count() - 1) * cellSpacing.height();
+ averageEdgeSize.setHeight((loadedTableOuterRect.height() - accRowSpacing) / loadedRows.count());
+ }
}
void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable()
@@ -770,13 +910,12 @@ void QQuickTableViewPrivate::forceLayout()
scheduleRebuildTable(rebuildOptions);
- if (polishing) {
+ auto rootView = rootSyncView();
+ const bool updated = rootView->d_func()->updateTableRecursive();
+ if (!updated) {
qWarning() << "TableView::forceLayout(): Cannot do an immediate re-layout during an ongoing layout!";
- q_func()->polish();
- return;
+ rootView->polish();
}
-
- updatePolish();
}
void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest()
@@ -1212,19 +1351,6 @@ bool QQuickTableViewPrivate::isRowHidden(int row)
return qFuzzyIsNull(getRowHeight(row));
}
-void QQuickTableViewPrivate::relayoutTable()
-{
- clearEdgeSizeCache();
- relayoutTableItems();
- syncLoadedTableRectFromLoadedTable();
- enforceTableAtOrigin();
- updateContentWidth();
- updateContentHeight();
- // Return back to updatePolish to loadAndUnloadVisibleEdges()
- // since the re-layout might have caused some edges to be pushed
- // out, while others might have been pushed in.
-}
-
void QQuickTableViewPrivate::relayoutTableItems()
{
qCDebug(lcTableViewDelegateLifecycle);
@@ -1409,20 +1535,7 @@ void QQuickTableViewPrivate::processLoadRequest()
if (rebuildState == RebuildState::Done) {
// Loading of this edge was not done as a part of a rebuild, but
// instead as an incremental build after e.g a flick.
- switch (loadRequest.edge()) {
- case Qt::LeftEdge:
- case Qt::TopEdge:
- enforceTableAtOrigin();
- break;
- case Qt::RightEdge:
- updateAverageEdgeSize();
- updateContentWidth();
- break;
- case Qt::BottomEdge:
- updateAverageEdgeSize();
- updateContentHeight();
- break;
- }
+ updateExtents();
drainReusePoolAfterLoadRequest();
}
@@ -1637,16 +1750,29 @@ void QQuickTableViewPrivate::beginRebuildTable()
else if (rebuildOptions & RebuildOption::ViewportOnly)
releaseLoadedItems(reusableFlag);
+ if (rebuildOptions & RebuildOption::All) {
+ origin = QPointF(0, 0);
+ endExtent = QSizeF(0, 0);
+ hData.markExtentsDirty();
+ vData.markExtentsDirty();
+ updateBeginningEnd();
+ }
+
loadedColumns.clear();
loadedRows.clear();
loadedTableOuterRect = QRect();
loadedTableInnerRect = QRect();
clearEdgeSizeCache();
- if (syncHorizontally)
+ if (syncHorizontally) {
setLocalViewportX(syncView->contentX());
- if (syncVertically)
+ viewportRect.moveLeft(syncView->d_func()->viewportRect.left());
+ }
+
+ if (syncVertically) {
setLocalViewportY(syncView->contentY());
+ viewportRect.moveTop(syncView->d_func()->viewportRect.top());
+ }
if (!model) {
qCDebug(lcTableViewDelegateLifecycle()) << "no model found, leaving table empty";
@@ -1690,12 +1816,29 @@ void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
// columns, since during the process, we didn't have all the items
// available yet for the calculation. So we do it now. The exception
// is if we specifically only requested a relayout.
- relayoutTable();
+ clearEdgeSizeCache();
+ relayoutTableItems();
+ syncLoadedTableRectFromLoadedTable();
+ }
+
+ if (syncView || rebuildOptions.testFlag(RebuildOption::All)) {
+ // We try to limit how often we update the content size. The main reason is that is has a
+ // tendency to cause flicker in the viewport if it happens while flicking. But another just
+ // as valid reason is that we actually never really know what the size of the full table will
+ // ever be. Even if e.g spacing changes, and we normally would assume that the size of the table
+ // would increase accordingly, the model might also at some point have removed/hidden/resized
+ // rows/columns outside the viewport. This would also affect the size, but since we don't load
+ // rows or columns outside the viewport, this information is ignored. And even if we did, we
+ // might also have been fast-flicked to a new location at some point, and started a new rebuild
+ // there based on a new guesstimated top-left cell. Either way, changing the content size
+ // based on the currently visible row/columns/spacing can be really off. So instead of pretending
+ // that we know what the actual size of the table is, we just keep the first guesstimate.
+ updateAverageEdgeSize();
+ updateContentWidth();
+ updateContentHeight();
}
- updateAverageEdgeSize();
- updateContentWidth();
- updateContentHeight();
+ updateExtents();
}
void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
@@ -1710,8 +1853,6 @@ void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
unloadItem(QPoint(column, r.key()));
loadedColumns.remove(column);
syncLoadedTableRectFromLoadedTable();
- updateAverageEdgeSize();
- updateContentWidth();
break; }
case Qt::TopEdge:
case Qt::BottomEdge: {
@@ -1720,8 +1861,6 @@ void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
unloadItem(QPoint(c.key(), row));
loadedRows.remove(row);
syncLoadedTableRectFromLoadedTable();
- updateAverageEdgeSize();
- updateContentHeight();
break; }
}
@@ -1925,8 +2064,17 @@ bool QQuickTableViewPrivate::updateTable()
void QQuickTableViewPrivate::fixup(QQuickFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent)
{
- if (scheduledRebuildOptions || rebuildState != RebuildState::Done)
+ if (inUpdateContentSize) {
+ // We update the content size dynamically as we load and unload edges.
+ // Unfortunately, this also triggers a call to this function. The base
+ // implementation will do things like start a momentum animation or move
+ // the content view somewhere else, which causes glitches. This can
+ // especially happen if flicking on one of the syncView children, which triggers
+ // an update to our content size. In that case, the base implementation don't know
+ // that the view is being indirectly dragged, and will therefore do strange things as
+ // it tries to 'fixup' the geometry. So we use a guard to prevent this from happening.
return;
+ }
QQuickFlickablePrivate::fixup(data, minExtent, maxExtent);
}
@@ -2011,13 +2159,11 @@ void QQuickTableViewPrivate::syncWithPendingChanges()
Q_Q(QQuickTableView);
viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
- // Sync rebuild options first, in case we schedule a rebuild from one of the
- // other sync calls above. If so, we need to start a new rebuild from the top.
- syncRebuildOptions();
-
syncModel();
syncDelegate();
syncSyncView();
+
+ syncRebuildOptions();
}
void QQuickTableViewPrivate::syncRebuildOptions()
@@ -2107,7 +2253,6 @@ void QQuickTableViewPrivate::syncSyncView()
assignedSyncView->d_func()->syncChildren.append(q);
scheduledRebuildOptions |= RebuildOption::ViewportOnly;
- q->polish();
}
syncView = assignedSyncView;
@@ -2120,6 +2265,21 @@ void QQuickTableViewPrivate::syncSyncView()
q->setColumnSpacing(syncView->columnSpacing());
if (syncVertically)
q->setRowSpacing(syncView->rowSpacing());
+
+ if (syncView && loadedItems.isEmpty() && !tableSize.isEmpty()) {
+ // When we have a syncView, we can sometimes temporarily end up with no loaded items.
+ // This can happen if the syncView has a model with more rows or columns than us, in
+ // which case the viewport can end up in a place where we have no rows or columns to
+ // show. In that case, check now if the viewport has been flicked back again, and
+ // that we can rebuild the table with a visible top-left cell.
+ const auto syncView_d = syncView->d_func();
+ if (!syncView_d->loadedItems.isEmpty()) {
+ if (syncHorizontally && syncView_d->leftColumn() <= tableSize.width() - 1)
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::ViewportOnly;
+ else if (syncVertically && syncView_d->topRow() <= tableSize.height() - 1)
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::ViewportOnly;
+ }
+ }
}
void QQuickTableViewPrivate::connectToModel()
@@ -2254,7 +2414,6 @@ void QQuickTableViewPrivate::modelResetCallback()
void QQuickTableViewPrivate::scheduleRebuildIfFastFlick()
{
Q_Q(QQuickTableView);
-
// If the viewport has moved more than one page vertically or horizontally, we switch
// strategy from refilling edges around the current table to instead rebuild the table
// from scratch inside the new viewport. This will greatly improve performance when flicking
@@ -2345,6 +2504,26 @@ QQuickTableView::QQuickTableView(QQuickTableViewPrivate &dd, QQuickItem *parent)
setFlag(QQuickItem::ItemIsFocusScope);
}
+qreal QQuickTableView::minXExtent() const
+{
+ return QQuickFlickable::minXExtent() - d_func()->origin.x();
+}
+
+qreal QQuickTableView::maxXExtent() const
+{
+ return QQuickFlickable::maxXExtent() - d_func()->endExtent.width();
+}
+
+qreal QQuickTableView::minYExtent() const
+{
+ return QQuickFlickable::minYExtent() - d_func()->origin.y();
+}
+
+qreal QQuickTableView::maxYExtent() const
+{
+ return QQuickFlickable::maxYExtent() - d_func()->endExtent.height();
+}
+
int QQuickTableView::rows() const
{
return d_func()->tableSize.height();
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 3d46221574..3b113efa4f 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -147,6 +147,11 @@ private:
Q_DISABLE_COPY(QQuickTableView)
Q_DECLARE_PRIVATE(QQuickTableView)
+ qreal minXExtent() const override;
+ qreal maxXExtent() const override;
+ qreal minYExtent() const override;
+ qreal maxYExtent() const override;
+
Q_PRIVATE_SLOT(d_func(), void _q_componentFinalized())
};
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 7f2aee9105..b66ac66dec 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -251,6 +251,9 @@ public:
QRectF loadedTableOuterRect;
QRectF loadedTableInnerRect;
+ QPointF origin = QPointF(0, 0);
+ QSizeF endExtent = QSizeF(0, 0);
+
QRectF viewportRect = QRectF(0, 0, -1, -1);
QSize tableSize;
@@ -272,6 +275,7 @@ public:
bool syncHorizontally = false;
bool inSetLocalViewportPos = false;
bool inSyncViewportPosRecursive = false;
+ bool inUpdateContentSize = false;
QJSValue rowHeightProvider;
QJSValue columnWidthProvider;
@@ -337,7 +341,6 @@ public:
bool updateTableRecursive();
bool updateTable();
- void relayoutTable();
void relayoutTableItems();
void layoutVerticalEdge(Qt::Edge tableEdge);
@@ -350,7 +353,7 @@ public:
void updateAverageEdgeSize();
void forceLayout();
- void enforceTableAtOrigin();
+ void updateExtents();
void syncLoadedTableRectFromLoadedTable();
void syncLoadedTableFromLoadRequest();
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 6d343a91ce..ae849aeb4b 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1653,13 +1653,17 @@ void QQuickText::setText(const QString &n)
if (d->text == n)
return;
- d->richText = d->format == RichText;
+ d->markdownText = d->format == MarkdownText;
+ d->richText = d->format == RichText || d->markdownText;
d->styledText = d->format == StyledText || (d->format == AutoText && Qt::mightBeRichText(n));
d->text = n;
if (isComponentComplete()) {
if (d->richText) {
d->ensureDoc();
- d->extra->doc->setText(n);
+ if (d->markdownText)
+ d->extra->doc->setMarkdownText(n);
+ else
+ d->extra->doc->setText(n);
d->rightToLeftText = d->extra->doc->toPlainText().isRightToLeft();
} else {
d->clearFormats();
@@ -2146,7 +2150,8 @@ void QQuickText::setTextFormat(TextFormat format)
return;
d->format = format;
bool wasRich = d->richText;
- d->richText = format == RichText;
+ d->markdownText = format == MarkdownText;
+ d->richText = format == RichText || d->markdownText;
d->styledText = format == StyledText || (format == AutoText && Qt::mightBeRichText(d->text));
if (isComponentComplete()) {
@@ -2687,7 +2692,10 @@ void QQuickText::componentComplete()
if (d->updateOnComponentComplete) {
if (d->richText) {
d->ensureDoc();
- d->extra->doc->setText(d->text);
+ if (d->markdownText)
+ d->extra->doc->setMarkdownText(d->text);
+ else
+ d->extra->doc->setText(d->text);
d->rightToLeftText = d->extra->doc->toPlainText().isRightToLeft();
} else {
d->rightToLeftText = d->text.isRightToLeft();
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 1af60051fb..45f387cb12 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -121,6 +121,7 @@ public:
Q_ENUM(TextStyle)
enum TextFormat { PlainText = Qt::PlainText,
RichText = Qt::RichText,
+ MarkdownText = Qt::MarkdownText,
AutoText = Qt::AutoText,
StyledText = 4 };
Q_ENUM(TextFormat)
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index efa45e0958..c01998b100 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -161,6 +161,7 @@ public:
bool updateOnComponentComplete:1;
bool richText:1;
bool styledText:1;
+ bool markdownText:1;
bool widthExceeded:1;
bool heightExceeded:1;
bool internalWidthUpdate:1;
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index a7a90c9134..caef24293a 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -1297,6 +1297,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|| e->replacementLength() > 0;
bool forceSelectionChanged = false;
+ int oldCursorPos = cursor.position();
cursor.beginEditBlock();
if (isGettingInput) {
@@ -1365,6 +1366,8 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QTextCursorPrivate *cursor_d = QTextCursorPrivate::getPrivate(&cursor);
if (cursor_d)
cursor_d->setX();
+ if (cursor.position() != oldCursorPos)
+ emit q->cursorPositionChanged();
q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged || isGettingInput);
selectionChanged(forceSelectionChanged);
}
diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp
index 06ac5804c4..021bbca0f6 100644
--- a/src/quick/items/qquicktextdocument.cpp
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -237,6 +237,14 @@ void QQuickTextDocumentWithImageResources::setText(const QString &text)
#endif
}
+#if QT_CONFIG(textmarkdownreader)
+void QQuickTextDocumentWithImageResources::setMarkdownText(const QString &text)
+{
+ clearResources();
+ QTextDocument::setMarkdown(text);
+}
+#endif
+
QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextdocument_p.h b/src/quick/items/qquicktextdocument_p.h
index 1218b12b89..9c5152d442 100644
--- a/src/quick/items/qquicktextdocument_p.h
+++ b/src/quick/items/qquicktextdocument_p.h
@@ -73,6 +73,9 @@ public:
virtual ~QQuickTextDocumentWithImageResources();
void setText(const QString &);
+#if QT_CONFIG(textmarkdownreader)
+ void setMarkdownText(const QString &);
+#endif
int resourcesLoading() const { return outstanding; }
QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) override;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 6b4b118eb7..b299e7c92f 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -2298,7 +2298,6 @@ void QQuickTextEditPrivate::init()
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SIGNAL(cursorPositionChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString)));
- qmlobject_connect(control, QQuickTextControl, SIGNAL(linkHovered(QString)), q, QQuickTextEdit, SIGNAL(linkHovered(QString)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(overwriteModeChanged(bool)), q, QQuickTextEdit, SIGNAL(overwriteModeChanged(bool)));
qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
qmlobject_connect(control, QQuickTextControl, SIGNAL(preeditTextChanged()), q, QQuickTextEdit, SIGNAL(preeditTextChanged()));
@@ -2310,6 +2309,7 @@ void QQuickTextEditPrivate::init()
qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(imagesLoaded()), q, QQuickTextEdit, SLOT(updateSize()));
QObject::connect(document, &QQuickTextDocumentWithImageResources::contentsChange, q, &QQuickTextEdit::q_contentsChange);
QObject::connect(document->documentLayout(), &QAbstractTextDocumentLayout::updateBlock, q, &QQuickTextEdit::invalidateBlock);
+ QObject::connect(control, &QQuickTextControl::linkHovered, q, &QQuickTextEdit::q_linkHovered);
document->setDefaultFont(font);
document->setDocumentMargin(textMargin);
@@ -2317,6 +2317,9 @@ void QQuickTextEditPrivate::init()
document->setUndoRedoEnabled(true);
updateDefaultTextOption();
q->updateSize();
+#if QT_CONFIG(cursor)
+ q->setCursor(Qt::IBeamCursor);
+#endif
}
void QQuickTextEditPrivate::resetInputMethod()
@@ -2584,6 +2587,20 @@ void QQuickTextEdit::updateCursor()
}
}
+void QQuickTextEdit::q_linkHovered(const QString &link)
+{
+ Q_D(QQuickTextEdit);
+ emit linkHovered(link);
+#if QT_CONFIG(cursor)
+ if (link.isEmpty()) {
+ setCursor(d->cursorToRestoreAfterHover);
+ } else if (cursor().shape() != Qt::PointingHandCursor) {
+ d->cursorToRestoreAfterHover = cursor().shape();
+ setCursor(Qt::PointingHandCursor);
+ }
+#endif
+}
+
void QQuickTextEdit::q_updateAlignment()
{
Q_D(QQuickTextEdit);
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index 7a847ffeae..259a614d6b 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -374,6 +374,7 @@ private Q_SLOTS:
void updateWholeDocument();
void invalidateBlock(const QTextBlock &block);
void updateCursor();
+ void q_linkHovered(const QString &link);
void q_updateAlignment();
void updateSize();
void triggerPreprocess();
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 46d3d5ff6b..389ce3175c 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -207,6 +207,7 @@ public:
Qt::InputMethodHints inputMethodHints;
#endif
UpdateType updateType;
+ Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor;
bool dirty : 1;
bool richText : 1;
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index a1b5eb1faf..32478ba375 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -1011,6 +1011,17 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
break;
};
+ switch (block.blockFormat().marker()) {
+ case QTextBlockFormat::Checked:
+ listItemBullet = QChar(0x2612); // Checked checkbox
+ break;
+ case QTextBlockFormat::Unchecked:
+ listItemBullet = QChar(0x2610); // Unchecked checkbox
+ break;
+ case QTextBlockFormat::NoMarker:
+ break;
+ }
+
QSizeF size(fontMetrics.horizontalAdvance(listItemBullet), fontMetrics.height());
qreal xoff = fontMetrics.horizontalAdvance(QLatin1Char(' '));
if (block.textDirection() == Qt::LeftToRight)
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index f3a2b07620..5dcd101462 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -64,6 +64,7 @@
#include <QtGui/qpainter.h>
#include <QtGui/qevent.h>
#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpa/qplatformtheme.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractanimation.h>
#include <QtCore/QLibraryInfo>
@@ -632,25 +633,28 @@ static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::Touc
return me;
}
-bool QQuickWindowPrivate::checkIfDoubleClicked(ulong newPressEventTimestamp)
+bool QQuickWindowPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos)
{
- bool doubleClicked;
+ bool doubleClicked = false;
+
+ if (touchMousePressTimestamp > 0) {
+ QPoint distanceBetweenPresses = newPressPos - touchMousePressPos;
+ const int doubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt();
+ doubleClicked = (qAbs(distanceBetweenPresses.x()) <= doubleTapDistance) && (qAbs(distanceBetweenPresses.y()) <= doubleTapDistance);
- if (touchMousePressTimestamp == 0) {
- // just initialize the variable
- touchMousePressTimestamp = newPressEventTimestamp;
- doubleClicked = false;
- } else {
- ulong timeBetweenPresses = newPressEventTimestamp - touchMousePressTimestamp;
- ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->
- mouseDoubleClickInterval());
- doubleClicked = timeBetweenPresses < doubleClickInterval;
if (doubleClicked) {
- touchMousePressTimestamp = 0;
- } else {
- touchMousePressTimestamp = newPressEventTimestamp;
+ ulong timeBetweenPresses = newPressEventTimestamp - touchMousePressTimestamp;
+ ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->
+ mouseDoubleClickInterval());
+ doubleClicked = timeBetweenPresses < doubleClickInterval;
}
}
+ if (doubleClicked) {
+ touchMousePressTimestamp = 0;
+ } else {
+ touchMousePressTimestamp = newPressEventTimestamp;
+ touchMousePressPos = newPressPos;
+ }
return doubleClicked;
}
@@ -707,7 +711,9 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
if (auto pointerEventPoint = pointerEvent->pointById(p.id()))
pointerEventPoint->setGrabberItem(item);
- if (checkIfDoubleClicked(event->timestamp())) {
+ if (checkIfDoubleTapped(event->timestamp(), p.screenPos().toPoint())) {
+ // since we synth the mouse event from from touch, we respect the
+ // QPlatformTheme::TouchDoubleTapDistance instead of QPlatformTheme::MouseDoubleClickDistance
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event.data(), item, false));
QCoreApplication::sendEvent(item, mouseDoubleClick.data());
event->setAccepted(mouseDoubleClick->isAccepted());
@@ -722,6 +728,12 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
// Touch point was there before and moved
} else if (touchMouseDevice == device && p.id() == touchMouseId) {
if (p.state() & Qt::TouchPointMoved) {
+ if (touchMousePressTimestamp != 0) {
+ const int doubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt();
+ const QPoint moveDelta = p.screenPos().toPoint() - touchMousePressPos;
+ if (moveDelta.x() >= doubleTapDistance || moveDelta.y() >= doubleTapDistance)
+ touchMousePressTimestamp = 0; // Got dragged too far, dismiss the double tap
+ }
if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event.data(), mouseGrabberItem, false));
QCoreApplication::sendEvent(item, me.data());
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 5a3807b24f..63760a3b68 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -135,8 +135,9 @@ public:
#endif
int touchMouseId;
QQuickPointerDevice *touchMouseDevice;
- bool checkIfDoubleClicked(ulong newPressEventTimestamp);
+ bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
ulong touchMousePressTimestamp;
+ QPoint touchMousePressPos; // in screen coordiantes
void cancelTouchMouseSynthesis();
// Mouse positions are saved in widget coordinates
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index d9ed25c099..53648e352a 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -393,7 +393,7 @@ QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, Q
void QSGRenderContext::textureFactoryDestroyed(QObject *o)
{
m_mutex.lock();
- m_texturesToDelete << m_textures.take(static_cast<QQuickTextureFactory *>(o));
+ m_texturesToDelete << m_textures.take(o);
m_mutex.unlock();
}
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 6d70d7ef6b..282ce828af 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -194,7 +194,7 @@ protected:
QPointer<QSGContext> m_sg;
QMutex m_mutex;
- QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
+ QHash<QObject *, QSGTexture *> m_textures;
QSet<QSGTexture *> m_texturesToDelete;
QHash<QString, QSGDistanceFieldGlyphCache *> m_glyphCaches;
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 8121b4559e..9ad0a77318 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -41,6 +41,7 @@
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qbuffer.h>
+#include <QtCore/qendian.h>
#include <QtQml/qqmlfile.h>
#include <QtGui/private/qdistancefield_p.h>
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
index 37a89c70b9..cfa1c1dad2 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -53,6 +53,7 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgbasicglyphnode_p.h>
+#include <qlinkedlist.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index d739c8a017..776e7ab59a 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -201,14 +201,14 @@ public:
QPointer<QObject> object;
QList<const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
bool decoded : 1;
bool restore : 1;
bool isExplicit : 1;
void decode();
- void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding);
+ void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding);
class ExpressionChange {
public:
@@ -236,7 +236,7 @@ public:
QQmlProperty property(const QString &);
};
-void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
error(compilationUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects."));
@@ -266,7 +266,7 @@ void QQuickPropertyChangesPrivate::decode()
decoded = true;
}
-void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
Q_Q(QQuickPropertyChanges);
@@ -314,7 +314,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
QQmlBinding::Identifier id = QQmlBinding::Invalid;
if (!binding->isTranslationBinding()) {
- expression = binding->valueAsString(compilationUnit.data());
+ expression = compilationUnit->bindingValueAsString(binding);
id = binding->value.compiledScriptIndex;
}
expressions << ExpressionChange(propertyName, binding, id, expression, url, line, column);
@@ -328,10 +328,10 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
case QV4::CompiledData::Binding::Type_TranslationById:
Q_UNREACHABLE();
case QV4::CompiledData::Binding::Type_String:
- var = binding->valueAsString(compilationUnit.data());
+ var = compilationUnit->bindingValueAsString(binding);
break;
case QV4::CompiledData::Binding::Type_Number:
- var = binding->valueAsNumber(compilationUnit->constants);
+ var = compilationUnit->bindingValueAsNumber(binding);
break;
case QV4::CompiledData::Binding::Type_Boolean:
var = binding->valueAsBoolean();
@@ -346,13 +346,13 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
properties << qMakePair(propertyName, var);
}
-void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
+void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
for (int ii = 0; ii < props.count(); ++ii)
verifyList(compilationUnit, props.at(ii));
}
-void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQuickPropertyChangesPrivate *p =
static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 74fe511d6e..82a6ebffac 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -101,10 +101,10 @@ public:
QQuickPropertyChangesParser()
: QQmlCustomParser(AcceptsAttachedProperties) {}
- void verifyList(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
+ void verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
+ void applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index d8daec2f07..b53949d21c 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -130,6 +130,8 @@ QQuickStateGroup::~QQuickStateGroup()
Q_D(const QQuickStateGroup);
for (int i = 0; i < d->states.count(); ++i)
d->states.at(i)->setStateGroup(nullptr);
+ if (d->nullState)
+ d->nullState->setStateGroup(nullptr);
}
QList<QQuickState *> QQuickStateGroup::states() const
diff --git a/src/src.pro b/src/src.pro
index bd634247e7..b1e0a72c9f 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -7,6 +7,8 @@ SUBDIRS += \
qml \
qmlmodels
+qtConfig(qml-worker-script): \
+ SUBDIRS += qmlworkerscript
qtHaveModule(gui):qtConfig(qml-animation) {
SUBDIRS += \
diff --git a/sync.profile b/sync.profile
index b6a1825eed..ec880f2d67 100644
--- a/sync.profile
+++ b/sync.profile
@@ -8,6 +8,7 @@
"QtPacketProtocol" => "$basedir/src/plugins/qmltooling/packetprotocol",
"QtQmlDebug" => "$basedir/src/qmldebug",
"QtQmlModels" => "$basedir/src/qmlmodels",
+ "QtQmlWorkerScript" => "$basedir/src/qmlworkerscript",
);
%inject_headers = (
"$basedir/src/qml" => [ "^qqmljsgrammar_p.h", "^qqmljsparser_p.h" ],
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
index cbe3be2e70..33efcb4da4 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
+++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
@@ -509,7 +509,7 @@ static bool executeTest(const QByteArray &data, bool runAsModule = false, const
QVector<QUrl> modulesToLoad = { rootModuleUrl };
while (!modulesToLoad.isEmpty()) {
QUrl url = modulesToLoad.takeFirst();
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> module;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> module;
QFile f(url.toLocalFile());
if (f.open(QIODevice::ReadOnly)) {
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index e86b7bf5fe..c215e9620d 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -33,6 +33,7 @@
#include <private/qv4engine_p.h>
#include <private/qv4codegen_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qv4executablecompilationunit_p.h>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlFileSelector>
@@ -118,7 +119,8 @@ struct TestCompiler
{
closeMapping();
testFilePath = baseDirectory + QStringLiteral("/test.qml");
- cacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
+ cacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(testFilePath));
mappedFile.setFileName(cacheFilePath);
}
@@ -185,8 +187,10 @@ struct TestCompiler
bool verify()
{
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Compiler::Codegen::createUnitForLoading();
- return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), QFileInfo(testFilePath).lastModified(), &lastErrorString);
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
+ = QV4::ExecutableCompilationUnit::create();
+ return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath),
+ QFileInfo(testFilePath).lastModified(), &lastErrorString);
}
void closeMapping()
@@ -263,8 +267,9 @@ void tst_qmldiskcache::loadLocalAsFallback()
f.write(reinterpret_cast<const char *>(&unit), sizeof(unit));
}
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Compiler::Codegen::createUnitForLoading();
- bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath), QFileInfo(testCompiler.testFilePath).lastModified(),
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> unit = QV4::ExecutableCompilationUnit::create();
+ bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath),
+ QFileInfo(testCompiler.testFilePath).lastModified(),
&testCompiler.lastErrorString);
QVERIFY2(loaded, qPrintable(testCompiler.lastErrorString));
QCOMPARE(unit->objectCount(), 1);
@@ -323,7 +328,10 @@ void tst_qmldiskcache::regenerateAfterChange()
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(0);
QCOMPARE(quint32(obj->nBindings), quint32(2));
QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Number));
- QCOMPARE(obj->bindingTable()->valueAsNumber(reinterpret_cast<const QV4::Value *>(testUnit->constants())), double(42));
+
+ QCOMPARE(reinterpret_cast<const QV4::Value *>(testUnit->constants())
+ [obj->bindingTable()->value.constantValueIndex].doubleValue(),
+ double(42));
QCOMPARE(quint32(testUnit->functionTableSize), quint32(1));
@@ -572,7 +580,8 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 42);
- QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)));
+ QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(testFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -587,7 +596,8 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 100);
- QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(selectedTestFilePath)));
+ QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(selectedTestFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
}
@@ -737,7 +747,8 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes()
QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData());
QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData());
- const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
+ const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -815,7 +826,8 @@ void tst_qmldiskcache::singletonDependency()
QCOMPARE(obj->property("value").toInt(), 42);
}
- const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
+ const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -872,7 +884,8 @@ void tst_qmldiskcache::cppRegisteredSingletonDependency()
QCOMPARE(value.toInt(), 42);
}
- const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
+ const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
new file mode 100644
index 0000000000..b42f975fe0
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQml 2.14
+
+Rectangle {
+ height: 400
+ width: 400
+
+ Rectangle {
+ property bool when: true
+
+ id: myItem
+ objectName: "myItem"
+ height: 300
+ width: 200
+ }
+
+ property var boundValue: 100
+
+ Binding {
+ restoreMode: Binding.RestoreValue
+ objectName: "theBinding"
+ target: myItem
+ property: "height"
+ when: myItem.when
+ value: boundValue
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
new file mode 100644
index 0000000000..1f63457ab6
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQml 2.14
+
+Rectangle {
+ height: 400
+ width: 400
+
+ Rectangle {
+ property bool when: true
+
+ id: myItem
+ objectName: "myItem"
+ height: 300
+ width: 200
+ property var foo: 42
+ }
+
+ property var boundValue: 13
+
+ Binding {
+ restoreMode: Binding.RestoreBindingOrValue
+ objectName: "theBinding"
+ target: myItem
+ property: "foo"
+ when: myItem.when
+ value: boundValue
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
new file mode 100644
index 0000000000..f34c3b40cf
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQml 2.14
+
+Rectangle {
+ height: 400
+ width: 400
+
+ Rectangle {
+ property bool when: true
+
+ id: myItem
+ objectName: "myItem"
+ height: 300
+ width: 200
+ property var foo: original
+ property bool fooCheck: foo === original && foo.bar() === 42
+ }
+
+ property var original: ({ bar: function() { return 42 } })
+
+ property var boundValue: 13
+
+ Binding {
+ restoreMode: Binding.RestoreBinding
+ objectName: "theBinding"
+ target: myItem
+ property: "foo"
+ when: myItem.when
+ value: boundValue
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 34cf21024d..717fd5dbd1 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -42,6 +42,9 @@ private slots:
void binding();
void whenAfterValue();
void restoreBinding();
+ void restoreBindingValue();
+ void restoreBindingVarValue();
+ void restoreBindingJSValue();
void restoreBindingWithLoop();
void restoreBindingWithoutCrash();
void deletedObject();
@@ -134,6 +137,78 @@ void tst_qqmlbinding::restoreBinding()
delete rect;
}
+void tst_qqmlbinding::restoreBindingValue()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restoreBinding2.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ QVERIFY(!rect.isNull());
+
+ auto myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
+ QVERIFY(myItem != nullptr);
+
+ QCOMPARE(myItem->height(), 100);
+ myItem->setProperty("when", QVariant(false));
+ QCOMPARE(myItem->height(), 300); // make sure the original value was restored
+
+ myItem->setProperty("when", QVariant(true));
+ QCOMPARE(myItem->height(), 100); // make sure the value specified in Binding is set
+ rect->setProperty("boundValue", 200);
+ QCOMPARE(myItem->height(), 200); // make sure the changed binding value is set
+ myItem->setProperty("when", QVariant(false));
+ // make sure that the original value is back, not e.g. the value from before the
+ // change (i.e. 100)
+ QCOMPARE(myItem->height(), 300);
+}
+
+void tst_qqmlbinding::restoreBindingVarValue()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restoreBinding3.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ QVERIFY(!rect.isNull());
+
+ auto myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
+ QVERIFY(myItem != nullptr);
+
+ QCOMPARE(myItem->property("foo"), 13);
+ myItem->setProperty("when", QVariant(false));
+ QCOMPARE(myItem->property("foo"), 42); // make sure the original value was restored
+
+ myItem->setProperty("when", QVariant(true));
+ QCOMPARE(myItem->property("foo"), 13); // make sure the value specified in Binding is set
+ rect->setProperty("boundValue", 31337);
+ QCOMPARE(myItem->property("foo"), 31337); // make sure the changed binding value is set
+ myItem->setProperty("when", QVariant(false));
+ // make sure that the original value is back, not e.g. the value from before the
+ // change (i.e. 100)
+ QCOMPARE(myItem->property("foo"), 42);
+}
+
+void tst_qqmlbinding::restoreBindingJSValue()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restoreBinding4.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ QVERIFY(!rect.isNull());
+
+ auto myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem"));
+ QVERIFY(myItem != nullptr);
+
+ QCOMPARE(myItem->property("fooCheck"), false);
+ myItem->setProperty("when", QVariant(false));
+ QCOMPARE(myItem->property("fooCheck"), true); // make sure the original value was restored
+
+ myItem->setProperty("when", QVariant(true));
+ QCOMPARE(myItem->property("fooCheck"), false); // make sure the value specified in Binding is set
+ rect->setProperty("boundValue", 31337);
+ QCOMPARE(myItem->property("fooCheck"), false); // make sure the changed binding value is set
+ myItem->setProperty("when", QVariant(false));
+ // make sure that the original value is back, not e.g. the value from before the change
+ QCOMPARE(myItem->property("fooCheck"), true);
+
+}
+
void tst_qqmlbinding::restoreBindingWithLoop()
{
QQmlEngine engine;
diff --git a/tests/auto/qml/qqmlengine/data/CachedGetterLookup.qml b/tests/auto/qml/qqmlengine/data/CachedGetterLookup.qml
new file mode 100644
index 0000000000..1a2a7ff341
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/CachedGetterLookup.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.12
+
+QtObject {
+ Component.onCompleted: {
+ // create getter
+ var getFoo = function(o) { return o.foo; }
+
+ // create two diffrent shapes for x,y
+ var x = { foo:1 , bar:2 }
+ var y = { bar:2 , foo:1 }
+
+ // initialize inline cache with getFoo
+ getFoo(x);
+ getFoo(y);
+
+ // hit getter lookup with string "crash"
+ getFoo('crash');
+ }
+}
+
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index b9cb6b70d2..0cb6753020 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -81,6 +81,7 @@ private slots:
void cppSignalAndEval();
void singletonInstance();
void aggressiveGc();
+ void cachedGetterLookup_qtbug_75335();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -1056,6 +1057,16 @@ void tst_qqmlengine::aggressiveGc()
qputenv("QV4_MM_AGGRESSIVE_GC", origAggressiveGc);
}
+void tst_qqmlengine::cachedGetterLookup_qtbug_75335()
+{
+ QQmlEngine engine;
+ const QUrl testUrl = testFileUrl("CachedGetterLookup.qml");
+ QQmlComponent component(&engine, testUrl);
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/bareQmlImport.errors.txt b/tests/auto/qml/qqmllanguage/data/bareQmlImport.errors.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/bareQmlImport.errors.txt
diff --git a/tests/auto/qml/qqmllanguage/data/bareQmlImport.qml b/tests/auto/qml/qqmllanguage/data/bareQmlImport.qml
new file mode 100644
index 0000000000..3567cdb5a3
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/bareQmlImport.qml
@@ -0,0 +1,6 @@
+import QML 1.0
+QtObject {
+ property Component component: Component {
+ QtObject {}
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index f9a6ee8e5a..d6215307bf 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -125,7 +125,7 @@ QVariant myCustomVariantTypeConverter(const QString &data)
}
-void CustomBindingParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void CustomBindingParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
Q_ASSERT(customBinding);
@@ -154,7 +154,7 @@ void CustomBinding::componentComplete()
}
}
-void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
if (bindings.count() != 1) {
error(bindings.first(), QStringLiteral("Custom parser invoked incorrectly for unit test"));
@@ -184,7 +184,7 @@ void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer<QV4::Compil
}
}
-void SimpleObjectCustomParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &bindings)
+void SimpleObjectCustomParser::applyBindings(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &bindings)
{
SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
Q_ASSERT(o);
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index bb6e9582c2..0618d2b20f 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -781,15 +781,15 @@ class MyCustomParserType : public QObject
class MyCustomParserTypeParser : public QQmlCustomParser
{
public:
- virtual void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
};
class EnumSupportingCustomParser : public QQmlCustomParser
{
public:
- virtual void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
- virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
};
class MyParserStatus : public QObject, public QQmlParserStatus
@@ -1275,15 +1275,15 @@ public:
void setTarget(QObject *newTarget) { m_target = newTarget; }
QPointer<QObject> m_target;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding*> bindings;
QByteArray m_bindingData;
};
class CustomBindingParser : public QQmlCustomParser
{
- virtual void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
};
class SimpleObjectWithCustomParser : public QObject
@@ -1328,8 +1328,8 @@ private:
class SimpleObjectCustomParser : public QQmlCustomParser
{
- virtual void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &);
};
class RootObjectInCreationTester : public QObject
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index b97c75e2ce..8cbb39974e 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -620,6 +620,8 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("fuzzed.1") << "fuzzed.1.qml" << "fuzzed.1.errors.txt" << false;
QTest::newRow("fuzzed.2") << "fuzzed.2.qml" << "fuzzed.2.errors.txt" << false;
+
+ QTest::newRow("bareQmlImport") << "bareQmlImport.qml" << "bareQmlImport.errors.txt" << false;
}
@@ -2223,7 +2225,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize));
memcpy(qmlUnit, readOnlyQmlUnit, readOnlyQmlUnit->unitSize);
qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = td->compilationUnit();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
compilationUnit->setUnitData(qmlUnit);
const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0);
@@ -2233,9 +2235,9 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
const QV4::CompiledData::Binding *binding = rootObject->bindingTable() + i;
if (compilationUnit->stringAt(binding->propertyNameIndex) != QString("scriptProperty"))
continue;
- QCOMPARE(binding->valueAsScriptString(compilationUnit.data()), QString("intProperty"));
+ QCOMPARE(compilationUnit->bindingValueAsScriptString(binding), QString("intProperty"));
const_cast<QV4::CompiledData::Binding*>(binding)->stringIndex = 0; // empty string index
- QVERIFY(binding->valueAsScriptString(compilationUnit.data()).isEmpty());
+ QVERIFY(compilationUnit->bindingValueAsScriptString(binding).isEmpty());
break;
}
QVERIFY(i < rootObject->nBindings);
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index 809a9bd9db..3b17df9872 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -85,7 +85,8 @@ void tst_qqmltranslation::translation()
<< QStringLiteral("disambiguation")
<< QStringLiteral("singular") << QStringLiteral("plural");
- const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0);
+ const QV4::CompiledData::Object *rootObject
+ = compilationUnit->qmlData->objectAt(/*root object*/0);
const QV4::CompiledData::Binding *binding = rootObject->bindingTable();
for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) {
const QString propertyName = compilationUnit->stringAt(binding->propertyNameIndex);
@@ -139,7 +140,8 @@ void tst_qqmltranslation::idTranslation()
QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit();
QVERIFY(compilationUnit);
- const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0);
+ const QV4::CompiledData::Object *rootObject
+ = compilationUnit->qmlData->objectAt(/*root object*/0);
const QV4::CompiledData::Binding *binding = rootObject->bindingTable();
for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) {
const QString propertyName = compilationUnit->stringAt(binding->propertyNameIndex);
diff --git a/tests/auto/qml/qquickworkerscript/qquickworkerscript.pro b/tests/auto/qml/qquickworkerscript/qquickworkerscript.pro
index be8b9089a2..f58fd4543f 100644
--- a/tests/auto/qml/qquickworkerscript/qquickworkerscript.pro
+++ b/tests/auto/qml/qquickworkerscript/qquickworkerscript.pro
@@ -8,4 +8,4 @@ include (../../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private testlib
+QT += core-private gui-private qml-private testlib qmlworkerscript-private
diff --git a/tests/auto/qmltest/statemachine/tst_parallelmachine.qml b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml
index be7d73fbe5..eb996c7718 100644
--- a/tests/auto/qmltest/statemachine/tst_parallelmachine.qml
+++ b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml
@@ -32,25 +32,29 @@ import QtQml.StateMachine 1.0
TestCase {
StateMachine {
id: myStateMachine
- childMode: State.ParallelStates
+ initialState: rootState
State {
- id: childState1
+ id: rootState
childMode: State.ParallelStates
State {
- id: childState11
+ id: childState1
+ childMode: State.ParallelStates
+